- JWT 서명 키 — 비대칭 ES256 키 페어(
kid태그 사용)로,core."signingKey"에 저장되며 액세스/리프레시 토큰을 서명하고 검증하는 데 사용됩니다. - 정지 상태 암호화 키 — OAuth 토큰, 애플리케이션 변수, 서명 키의 개인 키, 민감한 설정 값,
enc:v2:봉투 안의 TOTP 시크릿을 암호화하는 데 사용되는ENCRYPTION_KEY입니다.
APP_SECRET은 하위 호환성을 위해 유지되는 레거시 시크릿입니다. ENCRYPTION_KEY가 설정되지 않은 경우 정지 상태 암호화/세션 쿠키 폴백 역할을 하며, 기존 HS256 액세스 토큰을 계속 검증합니다. 이는 사용 중단 예정입니다.
JWT 서명 키
각 키는publicKey(이전에 발급된 토큰을 검증할 수 있도록 무기한 보관), 암호화된 privateKey(해당 키가 현재 키일 때만 사용), isCurrent 플래그(한 번에 정확히 한 행만 true), 선택적인 revokedAt를 가집니다.
현재 키 회전
옵트인하려면SIGNING_KEY_ROTATION_DAYS 를 설정하세요. 그러면 일일 cron 작업이 기존 키가 해당 기준값보다 오래되면 새로운 현재 키를 발급합니다. 이전 키는 폐기되지 않으므로, 해당 키로 서명된 토큰은 계속 검증됩니다. 자동 회전을 사용하지 않으려면 변수를 설정하지 않은 상태로 두세요.
자동 회전 기능은 v2.6+부터 제공됩니다.
키 폐기(유출 / 비상 시에만)
현재 키가 아닌 행에서 Settings → Admin Panel → Signing keys → Revoke를 수행합니다. 암호화된 개인 데이터를 삭제하고revokedAt을 설정하며, 해당 kid로 서명된 모든 기존 토큰을 거부합니다.
ENCRYPTION_KEY 회전
아래에 설명된
secret-encryption:rotate 커맨드는 v2.6+에서 제공됩니다.enc:v2:\<keyId>:\<payload> 형식으로 래핑됩니다. 여기서 \<keyId>는 원시 키에서 파생된 8자리 16진수 접두사입니다. 회전 작업은 온라인으로 수행되며, 중단 후 재개할 수 있습니다.
-
새 키 생성:
openssl rand -base64 32. -
.env에 두 키를 나란히 설정한 다음, 재시작합니다:새로 기록되는 데이터는 새 키를 사용하며, 기존 행은 폴백을 통해 계속 복호화됩니다. -
기존 행 재암호화:
이 커맨드는 여섯 개의 위치(
connected-account-tokens,application-variable,application-registration-variable,signing-key-private-keys,sensitive-config-storage,totp-secrets)를 순회합니다. SQL 필터는 이미 새\<keyId>로 암호화된 행을 건너뛰므로, 이 커맨드는 멱등성을 가집니다. 필요에 따라 중단하고 다시 실행해도 됩니다. 어떤 행이라도 실패하면 0이 아닌 코드로 종료되며, 재실행하여 재시도할 수 있습니다.플래그 설명 -s, --site \<site>단일 사이트로 범위를 제한합니다. -b, --batch-size \<n>배치당 행 수(기본값 200, 최대5000).-d, --dry-run메모리에서 복호화 + 재암호화를 수행하고, UPDATE는 생략합니다. -
--dry-run결과 남은 행이 0이면 폴백을 제거합니다.FALLBACK_ENCRYPTION_KEY를 삭제하고 재시작합니다.
레거시 APP_SECRET 지원
ENCRYPTION_KEY를 설정하지 않은 오래된 인스턴스는 정지 상태 암호화 키(및 이로부터 파생된 세션 쿠키 시크릿)로 APP_SECRET을 사용합니다. 이 경로는 하위 호환성을 위해 유지되지만 사용 중단 예정입니다. 전용 ENCRYPTION_KEY를 설정하고 위의 회전 절차를 따라 이를 사용하지 않는 방식으로 마이그레이션하세요. APP_SECRET 자체는 기존 HS256 액세스 토큰을 검증하는 데 계속 사용됩니다.