> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twenty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Ротация ключей

У Twenty есть два независимых семейства ключей:

* **Ключи подписи JWT** — асимметричные пары ключей ES256 (с тегами `kid`), хранятся в `core."signingKey"` и используются для подписи и проверки access/refresh-токенов.
* **Ключ шифрования данных на диске** — `ENCRYPTION_KEY`, используется для шифрования OAuth-токенов, переменных приложения, закрытых ключей подписи, конфиденциальных значений конфигурации и TOTP-секретов внутри оболочки `enc:v2:`.

`APP_SECRET` — устаревший секрет, сохранённый для обратной совместимости: когда `ENCRYPTION_KEY` не установлен, он используется как резерв для шифрования данных на диске/сеансовых cookie и по-прежнему проверяет ранее выданные HS256 access-токены. Он будет объявлен устаревшим.

## Ключи подписи JWT

Каждый ключ содержит `publicKey` (хранится бессрочно, чтобы можно было проверять ранее выданные токены), зашифрованный `privateKey` (используется только пока ключ является текущим), флаг `isCurrent` (в каждый момент времени ровно одна строка) и необязательное поле `revokedAt`.

### Выполнить ротацию текущего ключа

Установите `SIGNING_KEY_ROTATION_DAYS`, чтобы включить эту опцию: ежедневный cron затем будет выпускать новый текущий ключ, как только существующий ключ станет старше этого порогового значения. Предыдущие ключи *не* отзываются, поэтому токены, подписанные ими, продолжают успешно проходить проверку. Оставьте переменную не заданной, чтобы отключить автоматическую ротацию.

<Note>Автоматическая ротация доступна, начиная с версии v2.6+.</Note>

### Отозвать ключ (только при утечке / в экстренных случаях)

**Settings → Admin Panel → Signing keys → Revoke** в нетекущей строке. Стирает зашифрованный закрытый материал, устанавливает `revokedAt` и отклоняет все существующие токены, подписанные с этим `kid`.

## Выполнить ротацию `ENCRYPTION_KEY`

<Note>Команда `secret-encryption:rotate`, описанная ниже, поставляется начиная с v2.6+.</Note>

Каждое зашифрованное значение оборачивается как `enc:v2:\<keyId>:\<payload>`, где `\<keyId>` — это 8-символьный шестнадцатеричный префикс, полученный из исходного ключа. Ротация выполняется онлайн и может быть возобновлена.

1. **Сгенерировать новый ключ**: `openssl rand -base64 32`.

2. **Настройте оба ключа параллельно** в `.env`, затем перезапустите:
   ```ini theme={null}
   ENCRYPTION_KEY=NEW_VALUE
   FALLBACK_ENCRYPTION_KEY=OLD_VALUE
   ```
   Новые записи используют новый ключ, существующие строки по-прежнему расшифровываются через резервный ключ.

3. **Повторно зашифровать существующие строки**:

   ```bash theme={null}
   docker exec -it {server_container} yarn command:prod secret-encryption:rotate
   ```

   Команда обходит шесть разделов (`connected-account-tokens`, `application-variable`, `application-registration-variable`, `signing-key-private-keys`, `sensitive-config-storage`, `totp-secrets`). SQL-фильтр пропускает строки, которые уже находятся на новом `\<keyId>`, поэтому команда идемпотентна: прерывайте и запускайте повторно по мере необходимости. Завершает работу с ненулевым кодом, если какая-либо строка завершилась с ошибкой — запустите повторно, чтобы повторить попытку.

   | Флаг                    | Описание                                                           |
   | ----------------------- | ------------------------------------------------------------------ |
   | `-s, --site \<site>`    | Ограничить одним сайтом.                                           |
   | `-b, --batch-size \<n>` | Строк в партии (по умолчанию `200`, максимум `5000`).              |
   | `-d, --dry-run`         | Расшифровать + повторно зашифровать в памяти, пропустить `UPDATE`. |

4. **Удалите резервный ключ** после того, как `--dry-run` покажет ноль оставшихся строк: удалите `FALLBACK_ENCRYPTION_KEY` и перезапустите.

## Устаревшая поддержка `APP_SECRET`

Более старые инстансы, в которых никогда не был установлен `ENCRYPTION_KEY`, используют `APP_SECRET` как ключ шифрования данных на диске (и как секрет для сеансовых cookie, производный от него). Этот путь сохранен для обратной совместимости, но **устарел** — установите отдельный `ENCRYPTION_KEY` и выполните описанную выше процедуру ротации, чтобы с него мигрировать. Сам `APP_SECRET` продолжает использоваться для проверки устаревших HS256 access-токенов.
