環境変数管理ガイド|.envを本番にコミットして事故った話
結論(私の判断基準)
- .envは絶対にコミットしない:私はやりかけた
- .env.exampleをコミットする:変数名だけ、値は空
- 本番の環境変数はホスティングサービスで設定:コードに書かない
- 環境ごとのファイル分けはしない:本番とローカルの2択で十分
私は一度、.envをコミットしかけた。レビューで指摘されて気づいた。
私が.envをコミットしかけた話
新しいプロジェクトを始めた。.envを作った。動いた。嬉しくなってコミットした。
git add .
git commit -m "Initial commit"
プルリクエストを出した。5分後、Slackに通知が来た。
「.envがコミットされてます。APIキー見えてます。」
血の気が引いた。慌ててブランチを削除して、履歴からも消した。
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch .env' HEAD
mainにマージされる前だったから助かった。もしマージされていたら、APIキーを無効化して、フォークを確認して、影響範囲を調査して……考えただけで胃が痛い。
あの5分間が、私の.env運用を変えた。
.envとは
環境変数を定義するファイル。
# .env
DATABASE_URL=postgres://user:password@localhost:5432/mydb
API_KEY=sk-xxxxxxxxxxxxxxxxxxxx
SECRET_KEY=my-secret-key-12345
パスワード、APIキー、シークレットキーなど、コードに書きたくない値を入れる。
私のプロジェクト構成
project/
├── .env # 本物の値(コミットしない)
├── .env.example # 変数名だけ(コミットする)
├── .gitignore # .envを除外
└── ...
以前は.env.local、.env.development、.env.productionを分けていた。やめた。
理由:混乱するから。「この値はどのファイルに書くんだっけ」と毎回迷う。本番の値はVercelで設定する。ローカルは.envに書く。この2択で十分。
.gitignoreの設定(必須)
# .gitignore
.env
.env.local
.env.*.local
**プロジェクト開始時に必ず設定する。**後から追加しても、履歴には残る。
私は今、リポジトリを作ったら最初に.gitignoreを書く。.envを追加してからコミットする癖がついた。
.env.exampleの書き方
# .env.example
# データベース接続
DATABASE_URL=
# 外部API
API_KEY=
STRIPE_SECRET_KEY=
# アプリケーション設定
SECRET_KEY=
NODE_ENV=development
**変数名だけ書く。値は空。**コメントで何を入れるか説明する。
新しいメンバーが参加したとき、.env.exampleをコピーして.envを作る。
cp .env.example .env
# 値を入力
本番環境の設定方法
コードに本番の値を書かない。ホスティングサービスで設定する。
Vercel
Settings → Environment Variables
Netlify
Site settings → Environment variables
AWS
Systems Manager → Parameter Store
Heroku
Settings → Config Vars
私はVercelしか使っていないので、他は調べながらやっている。
よくある失敗(私が見たケース)
失敗1:.envをコミットした
# ❌ 絶対ダメ
git add .env
これは私自身がやりかけた。
失敗2:.env.exampleに本物の値を書いた
# ❌ .env.example に本物の値
API_KEY=sk-xxxxxxxxxxxxxxxxxxxx
.env.exampleはコミットするので、値を書いたら漏洩する。
失敗3:フロントエンドの環境変数にシークレットを入れた
// ❌ フロントエンドでAPIキーを使う
const apiKey = process.env.NEXT_PUBLIC_API_KEY;
NEXT_PUBLIC_やVITE_がついた変数は、ビルド時にクライアントに埋め込まれる。秘密情報を入れてはいけない。
私はこれを知らなかった。Next.jsのドキュメントを読んで初めて気づいた。
失敗4:環境変数の変更を反映し忘れた
本番環境で環境変数を変更したが、アプリを再起動しなかった。変更が反映されない。
環境変数を変更したら再デプロイする。
私の割り切り
| やること | やらないこと |
|---|---|
| .gitignoreに.envを追加 | .env.development/.env.productionの分離 |
| .env.exampleを作る | stagingとproductionの分離 |
| 本番の値はVercelで設定 | 複雑な環境変数管理ツールの導入 |
環境を細かく分けるほど、「どこに何を書くか」で迷う。迷う時間が無駄。
本番とローカルの2択。これで15年やってきて困ったことはない。
撤退基準(ここまでやらない)
- 個人開発では.env.exampleを作らない:自分しか使わないから
- 1人プロジェクトでは.gitignoreだけ設定して終わり
- チーム開発なら.env.exampleを作る:新メンバーが迷わないように
漏洩したときの対処
- すぐにキーを無効化する:漏洩したAPIキーを無効化
- 新しいキーを発行する:別のキーを作成
- Gitの履歴から削除する:
git filter-branchまたはBFG Repo-Cleaner - 影響範囲を確認する:不正利用されていないか確認
履歴から削除しても、フォークやキャッシュに残っている可能性がある。キーの無効化が最優先。
迷ったときの判断
| 迷い | 私の判断 |
|---|---|
| .envをコミットするか | 絶対しない |
| .env.exampleを作るか | チーム開発なら作る。個人なら不要 |
| 本番の値をどこに置くか | ホスティングサービスの環境変数 |
| フロントエンドに秘密情報を置くか | 置かない |
| 環境ごとにファイルを分けるか | 分けない。本番とローカルの2択 |
まとめ
- .envは絶対にコミットしない
- .env.exampleをコミットする(変数名だけ)
- 本番の環境変数はホスティングサービスで設定
- フロントエンドの環境変数に秘密情報を入れない
- 漏洩したらすぐにキーを無効化
- 環境ごとのファイル分けはしない。本番とローカルの2択で十分
私は.envをコミットしかけた。Slackで指摘されて血の気が引いた。あの5分間が、今の運用を作った。