シークレットの取り扱いは、地味ですが事故ると一発で致命傷になる領域です。「API キーが GitHub に漏れた」「NEXT_PUBLIC_ を付けたら本番のキーがブラウザに出ていた」——どれも数分で起きて、長く尾を引きます。
この記事は Vercel 環境変数の公式仕様に忠実に、3環境の使い分け・NEXT_PUBLIC_ の罠・OIDC 鍵レス・型安全な env 境界をまとめます。全体像は Vercel 本番運用ガイド、入口セキュリティは Firewall・WAF・BotID を参照してください。
3つの環境を使い分ける
Vercel の環境変数は環境ごとに値を変えられます。値は保存時に暗号化され、プロジェクトにアクセスできるメンバーに見えます。
| 環境 | いつ適用されるか | 用途 |
|---|---|---|
| Production | 本番ブランチ(通常 main)へのプッシュ / vercel --prod | 本番のキー・接続文字列 |
| Preview | 本番以外のブランチへのプッシュ / vercel | ステージングDB等。ブランチ別に上書き可 |
| Development | vercel dev / ローカル | ローカル開発用 |
# 環境ごとに値を登録
vercel env add DATABASE_URL production # 本番DB
vercel env add DATABASE_URL preview # ステージングDB
vercel env add DATABASE_URL development # ローカルDB
# 特定ブランチだけ上書きしたいとき(preview)
# → ダッシュボードでブランチ指定。同名変数はブランチ別が優先される
重要な落とし穴:環境変数の変更は、新しいデプロイにのみ適用されます。既存の本番デプロイは値が変わりません。「変えたのに反映されない」の大半はこれ——再デプロイしてください。
Preview のブランチ別上書き
Preview 変数は「全非本番ブランチ」か「特定ブランチ」に適用できます。ブランチ指定の変数は同名の一般 Preview 変数を上書きするので、全部を複製せず差分だけ定義すれば済みます。
NEXT_PUBLIC_ の罠(最重要)
最も多い、そして最も危険な事故が NEXT_PUBLIC_ 接頭辞です。
NEXT_PUBLIC_を付けた変数は、ビルド時にバンドルへ埋め込まれ、ブラウザに露出します。- だから、API キー・DB 接続文字列・秘密鍵・サービスロールキーには絶対に付けない。
- 付けてよいのは「クライアントで読む必要がある公開値」だけ(公開可能な計測 ID、公開 API のベースURL など)。
// ❌ 絶対NG:秘密に NEXT_PUBLIC_ → ブラウザに丸見え
// NEXT_PUBLIC_STRIPE_SECRET_KEY=sk_live_xxx
// ✅ サーバーでだけ読む(無印)
const stripeSecret = process.env.STRIPE_SECRET_KEY; // サーバー専用
// ✅ クライアントで読む公開値だけ NEXT_PUBLIC_
const ga = process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID; // 公開してよい
Supabase の
anon keyとservice_role keyの取り違え、NEXT_PUBLIC_への秘密混入は、実際の脆弱性診断で頻出します(env リーク防止、anon/service_role の露出)。「クライアントで読む必要が本当にあるか」を一段疑うのが防御です。
サイズ上限とランタイム差
- 合計 64KB / デプロイ(全変数の合計。単一変数も 64KB 以下)。JWT・証明書のような大きな値も扱えます。
- 対応ランタイム(64KB):Node.js / Python / Ruby / Go / PHP コミュニティランタイム。
- Edge ランタイムは 1変数 5KB まで。Edge ミドルウェアで大きな値を読むなら注意。
ローカル開発:vercel env pull
ローカルでは .env.local(または vercel env pull が生成する .env)に開発用変数を置きます。
# Development 環境の変数をローカルへ同期
vercel env pull .env.local
# vercel dev なら自動で Development 変数をメモリに読み込む(pull不要)
vercel dev
.env* はコミットしない(.gitignore に必ず入れる)。Vercel CLI 経由のデプロイは .env 系を自動で無視しますが、Git 経由は .gitignore が頼りです。
@vercel/speed-insights/@vercel/analyticsの罠:これらは**package.jsonの依存**に入れます。グローバルに入れて参照すると、特にモノレポでビルドエラーになります(可観測性)。
システム環境変数
Vercel は実行時に有用なシステム変数を注入します。
| 変数 | 内容 |
|---|---|
VERCEL_ENV | production / preview / development |
VERCEL_URL | このデプロイの生成URL |
VERCEL_GIT_COMMIT_SHA | デプロイ元のコミット |
VERCEL_REGION | 実行リージョン |
// 環境で分岐(例:プレビューだけ noindex、本番だけ外部送信)
const isProd = process.env.VERCEL_ENV === "production";
if (!isProd) headers.set("X-Robots-Tag", "noindex");
OIDC 鍵レス:外部クラウドへ長命キーを置かない
AWS S3・SES、GCP、データベースなど外部リソースへアクセスするとき、長命のアクセスキーを環境変数に置くのは2026年では非推奨です。OIDC(OpenID Connect)連携で一時クレデンシャルを得ます。
- Vercel の OIDC トークンを外部クラウドの IAM ロールが信頼し、鍵を保管せずに一時的な権限を得る。
- 漏洩リスクが構造的に下がり、ローテーション運用も消える。
- CI/CD(GitHub Actions → Vercel/AWS)も同じく OIDC 鍵レスに(OIDC 鍵レス CI/CD)。
どうしても長命キーが必要な場合は、最小権限に絞り、Production にのみ置き、定期ローテーションします。
Fluid Compute での秘密の扱い
Fluid Compute は1インスタンスで複数リクエストを並行処理します。
// ✅ 起動時に一度だけ読む(リクエスト非依存)
const apiKey = process.env.EXTERNAL_API_KEY!;
// ❌ リクエスト固有のトークンをモジュールスコープにキャッシュしない
// let userToken; // 別リクエストに漏れる
リクエストごとのトークン・ユーザー秘密は関数スコープのローカルに閉じます。
型安全な env 境界(Zod)
環境変数は「外部入力」です。起動時に Zod で検証して、未設定や形式不正をビルド/起動で落とします。これで「本番で env 未設定の 500」を未然に防げます。
// lib/env.ts — env を型安全な単一の真実源に
import { z } from "zod";
const schema = z.object({
DATABASE_URL: z.string().url(),
STRIPE_SECRET_KEY: z.string().startsWith("sk_"),
NEXT_PUBLIC_GA_MEASUREMENT_ID: z.string().optional(),
});
// 起動時に検証(失敗したら即座に落ちる=本番で気づくより安全)
export const env = schema.parse(process.env);
process.env.X を直に散らさず、env.X 経由にすることで、型・必須・形式が一箇所で保証されます(型安全の徹底)。
本番チェックリスト(env・シークレット)
- 3環境(production/preview/development)に値を整理
-
NEXT_PUBLIC_に機密を付けていない(ブラウザ露出) - 変更後は再デプロイ(既存デプロイには反映されない)
-
.env*をコミットしていない - Edge で読む変数は 5KB 以内、合計 64KB 以内
- 外部クラウドは OIDC 鍵レス、長命キーは最小権限+ローテーション
- Fluid のグローバルにリクエスト固有の秘密を残さない
- env を Zod で起動時検証(型安全な境界)
まとめ
シークレット管理は「派手さはないが、外すと一発」の領域です。
- 3環境を使い分け、変更は再デプロイで反映
NEXT_PUBLIC_に秘密を付けない(最重要)- ローカルは
vercel env pull、.envはコミットしない - 外部クラウドは OIDC 鍵レスで長命キーを消す
- env は Zod で型安全な境界にする
シークレット管理の監査・OIDC 鍵レス化・型安全な env 境界の導入を、案件として承ります。
本記事は Vercel 環境変数 公式ドキュメント(2026年6月時点)に基づきます。上限・仕様は更新されるため、本番採用時は公式で最新値を確認してください。