비밀 및 키 관리

이 페이지

이 목록으로 어떤 값이 런타임 환경에 속하고, 어떤 값이 데이터베이스에 생성되며, 어떤 값이 플러그인에 저장되는지 결정하세요. 각 섹션은 교체가 실행 중인 사이트에 미치는 영향을 설명합니다.

Node.js에서는 프로세스 시작 시 process.env에 들어가도록 런타임 비밀을 호스팅 플랫폼의 비밀 관리자에 넣으세요. Worker에서는 wrangler secret put을 사용하세요. 비밀 값을 astro.config.mjs, wrangler.jsonc, import.meta.env에 넣지 마세요. Vite가 빌드 시점 값을 서버 번들에 임베드할 수 있습니다.

개요

비밀출처저장 위치키 분실 영향
EMDASH_ENCRYPTION_KEY운영자(emdash secrets generate)환경 / Worker 비밀만일치하는 키를 복원할 때까지 암호화된 플러그인 설정을 읽을 수 없음
미리보기 비밀자동 생성(환경 재정의)options 테이블(emdash:preview_secret)미사용 미리보기 링크가 동작하지 않음. 새 링크는 정상
IP 솔트자동 생성(환경 재정의)options 테이블(emdash:ip_salt)댓글 속도 제한 연속성이 재설정됨
세션 및 API 토큰세션/토큰별 생성세션 저장소 / 데이터베이스(해시만)없음 — 평문은 절대 저장되지 않음
OAuth 제공자 자격 증명사용자(Google/GitHub 콘솔)환경해당 제공자 로그인이 교체될 때까지 중지됨
Turnstile 비밀사용자(Cloudflare 대시보드)환경댓글 CAPTCHA 검증 실패
S3 자격 증명사용자(스토리지 제공자)런타임 환경미디어 업로드/다운로드가 교체될 때까지 실패
플러그인 비밀사용자(관리 설정 UI)암호화된 데이터베이스 설정일치하는 암호화 키를 복원하거나 값을 다시 입력
CLI 자격 증명emdash login / emdash plugin publish 디바이스 플로우~/.config/emdash/auth.json(모드 0600)디바이스 플로우를 다시 실행
레지스트리 CLI 자격 증명emdash-plugin atproto OAuth~/.emdash/oauth/, ~/.emdash/credentials.json(모드 0600)다시 로그인. 신원은 PDS에 있음

암호화 키

EMDASH_ENCRYPTION_KEY는 type: "secret"으로 선언된 플러그인 설정을 암호화합니다. EmDash는 플러그인 ID와 설정 키를 인증 데이터로 하는 AES-GCM을 사용합니다. 잘못된 형식의 값은 운영자용 시작 메시지를 내고, 암호화된 플러그인 설정이 필요한 작업은 fail closed 합니다. 관련 없는 사이트 요청은 계속 동작합니다.

다음 명령은 올바른 형식의 값을 생성합니다. 런타임 환경에 저장하거나, 배포가 이 변수를 쓰면 Worker 비밀로 저장하세요.

npx emdash secrets generate
# emdash_enc_v1_<43 base64url chars>

# Cloudflare:
wrangler secret put EMDASH_ENCRYPTION_KEY

형식은 emdash_enc_v1_ 뒤에 패딩 없는 base64url의 32 랜덤 바이트입니다. 값은 운영자가 제공하며 데이터베이스에 저장되지 않습니다. 비밀 관리자와 별도의 복구 백업에 보관하세요.

키를 교체하려면 새 값을 앞에 두고 쉼표 뒤에 이전 값을 유지하세요.

EMDASH_ENCRYPTION_KEY=emdash_enc_v1_<new-key>,emdash_enc_v1_<old-key>

EmDash는 새 값과 다시 저장한 값을 첫 번째 키로 암호화합니다. 읽기에는 저장된 kid 지문으로 이전 키를 선택합니다. 이전 키를 제거하기 전에 모든 플러그인 비밀을 다시 저장하고, 새 키만 있는 배포에서 해당 연동을 검증하세요. EmDash는 현재 어떤 키 ID가 아직 사용되는지 보고하지 않으므로, 다시 저장한 자격 증명 목록을 유지하고 각 연동이 그 검증을 통과할 때까지 이전 키를 제거하지 마세요.

생성된 사이트 비밀

두 비밀은 첫 사용 시 자동 생성되어 options 테이블에 유지되므로 요청, 배포, isolate를 걸쳐 안정적입니다. 생성은 원자적입니다. 동시 콜드 스타트는 한 값으로 수렴합니다.

미리보기 비밀

미리보기 URL에 서명합니다(HMAC). emdash:preview_secret으로 저장. 32 랜덤 바이트, base64url.

  • 재정의: 여러 프로세스에서 같은 비밀이 필요하거나 감사를 위해 고정하려면 EMDASH_PREVIEW_SECRET(레거시 별칭: PREVIEW_SECRET)을 설정하세요. 환경이 항상 저장 값보다 우선합니다.
  • 교체: emdash:preview_secret 행을 삭제하거나 환경 변수를 바꾼 뒤 재배포하세요. 영향: 이전에 발급된 미리보기 링크가 검증에 실패합니다. 다른 것은 깨지지 않습니다. 다음 미리보기 요청에서 새 비밀이 생성(또는 환경에서 읽힘)됩니다.
  • 분실 시: 복구 불가능한 것은 없습니다. 미리보기 링크는 설계상 수명이 짧습니다.

미리보기 URL 구성과 검증은 미리보기 가이드를 보세요.

IP 솔트

댓글 속도 제한에 쓰는 댓글 작성자 IP 주소의 SHA-256 해시(ip_hash)에 솔트를 넣습니다. emdash:ip_salt으로 저장. 사이트별이므로 해시는 EmDash 설치 간에 상관할 수 없습니다.

  • 재정의: EMDASH_IP_SALT를 설정하세요. 하위 호환을 위해 EMDASH_AUTH_SECRET / AUTH_SECRET도 참조합니다. 과거 그것으로 솔트를 유도한 설치는 안정적인 해시를 유지합니다.
  • 교체: 환경 변수를 바꾸거나 emdash:ip_salt 행을 삭제하세요. 영향: 새 댓글 제출이 다른 값으로 해시되어 모든 사람의 속도 제한 집계가 재시작됩니다. 기존 댓글과 저장된 해시는 건드리지 않습니다.
  • 분실 시: 데이터 손실 없음. 속도 제한 연속성만 재설정됩니다.

세션 및 API 토큰

  • 세션은 Astro 세션 저장소를 사용합니다(Cloudflare에서는 Workers KV, Node에서는 파일시스템). 쿠키는 불투명 세션 ID를 담으며 관리할 서명 비밀이 없습니다. 로그아웃으로 세션을 끝내거나, 세션 저장소(예: KV 네임스페이스)를 비워 모두 다시 로그인하게 하세요.
  • API 토큰(접두사 ec_pat_, ec_oat_, ec_ort_)은 불투명 256비트 난수입니다. SHA-256 해시만 저장됩니다. 평문은 생성 시 한 번만 표시됩니다. 관리자에서 철회 후 재생성으로 교체하세요.
  • 초대, 매직 링크, 복구 토큰은 단일 목적이고 auth_tokens에 SHA-256 해시로 저장되며 시간 제한이 있습니다(초대 7일, 매직 링크 15분).

선제적으로 백업하거나 교체할 것은 없습니다. 데이터베이스 유출은 해시만 노출하며, 모든 토큰은 관리자에서 철회하거나 재발급할 수 있습니다.

사용자가 제공하는 서비스 자격 증명

외부 서비스 자격 증명은 환경에서 읽히며 데이터베이스에 쓰지 않습니다. 제공자에서 교체하고, 변수를 업데이트한 뒤 재배포하세요.

서비스변수
Google 로그인EMDASH_OAUTH_GOOGLE_CLIENT_ID, EMDASH_OAUTH_GOOGLE_CLIENT_SECRET(또는 접두사 없는 별칭)
GitHub 로그인EMDASH_OAUTH_GITHUB_CLIENT_ID, EMDASH_OAUTH_GITHUB_CLIENT_SECRET(또는 접두사 없는 별칭)
Marketplace 게시(CI)EMDASH_MARKETPLACE_TOKEN
Turnstile(댓글)EMDASH_TURNSTILE_SECRET_KEY(또는 TURNSTILE_SECRET_KEY)
S3 호환 스토리지S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_ENDPOINT, S3_BUCKET, S3_REGION

Cloudflare에서는 wrangler secret put으로 설정하세요. 로컬 개발에서는 .env에 넣으세요. Wrangler는 .dev.vars 또는 .env 중 하나만 읽으며, 있으면 .dev.vars가 우선합니다. 바인딩을 통한 R2는 바인딩이 런타임 접근을 주므로 액세스 키 변수가 필요 없습니다. 미디어 스토리지를 보세요.

플러그인 비밀

플러그인이 type: "secret"으로 선언하는 설정(이메일 제공자 API 키, 양식 CAPTCHA 등)은 관리 UI에 입력되고 options 테이블의 plugin:<id>:settings:<key> 아래에 암호화됩니다. 일치하는 암호화 키가 없어도 관리자는 비밀이 설정되었는지만 받으므로, 관리자가 읽을 수 없는 자격 증명을 교체할 수 있습니다. 플러그인 코드는 격리된 런타임 안 ctx.settings로 평문을 읽습니다. 선언된 설정 스키마 밖에 저장된 값(임의 플러그인 KV 및 상태 항목 포함)은 이 암호화 경로를 쓰지 않습니다.

  • 자격 증명 교체: 제공자에서 자격 증명을 교체하고 새 값을 플러그인 설정 페이지에 붙여넣으세요. 저장은 새 암호화 봉투를 씁니다.
  • 평문 마이그레이션: 이전 EmDash 릴리스에 저장된 비밀은 계속 읽을 수 있습니다. 각 값을 다시 저장해 암호화하세요.
  • 암호화 키를 잃은 경우: 별도 키 백업에서 일치하는 EMDASH_ENCRYPTION_KEY를 복원하세요. 복사본이 없으면 영향받는 각 자격 증명을 제공자에서 교체하고, 새 암호화 키를 구성한 뒤 대체 값을 입력하세요.

CLI 자격 증명

emdash CLI는 두 종류의 자격 증명을 ~/.config/emdash/auth.json(XDG_CONFIG_HOME 준수)에 소유자 전용 권한(0600)으로 보관합니다.

  • 사이트 토큰 — emdash login은 OAuth 디바이스 플로우로 EmDash 인스턴스에 인증하고, 결과 토큰을 인스턴스 URL로 키를 잡아 저장합니다. emdash logout이 제거합니다. 호출마다 --token 또는 EMDASH_TOKEN이 저장 토큰을 덮어씁니다.
  • Marketplace 토큰 — emdash plugin publish는 GitHub 디바이스 플로우로 EmDash Marketplace에 인증하고, 결과 JWT를 marketplace:<origin>으로 키를 잡아 저장합니다. CI 게시에서는 대신 EMDASH_MARKETPLACE_TOKEN을 설정하세요. 저장된 자격 증명보다 우선합니다.

파일을 잃어도 해롭지 않습니다. emdash login(또는 디바이스 플로우를 다시 실행하는 emdash plugin publish)을 다시 실행하세요.

플러그인 레지스트리 CLI 자격 증명

별도 emdash-plugin CLI(패키지 @emdash-cms/plugin-cli)는 실험적 AT Protocol 레지스트리를 대상으로 합니다. 그곳 게시는 AT Protocol 신원(게시자 DID)에 묶입니다. 사이트 자체는 게시 자격 증명을 갖지 않으며, 설치는 해당 DID에 귀속된 릴리스 레코드의 체크섬으로 아티팩트를 검증합니다.

  • atproto OAuth로 인증합니다. OAuth 세션/상태 blob은 ~/.emdash/oauth/에 있고, 게시자 신원(DID, 핸들, PDS)은 ~/.emdash/credentials.json에 캐시됩니다. 둘 다 소유자 전용 권한으로 씁니다.
  • CI에서는 EMDASH_PUBLISHER_DID, EMDASH_PUBLISHER_HANDLE, EMDASH_PUBLISHER_PDS로 신원을 제공하세요. EMDASH_REGISTRY_URL은 레지스트리 호스트를 재정의합니다. CI에서 자동 publish는 러너의 ~/.emdash/oauth/ OAuth 세션 파일이 여전히 필요합니다. 환경 변수만으로는 OAuth 세션을 전달하지 않습니다.
  • 게시 접근 교체 또는 철회는 AT Protocol 계정(예: 앱 비밀번호)에서 하며 EmDash 안이 아닙니다. Atmosphere 인증을 보세요.

교체 빠른 참조

하고 싶은 일이렇게 하세요
플러그인 설정 암호화 교체새 키를 앞에 두고, 플러그인 비밀을 다시 저장한 뒤 이전 키 제거
모든 미리보기 링크 무효화emdash:preview_secret 옵션 행 삭제(또는 환경 재정의 변경)
댓글 속도 제한 해싱 재설정EMDASH_IP_SALT 변경(또는 emdash:ip_salt 옵션 행 삭제)
유출된 API 토큰 철회Admin → Users → API tokens → 철회 후 대체 생성
모든 세션 종료세션 저장소 비우기(Workers KV 네임스페이스 / 세션 디렉터리)
제공자 자격 증명 교체제공자에서 교체, 환경 변수 업데이트, 재배포
플러그인 API 키 교체제공자에서 교체, 플러그인 관리 설정에 다시 입력