手元では動いていたのに
APIキーを使うものを作って、手元では動いている。git pushしてVercelに公開したら、本番だけが動かない。
原因はたいてい単純です。鍵を書いたファイルは、わざとGitHubに送っていないからです。.envのようなファイルは.gitignoreに書いて除外しているはずで、除外しているということはVercelにも届いていません。手元にだけある、という状態です。
なので、同じ値を別ルートでVercelにも渡す必要があります。その仕組みが環境変数です。
環境変数とは
Vercelの公式ドキュメントの説明はこうです。
Environment variables are key-value pairs configured outside your source code so that each value can change depending on the Environment. These values are encrypted at rest and visible to any user that has access to the project.
(環境変数は、ソースコードの外側に置く「名前と値」の組で、環境ごとに値を変えられます。値は保存時に暗号化され、そのプロジェクトにアクセスできるユーザーからは見えます)
引用の後半は先に知っておくところです。暗号化されているのは保管のしかたであって、権限のある人からは読めます。 ひとりで使っているうちは気になりませんが、人を招いた時点で意味が変わります。
環境は3つある
| 環境 | いつ使われるか |
|---|---|
| Production | 本番。mainにpushしたとき、またはvercel --prodを打ったとき |
| Preview | 本番以外のブランチにpushしたとき |
| Development | 手元。vercel devなどでローカルに動かしているとき |
値を登録するときに、どの環境に適用するかを選びます。 本番だけ本物の鍵にして、プレビューはテスト用の鍵にする、という分け方ができます。
登録はダッシュボードの Settings → Environment Variables から。ターミナルならvercel env addです。
逆に、Vercelに登録した値を手元へ降ろすこともできます。
vercel env pull
Environmentsのページには「This will populate the .env.local file in your application directory.(アプリのディレクトリに.env.localファイルを作ります)」とあります。なお環境変数のページのほうには.envと書かれた箇所もあるので、実際に生成されたファイル名を見るのが確実です。
落とし穴1——値を変えても、すでに公開されているものには反映されない
公式に、はっきり書かれています。
Any change you make to environment variables are not applied to previous deployments, they only apply to new deployments.
(環境変数への変更は、過去のデプロイには適用されません。新しいデプロイにだけ適用されます)
設定画面で直しただけでは、本番は変わりません。 直したあとに、もう一度デプロイし直す必要があります。ここは公開したものを、ひとつ前に戻すとも繋がっていて、ロールバックで戻したデプロイにも、あとから変えた値は反映されません。
落とし穴2——接頭辞を付けた瞬間、ブラウザから見える
こちらのほうが実害が大きいかもしれません。
サイトを作る土台(フレームワーク)には、環境変数のうち一部だけをブラウザ側に配る仕組みがあります。配る目印になるのが名前の頭に付ける接頭辞で、AstroならPUBLIC_、Next.jsならNEXT_PUBLIC_、ViteならVITE_です。
Astroの公式ドキュメントの書き方が分かりやすいので引きます。
only environment variables prefixed with
PUBLIC_are available in client-side code for security purposes(安全のため、
PUBLIC_で始まる環境変数だけがクライアント側のコードから使えます)
裏を返すと、PUBLIC_を付けたものは、見に来た全員に配られます。 ブラウザで「ページのソースを表示」すれば読めますし、隠す方法はありません。
動かないときに接頭辞を足したら動いた、というのはよくある道筋です。ただ、それが秘密の鍵だった場合、動くようになったのと引き換えに世界中に配り始めています。
判断の目安は単純で、ブラウザから使う必要が本当にあるかです。データベースの鍵や課金の鍵は、サーバー側だけで足ります。
読めなくしておく(Sensitive)
Vercelには、登録後に値を読み出せなくする設定があります。
Sensitive environment variables are environment variables whose values are non-readable once created.
(Sensitiveな環境変数とは、いったん作ると値を読み出せなくなる環境変数のことです)
公式ページによると、使えるのは本番とプレビューの環境だけで、Developmentには付けられません。既存のものをSensitiveにしたいときは、いったん削除して登録し直します。
ビルドのログについても書かれています。32文字以上の値がログに現れたら[REDACTED]に置き換わるそうです。逆にいえば、31文字以下の短い値はログに現れる可能性があるということでもあります。
エージェントに設定ファイルを読ませるとき
環境変数を扱う作業は、そのままエージェントに頼めます。「Vercelの環境変数にDATABASE_URLを追加して」で通ります。
ただし、設定ファイルを読ませる作業そのものが漏洩経路になります。 画面に表示された時点で会話のログに残るので、伏せたつもりが伏せられていなかった、という事故が起きます。実際に起きた話は伏せたはずのAPIキーが、そのまま画面に表示された話に書きました。
覚えておきたいこと
- 手元で動いて本番で落ちるときは、まず環境変数を疑う
- 設定を直したら、デプロイし直す。 直しただけでは反映されません
PUBLIC_は「配ってよい」の印。 秘密の鍵に付けない- 暗号化されていても、プロジェクトに参加している人からは見える
鍵を1つ登録するだけの作業ですが、置き場所を間違えたときの戻し方がないので、最初だけ丁寧にやっておくと後が楽になります。