環境変数
各サービスで使用する環境変数の一覧と設定方法をまとめます。
環境変数一覧
Cloudflare Workers API(apps/api)
| 変数名 | 用途 | Production | Staging | 必須 |
|---|---|---|---|---|
DATABASE_URL | Turso 接続 URL | libsql://subseek-db-...turso.io | libsql://subseek-db-staging-...turso.io | 必須 |
DATABASE_AUTH_TOKEN | Turso 認証トークン | (prod 用) | (staging 用) | 必須 |
BETTER_AUTH_SECRET | セッション署名キー(openssl rand -hex 32 で生成) | (prod 用) | (staging 用) | 必須 |
BETTER_AUTH_URL | Better Auth ベー ス URL | https://subseek-api.workers.dev/api/auth | https://subseek-api-staging.workers.dev/api/auth | 必須 |
BETTER_AUTH_API_KEY | Better Auth ダッシュボード接続用 API キー | — | (staging 用) | Staging のみ |
WEB_URL | CORS 許可 URL | https://subseek.cc | https://staging.subseek.cc | 必須 |
GOOGLE_CLIENT_ID | Google OAuth クライアント ID | (prod 用) | (staging 用) | 必須 |
GOOGLE_CLIENT_SECRET | Google OAuth シークレット | (prod 用) | (staging 用) | 必須 |
STRIPE_SECRET_KEY | Stripe 秘密鍵 | (prod 用) | (staging 用テストキー) | 必須 |
STRIPE_WEBHOOK_SECRET | Stripe Webhook 署名シークレット | (prod 用) | (staging 用) | 必須 |
MEILISEARCH_HOST | Meilisearch URL(Hetzner US VM、Cloudflare Tunnel 経由) | https://meili.subseek.cc | https://meili-staging.subseek.cc | 必須 |
MEILISEARCH_API_KEY | Meilisearch API キー | (prod 用) | (staging 用) | 必須 |
CLOUDFLARE_TURNSTILE_SECRET_KEY | Cloudflare Turnstile siteverify 用シークレット(/api/search 等のボット対策) | Cloudflare ダッシュボードで発行した本番用 Secret | Cloudflare 公式テストキー 1x0000000000000000000000000000000AA(常に pass) | 必須 |
GOOGLE_FORM_URL | お問い合わせフォーム送信先(Google Form の formResponse URL) | https://docs.google.com/forms/d/e/<prod-form-id>/formResponse | https://docs.google.com/forms/d/e/<staging-form-id>/formResponse | 必須 |
API ランタイム: Cloudflare Workers(
nodejs_compat+nodejs_compat_populate_process_env)。secrets はwrangler secret put <NAME>で登録、wrangler secret listで一覧表示(値は読めない)。Fly.io から移行済み(2026-04)。
Meilisearch のホスティング: Hetzner US(Ashburn)で Docker セルフホスト。Fly.io セルフホスト・Meilisearch Cloud は廃止。詳細は 検索インフラ調査 を参照。
Cloudflare Turnstile について:
/api/searchおよび/api/contactなどのボット対策に使用する。本番キーは Cloudflare ダッシュボード で発行し、ホスト名にsubseek.ccを登録すればstaging.subseek.cc含むサブドメインも自動で有効になる。Preview / ローカル開発では Cloudflare 公式の「常に pass するテストキー」を使用する(詳細は testing キー一覧)。
Google Form について: お問い合わせフォーム(#160)は DB に保存せず、バックエンド経由で Google Form の
formResponseエンドポイントにURLSearchParamsで POST して受信ストレージを Google Form に委ねる方式を採用している。GOOGLE_FORM_URLには Google Form の公開 URL から取得できる...forms/d/e/<form-id>/formResponseをそのまま設定する。entry ID(各項目のentry.xxxxx)はapps/api/src/features/contact/model/google-form-entry-ids.tsにコードとして持たせる。
R2 環境変数について: Cloudflare R2 は v0.3 で Meilisearch ダンプのバックアップ保存先として導入予定(#77)。Hetzner のアカウント BAN リスクに備えるため。v0.1 時点では
R2_*環境変数は不要。
Vercel Web(apps/web)
| 変数名 | 用途 | Production | Preview (PR) | 必須 |
|---|---|---|---|---|
NEXT_PUBLIC_API_URL | API サーバー URL(Cloudflare Workers) | https://subseek-api.workers.dev | https://subseek-api-staging.workers.dev | 必須 |
NEXT_PUBLIC_APP_URL | フロントエンド URL | https://subseek.cc | VERCEL_URL から自動生成(フォールバック) | 必須 |
NEXT_PUBLIC_TURNSTILE_SITE_KEY | Cloudflare Turnstile のサイトキー(クライアント公開) | Cloudflare ダッシュボードで発行した本番用 Site Key | 1x00000000000000000000AA(Cloudflare 公式テストキー) | 必須 |
NEXT_PUBLIC_ADSENSE_CLIENT_ID | Google AdSense Publisher ID(クライアント公開、広告表示用) | ca-pub-2848807786857797 | 未設定(広告非表示) | 任意 |
Preview 環境の
NEXT_PUBLIC_APP_URL: Vercel が自動注入するVERCEL_URL環境変数を使い、https://${VERCEL_URL}として動的に生成する。API は常設 Staging(subseek-api-staging)だが、Web は Vercel Preview で PR ごとに URL が変わる。
NEXT_PUBLIC_ADSENSE_CLIENT_IDについて: 値は Production のみに設定する。Preview / Development には設定しないことで、未承認ドメイン(*.vercel.app、localhost)での広告表示を回避する。AdSense ポリシー上、承認済みドメイン以外で広告を表示するとアカウント停止の対象となる。値自体は公開情報(apps/web/public/ads.txtに同じ Publisher ID が記載されている)。
GitHub Actions Secrets
CI/CD ワークフロー(.github/workflows/ci.yml, deploy-production.yml)が参照する Secrets。値は Cloudflare / Vercel / Turso / Meilisearch に登録済みのものと同じだが、GitHub Actions ランナーから読むには別途 GitHub Actions Secrets として登録する必要がある(各サービスのシークレットストアは GitHub Actions からは読めない)。
| Secret 名 | 用途 |
|---|---|
CLOUDFLARE_API_TOKEN | wrangler deploy で Cloudflare Workers(API)をデプロイする |
VERCEL_TOKEN | Vercel CLI で Web をデプロイする |
VERCEL_ORG_ID | Vercel プロジェクトの組織 ID |
VERCEL_PROJECT_ID | Vercel プロジェクト ID |
PROD_DATABASE_URL | 本番 Turso URL(drizzle-kit migrate で参照) |
PROD_DATABASE_AUTH_TOKEN | 本番 Turso 認証トークン |
STAGING_DATABASE_URL | staging Turso URL |
STAGING_DATABASE_AUTH_TOKEN | staging Turso 認証トークン |
PROD_MEILISEARCH_HOST | 本番 Meilisearch の URL(pnpm meilisearch:init で参照) |
PROD_MEILISEARCH_API_KEY | 本番 Meilisearch の admin / master API key |
STAGING_MEILISEARCH_HOST | staging Meilisearch の URL |
STAGING_MEILISEARCH_API_KEY | staging Meilisearch の admin / master API key |
Meilisearch 系 Secrets の用途:
deploy-apiジョブ内の「Apply Meilisearch index settings」ステップでpnpm --filter @subseek/api run meilisearch:initを実行する際に参照される。設定定義ファイル(apps/api/src/lib/meilisearch/subtitles-index/**)が変更された PR でのみトリガー。詳細は デプロイアーキテクチャ#Meilisearch インデックス設定のデプロイ を参照。
環境変数管理戦略
Vercel を Web 側の Single Source of Truth(単一ソース)として使用する。
wrangler secret list は名前のみ確認可能(値は読み取れない)ため、値の紛失を防ぐために Web/API 共通で使う変数(DATABASE_URL、GOOGLE_CLIENT_ID 等)は Vercel に保管し、API 側(Cloudflare Workers)へはそこから手動もしくはスクリプトで反映する運用とする。
Vercel (Production/Preview/Development) ──vercel env pull──→ ローカル .env / .env.local
Vercel (Production/Preview) ──vercel env pull + wrangler secret put──→ Cloudflare Workers
環境ごとの設定先
| 環境 | 設定先 | 取得方法 |
|---|---|---|
| Production | Vercel Production + Cloudflare Workers subseek-api secrets | Vercel で値を管理し、wrangler secret put <NAME> で Workers に反映 |
| Staging | Vercel Preview + Cloudflare Workers subseek-api-staging secrets | 常設アプリに一度設定すれば PR ごとの再設定は不要 |
| ローカル開発 | Vercel Development 環境変数 | pnpm generate-env(vercel env pull) |
設定方法
Cloudflare Workers(API) — wrangler で登録
Workers secrets は wrangler secret コマンドで個別に登録する。値を Vercel に保管しているなら vercel env pull で引いてから個別に wrangler secret put で登録する。
# Production
wrangler secret put DATABASE_URL # --env 省略で本番(subseek-api)
wrangler secret put DATABASE_AUTH_TOKEN
wrangler secret put BETTER_AUTH_SECRET
# ...他必須変数
# Staging
wrangler secret put DATABASE_URL --env staging # subseek-api-staging
wrangler secret put DATABASE_AUTH_TOKEN --env staging
# ...
現在の登録状況は wrangler secret list / wrangler secret list --env staging で確認できる(名前のみ)。
Vercel(Web)
# Production
vercel env add NEXT_PUBLIC_API_URL production # https://subseek-api.workers.dev
vercel env add NEXT_PUBLIC_APP_URL production # https://subseek.cc
# Preview (Staging)
vercel env add NEXT_PUBLIC_API_URL preview # https://subseek-api-staging.workers.dev
vercel env add NEXT_PUBLIC_APP_URL preview # https://staging.subseek.cc
GitHub Actions
# デプロイ用トークン
gh secret set CLOUDFLARE_API_TOKEN -R nito-tech/subseek
gh secret set VERCEL_TOKEN -R nito-tech/subseek
gh secret set VERCEL_ORG_ID -R nito-tech/subseek
gh secret set VERCEL_PROJECT_ID -R nito-tech/subseek
# DB(drizzle-kit migrate 用)
gh secret set PROD_DATABASE_URL -R nito-tech/subseek
gh secret set PROD_DATABASE_AUTH_TOKEN -R nito-tech/subseek
gh secret set STAGING_DATABASE_URL -R nito-tech/subseek
gh secret set STAGING_DATABASE_AUTH_TOKEN -R nito-tech/subseek
# Meilisearch(pnpm meilisearch:init 用、Cloudflare Tunnel 経由)
gh secret set PROD_MEILISEARCH_HOST --body "https://meili.subseek.cc" -R nito-tech/subseek
gh secret set PROD_MEILISEARCH_API_KEY -R nito-tech/subseek
gh secret set STAGING_MEILISEARCH_HOST --body "https://meili-staging.subseek.cc" -R nito-tech/subseek
gh secret set STAGING_MEILISEARCH_API_KEY -R nito-tech/subseek
セキュリティ上の注意事項
NEXT_PUBLIC_プレフィックスが付いた変数はクライアント(ブラウザ)に公開される。秘密情報を含めないことBETTER_AUTH_SECRETはセッション署名に使用するため、サーバーサイドのみで使用し、クライアントには絶対に公開しないことDATABASE_URL/DATABASE_AUTH_TOKENには DB 認証情報が含まれるため、シークレットとして管理すること.envと.env.localは.gitignoreに含まれており、リポジトリにコミットされない
新しい環境変数を追加する手順
- 該当アプリの
.env.exampleにプレースホルダーを追加 - ローカルの
.env/.env.localに実際の値を設定 - Cloudflare Workers(API)に
wrangler secret put <NAME>/wrangler secret put <NAME> --env staging、Vercel(Web)にvercel env add <NAME> production/vercel env add <NAME> previewで値を設定 turbo.jsonのenvに変数名を追加(ビルド時に必要な場合)- このドキュメントの一覧表を更新
.env.example の一覧
| ファイル | 対象アプリ |
|---|---|
apps/api/.env.example | Hono API サーバー(Cloudflare Workers) |
apps/web/.env.example | Next.js フロントエンド(Vercel) |