環境変数
各サービスで使用する環境変数の一覧と設定方法をまとめます。
環境変数一覧
Fly.io 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.fly.dev | https://subseek-api-staging.fly.dev | 必須 |
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) | http://<hetzner-ip>:7700 | http://<hetzner-ip>:7701(別ポート or 別 VM) | 必須 |
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 | 必須 |
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 | https://subseek-api.fly.dev | https://subseek-api-staging.fly.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
| Secret 名 | 用途 |
|---|---|
FLY_API_TOKEN | Fly.io デプロイ用トークン |
環境変数管理戦略
Vercel を環境変数の Single Source of Truth(単一ソース)として使用する。
Fly.io は fly secrets list で名前のみ確認可能(値は読み取れない)ため、値の紛失を防ぐために全環境変数を Vercel で一元管理する。
Vercel (環境変数) ──vercel env pull──→ ローカル .env / .env.local
Vercel (環境変数) ──GitHub Actions──→ fly secrets import → Fly.io
環境ごとの設定先
| 環境 | 設定先 | 取得方法 |
|---|---|---|
| Production | Vercel Production 環境変数 | GitHub Actions: vercel env pull --environment production → fly secrets import |
| Staging | Vercel Preview 環境変数 + Fly.io subseek-api-staging secrets | 常設アプリに一度設定すれば PR ごとの再設定は不要 |
| ローカル開発 | Vercel Development 環境変数 | pnpm generate-env(vercel env pull) |
設定方法
Fly.io(API) — Vercel 経由で注入
# Production(GitHub Actions が実行)
vercel env pull .env.production --environment production
fly secrets import -a subseek-api < .env.production
# Staging(GitHub Actions が実行)
vercel env pull .env.staging --environment preview
fly secrets import -a subseek-api-staging < .env.staging
Vercel(Web)
# Production
vercel env add NEXT_PUBLIC_API_URL production # https://subseek-api.fly.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.fly.dev
vercel env add NEXT_PUBLIC_APP_URL preview # https://staging.subseek.cc
GitHub Actions
gh secret set FLY_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
セキュリティ上の注意事項
NEXT_PUBLIC_プレフィックスが付いた変数はクライアント(ブラウザ)に公開される。秘密情報を含めないことBETTER_AUTH_SECRETはセッション署名に使用するため、サーバーサイドのみで使用し、クライアントには絶対に公開しないことDATABASE_URL/DATABASE_AUTH_TOKENには DB 認証情報が含まれるため、シークレットとして管理すること.envと.env.localは.gitignoreに含まれており、リポジトリにコミットされない
新しい環境変数を追加する手順
- 該当アプリの
.env.exampleにプレースホルダーを追加 - ローカルの
.env/.env.localに実際の値を設定 - Fly.io / Vercel に Production・Staging の値を設定
turbo.jsonのenvに変数名を追加(ビルド時に必要な場合)- このドキュメントの一覧表を更新
.env.example の一覧
| ファイル | 対象アプリ |
|---|---|
apps/api/.env.example | Hono API サーバー |
apps/web/.env.example | Next.js フロントエンド |