このチェックリストを使って、どの値がランタイム環境に属し、どれが自動生成されてデータベースに保存され、どれがプラグインによって保存されるのかを確認してください。各セクションでは、ローテーションが稼働中のサイトにどのような影響を与えるかも説明しています。
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、または Microsoft Entra コンソール) | 環境変数 | 置き換えるまで、そのプロバイダーでのサインインが停止する |
| Turnstile シークレット | あなた(Cloudflare ダッシュボード) | 環境変数 | コメントの CAPTCHA 検証が失敗する |
| S3 資格情報 | あなた(ストレージプロバイダー) | ランタイム環境 | 置き換えるまで、メディアのアップロード/ダウンロードが失敗する |
| プラグインシークレット | あなた(管理画面の設定 UI) | 暗号化されたデータベース設定 | 対応する暗号化キーを復元するか、値を再入力する |
| CLI 資格情報 | emdash login デバイスフロー | ~/.config/emdash/auth.json(モード 0600) | デバイスフローを再実行する |
| レジストリ CLI 資格情報 | emdash-plugin の atproto OAuth | ~/.emdash/oauth/、~/.emdash/credentials.json(モード 0600) | 再ログインする。ID は PDS 上にある |
暗号化キー
EMDASH_ENCRYPTION_KEY は、type: "secret" で宣言されたプラグイン設定を暗号化します。EmDash は AES-GCM を使用し、プラグイン ID と設定キーを認証データとして扱います。形式が不正な値は運用者向けの起動メッセージを生成し、暗号化されたプラグイン設定を必要とする操作はフェイルクローズします。それ以外のサイトのリクエストは引き続き動作します。
次のコマンドで正しい形式の値を生成できます。デプロイでこの変数を使用する場合は、ランタイム環境または 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 がまだ使用されているかを報告しないため、再保存した資格情報の一覧を管理し、すべての連携が検証されるまで古いキーを削除しないでください。
生成されるサイトシークレット
2 つのシークレットは初回使用時に自動生成され、options テーブルに永続化されるため、リクエスト、デプロイ、分離環境をまたいで安定します。生成はアトミックです。コールドスタートが同時に発生しても、同じ値に収束します。
プレビューシークレット
プレビュー 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 ではファイルシステム)。ストアが設定されていないアダプター(Vercel など)では、
astro.config.mjsでセッションドライバーを設定する必要があります。設定しないと、セッションドライバーが必要であることを示すエラーでログインが失敗します。Cookie には不透明なセッション ID が入っており、管理すべき署名シークレットはありません。ログアウトするとセッションが終了します。全員を強制的に再ログインさせるには、セッションストア(たとえば KV 名前空間)を消去します。 - API トークン(プレフィックス
ec_pat_、ec_oat_、ec_ort_)は不透明な 256 ビットのランダム値で、SHA-256 ハッシュのみが保存されます。平文は作成時に一度だけ表示されます。ローテーションするには、管理画面で取り消して再作成します。 - 招待、マジックリンク、リカバリートークンは単一用途で、SHA-256 ハッシュとして
auth_tokensに保存され、有効期限があります(招待は 7 日、マジックリンクは 15 分)。
バックアップやローテーションを事前に行う必要はありません。データベースが漏えいしてもハッシュが露出するだけで、すべてのトークンは管理画面から取り消しまたは再発行できます。
ユーザー提供のサービス資格情報
外部サービスの資格情報は環境変数から読み取られ、データベースには書き込まれません。プロバイダー側でローテーションし、変数を更新して再デプロイします。
| サービス | 変数 |
|---|---|
| Google サインイン | EMDASH_OAUTH_GOOGLE_CLIENT_ID、EMDASH_OAUTH_GOOGLE_CLIENT_SECRET(またはプレフィックスなしのエイリアス) |
| GitHub サインイン | EMDASH_OAUTH_GITHUB_CLIENT_ID、EMDASH_OAUTH_GITHUB_CLIENT_SECRET(またはプレフィックスなしのエイリアス) |
| Microsoft サインイン | EMDASH_OAUTH_MICROSOFT_CLIENT_ID、EMDASH_OAUTH_MICROSOFT_CLIENT_SECRET、EMDASH_OAUTH_MICROSOFT_TENANT_ID(またはプレフィックスなしのエイリアス) |
| 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 ではアクセスキーの変数は不要です。バインディングがランタイムアクセスを付与するためです。メディアストレージを参照してください。
Node では、EmDash はリクエスト到着時にサーバーのプロセス環境から Turnstile のシークレットキーを読み取りますが、astro dev もビルド済みサーバーも .env をそこに読み込みません。ホストの環境でキーを設定するか、astro dev を実行するシェルでエクスポートするか、node --env-file=.env ./dist/server/entry.mjs でビルド済みサーバーを起動してください。
プラグインシークレット
プラグインが 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 は、呼び出しごとに保存済みのトークンを上書きします。
このファイルを失っても問題ありません。emdash login を再実行するだけです。
プラグインレジストリ CLI 資格情報
スタンドアロンの emdash-plugin CLI(パッケージ @emdash-cms/plugin-cli)は、実験的な AT Protocol レジストリを対象としています。そこでの公開は、あなたの AT Protocol ID(パブリッシャー DID)に紐づきます。サイト自体は公開用の資格情報を保持せず、インストール時に、その DID に帰属する公開レコードのチェックサムに対してアーティファクトが検証されます。
- 認証には atproto OAuth を使用します。OAuth のセッション/状態データは
~/.emdash/oauth/にあり、パブリッシャー ID(DID、ハンドル、PDS)は~/.emdash/credentials.jsonにキャッシュされます。どちらも所有者のみがアクセスできるモードで書き込まれます。 - CI では、
EMDASH_PUBLISHER_DID、EMDASH_PUBLISHER_HANDLE、EMDASH_PUBLISHER_PDSで ID を指定します。EMDASH_REGISTRY_URLはレジストリのホストを上書きします。CI でのpublishの自動実行には、ランナー上の~/.emdash/oauth/にある OAuth セッションファイルが引き続き必要です。環境変数だけでは OAuth セッションを運べません。 - 公開アクセスのローテーションや取り消しは、EmDash ではなく AT Protocol アカウント側(たとえばアプリパスワード)で行います。Atmosphere auth を参照してください。
ローテーション早見表
| やりたいこと | 対処 |
|---|---|
| プラグイン設定の暗号化をローテーションする | 新しいキーを先頭に追加し、プラグインシークレットを再保存してから、古いキーを削除する |
| すべてのプレビューリンクを無効にする | emdash:preview_secret の行を削除する(または環境変数の上書きを変更する)。再デプロイする |
| コメントのレート制限ハッシュをリセットする | EMDASH_IP_SALT を変更する(または emdash:ip_salt のオプション行を削除する)。再デプロイする |
| 漏えいした API トークンを取り消す | Admin → Users → API tokens → 取り消し、その後、代わりのトークンを作成する |
| すべてのセッションを終了する | セッションストア(Workers KV 名前空間 / セッションディレクトリ)を消去する |
| プロバイダーの資格情報を置き換える | プロバイダー側でローテーションし、環境変数を更新して再デプロイする |
| プラグインの API キーを置き換える | プロバイダー側でローテーションし、プラグインの管理画面の設定で再入力する |