本文へスキップ本文へスキップ
開発環境

環境変数って.envに入れれば安全なの?なんとなく使ってるのでちゃんと整理してみた

環境変数って.envに入れれば安全なの?なんとなく使ってるのでちゃんと整理してみた
目次

環境変数って.envに入れれば安全なの?なんとなく使ってるのでちゃんと整理してみた

Web開発をしていると、かなり早い段階で .env が出てきます。

APIキー。 DBの接続情報。 外部サービスのURL。 メール送信の認証情報。

とりあえずコードへ直接書かず、

API_KEY=xxxx
DATABASE_URL=xxxx

みたいに .env へ入れる。

自分も普段そうしています。

ただ、あるとき改めて考えると、

「.envに入れたら安全」って、何が安全なんだ?

となりました。

.env は便利です。

でも、秘密情報を入れた瞬間に自動で暗号化される金庫ではありません。

この記事では、

環境変数は何のためにあるのか
.envは何を守ってくれるのか
何を守ってくれないのか
Next.jsではどこまでブラウザに見えるのか
GitHub Actionsや本番環境ではどう扱うのか

を整理します。


まず結論。.envは「秘密を守る仕組み」より「コードと設定を分ける仕組み」

.env を理解するとき、自分の中ではここが一番大事でした。

.env = 秘密の金庫

ではなく、

.env = コードとは別に設定値を置くためのファイル

と考えた方が分かりやすいです。

たとえば、コードへ直接こう書いたとします。

const apiKey = "super-secret-api-key"

これをGitへcommitすると、その値はソースコードの履歴へ入ります。

あとから行を消しても、過去のcommitに残る可能性があります。

そこで、

const apiKey = process.env.API_KEY

として、値そのものはコードの外へ出す。

これが環境変数を使う大きな意味です。

開発環境ではローカル用。 ステージングではステージング用。 本番では本番用。

同じコードでも、実行環境ごとに設定値を変えられる。

これがかなり便利です。

環境変数って.envに入れれば安全なの?なんとなく使ってるのでちゃんと整理してみた

.envの中身は普通に文字列。置いただけでは暗号化されない

ここは意外と重要です。

一般的な .env ファイルをテキストエディタで開けば、値はそのまま読めます。

DATABASE_URL=postgres://...
API_KEY=abc123...

つまり、

PCへアクセスできる人
ファイルを読めるプロセス
バックアップを取得できる人

などから絶対に見えなくなる仕組みではありません。

だから、

.envに移したからAPIキーは安全

とは言い切れません。

.env が主に防いでくれるのは、

秘密値をソースコードへ直接書いて、Gitで共有してしまう事故

です。

もちろんそれだけでもかなり大きいです。

ただし「ファイルに書いてある秘密を暗号化して守る」のとは別の話です。


まず絶対に避けたいのは.envをGitへ入れること

Next.jsの公式Docsでも、.env ファイルは基本的にGitへcommitしないよう注意されています。

create-next-app のデフォルト構成でも、.env ファイルが .gitignore の対象になるようになっています。

参考: https://nextjs.org/docs/app/guides/environment-variables⁠(外部サイト)

たとえば、

.env
.env.local
.env.*.local

のように、秘密値を含むローカルファイルを除外します。

ここで注意したいのは、

Gitへpushする前に消せばOK

ではないことです。

一度commitへ入った秘密値は、Git履歴へ残っている可能性があります。

もし本物のAPIキーやトークンを誤ってcommitしたら、

ファイルを消すだけではなく、キー自体を無効化して新しく発行する

ところまで考えた方が安全です。

秘密が漏れた可能性があるなら、「見えない場所へ移したから元のキーも安全」とは考えない方がいいです。


Next.jsではNEXT_PUBLIC_を付けた時点で「秘密ではない」

Next.jsを使っていると、こんな環境変数があります。

NEXT_PUBLIC_API_URL=https://example.com

名前だけ見ると、

.envに書いてあるから外から見えない?

と思いたくなります。

でも NEXT_PUBLIC_ は逆です。

Next.js公式Docsでは、NEXT_PUBLIC_ を付けた環境変数は、ビルド時にブラウザへ配信するJavaScriptへ埋め込まれると説明されています。

参考: https://nextjs.org/docs/app/guides/environment-variables⁠(外部サイト)

つまり、

NEXT_PUBLIC_API_KEY=本当に秘密のキー

みたいなことをすると危険です。

NEXT_PUBLIC_ = ブラウザへ渡してよい値

くらいに考えた方が分かりやすいです。

たとえば、

  • 公開してよいAPIのベースURL

  • 公開前提のAnalytics ID

  • クライアント側で必要な設定値

などです。

一方、

DATABASE_URL=...
PRIVATE_API_KEY=...
SERVICE_ROLE_KEY=...

のような秘密値はサーバー側だけで扱います。

Next.jsでは、NEXT_PUBLIC_ を付けていない環境変数は基本的にサーバー側で利用します。


「サーバー側に置いた」だけでも安心しすぎない

ここまでだと、

NEXT_PUBLIC_を付けなければ安全なのか

となります。

これも「絶対安全」とまでは言えません。

サーバー側だけで扱うことで、ブラウザへ直接配信されるリスクは減ります。

でも、

  • ログに出力する

  • エラーメッセージへ含める

  • APIレスポンスへ間違えて含める

  • Server ComponentからClient Componentへ渡す

  • デバッグ用の画面へ表示する

などをすれば漏れる可能性があります。

Next.jsのData Securityガイドでも、秘密値をクライアントへ渡さないことや、サーバー専用コードを明確に分離する考え方が説明されています。

参考: https://nextjs.org/docs/app/guides/data-security⁠(外部サイト)

なので、

環境変数にした = どこからも見えない

ではなく、

環境変数にした上で、使う場所も限定する

ところまで必要です。


ローカルの.envとGitHub ActionsのSecretsは役割が違う

開発中は .env.local で十分なことも多いです。

でもCIでGitHub Actionsを動かすと、GitHub上のrunnerには自分のPCの .env.local はありません。

そこで使えるのがGitHub Actions Secretsです。

GitHubでは、

  • Repository

  • Environment

  • Organization

単位でSecretsを管理できます。

参考: https://docs.github.com/en/actions/concepts/security/secrets⁠(外部サイト)

workflow側では、

env:
API_KEY: ${{ secrets.API_KEY }}

のようにして使います。

大事なのは、

秘密値そのものをworkflowファイルへ書かない

ことです。

GitHubのSecretsは、workflowで明示的に参照したときに利用できます。

またEnvironment単位でSecretsを分けられるので、

staging用
production用

のように分離できます。

ローカルとCIで同じ「環境変数」という言葉を使いますが、

値を保管する場所は別

です。


本番環境でも.envファイルを置けばいいのか

自前サーバーなら、本番サーバーへ .env を配置する構成もあります。

ただし、その場合は、

  • ファイル権限

  • サーバーへ入れる人

  • バックアップ

  • デプロイ方法

  • ログ

  • 秘密値の更新方法

まで自分で管理する必要があります。

一方、Vercelのようなホスティングサービスには環境変数を管理する仕組みがあります。

Vercelでは2026年8月から環境変数が Config / Secret の2種類に整理され、Secretは保存後にメンバーが値を再表示できない用途として案内されています。

参考: https://vercel.com/changelog/environment-variables-now-use-config-and-secret-types⁠(外部サイト)

さらにProduction / Preview / Developmentなど、環境ごとに値を分けられます。

つまり本番では、

秘密値をリポジトリや配布物へ入れず、実行環境側から渡す

という考え方が基本になります。

環境変数って.envに入れれば安全なの?なんとなく使ってるのでちゃんと整理してみた

開発・ステージング・本番で同じキーを使い回さない

これも環境変数を整理するときに大事です。

たとえば外部APIのキーが一つしかなく、

ローカル
ステージング
本番

ですべて同じものを使っていたとします。

すると、ローカルPCで漏れたキーが、そのまま本番権限を持っている可能性があります。

できるサービスなら、

  • 開発用

  • ステージング用

  • 本番用

で資格情報を分ける方が安全です。

権限も、

とりあえず全部できるAPIキー

より、

この処理だけできるAPIキー

にした方が、漏れたときの影響を減らせます。

前の記事で暗号鍵を調べたときにも感じましたが、

秘密値は「どこに置くか」だけでなく、「何ができる鍵なのか」まで見る

必要があります。


.env.exampleは何のためにある?

チーム開発やGitHubのリポジトリで、

.env.example

を置くことがあります。

たとえば、

DATABASE_URL=
API_KEY=
NEXT_PUBLIC_API_URL=

のように、値を空にしてキー名だけ共有するファイルです。

これなら、

このプロジェクトを動かすには、どの環境変数が必要なのか

を共有できます。

実際の秘密値は入れない。

設定項目の設計図だけをGitで管理する。

という役割です。

個人的にはこれがかなり分かりやすいです。

READMEへ大量に書くより、

必要な環境変数そのものが一覧で見える

ので、環境構築時の抜けも減らせます。


環境変数をログへ出すのは地味に怖い

開発中に、

console.log(process.env)

みたいなことをしたくなる場面があります。

値がちゃんと入っているか確認したいからです。

でも本番やCIでこれをやると、ログに秘密値を残す可能性があります。

GitHubなどのサービスにはSecretsをマスクする仕組みがありますが、

マスクしてくれるから何を出してもOK

とは考えない方がいいです。

加工した値。 一部だけ切り出した値。 別形式へ変換した値。

などは意図どおり隠れない可能性があります。

確認したいなら、

console.log(Boolean(process.env.API_KEY))

のように、

値そのものではなく「存在するか」だけを見る

方が安全です。

秘密情報をデバッグしやすくするために表示した結果、そのログが別の漏えい経路になる。

これは避けたいところです。


環境変数には「秘密」と「ただの設定」が混ざっている

ここも整理するとかなり分かりやすくなりました。

環境変数に入れるものが、全部秘密とは限りません。

公開されても問題ない設定

NEXT_PUBLIC_SITE_URL=https://example.com
NEXT_PUBLIC_ANALYTICS_ID=xxxx

外へ出してはいけない秘密

DATABASE_URL=...
PAYMENT_SECRET_KEY=...
PRIVATE_API_KEY=...

両方とも環境変数です。

でも扱いはまったく違います。

だから、

環境変数だから安全か?

ではなく、

この値は秘密なのか。秘密なら、どこまで見えていいのか。

を最初に決める方がいいです。


自分なら環境変数をこの4段階で確認する

環境変数を追加するとき、自分なら最低限この4つを確認します。

1. これは公開していい値か

ブラウザから見えても問題ないのか。

秘密なら NEXT_PUBLIC_ のようなクライアント公開の仕組みへ乗せない。

2. Gitへ入っていないか

.env が .gitignore されているか。

過去にcommitしていないか。

3. 環境ごとに分ける必要があるか

local / staging / productionで値や権限を分離できるか。

4. 漏れたときに交換できるか

キーやトークンをローテーションできるか。

どこで使っているか把握できているか。

この4つを見るだけでも、

「.envに入れたからOK」

からかなり先へ進めます。


.envは金庫ではない。でも使う意味はかなり大きい

今回整理してみて、.env の役割はかなりシンプルでした。

コードと設定を分ける。
秘密値をGitへ直接入れない。
環境ごとに違う値を渡せるようにする。

これだけでも十分重要です。

ただし、

.envファイル自体が秘密を暗号化して守ってくれるわけではない。

Next.jsなら、NEXT_PUBLIC_ を付ければブラウザへ出ます。

CIならGitHub Actions Secretsのような仕組みがあります。

ホスティング側にもSecret管理があります。

そして秘密値を使うコード自体も、クライアントへ漏らさないようにしないといけません。

だから自分の中では、

.envは「秘密にする場所」ではなく、「秘密をコードから分離する入口」

くらいに考えるのが一番しっくりきました。

環境変数を追加するときに、

この値は誰から見える?
どこに保存される?
どの環境で使う?
漏れたら交換できる?

まで考える。

そこまでやって初めて、「環境変数として安全に扱う」に近づくと思います。

過去の記事から 1 本

全 12 本のうち 2 本目の記事

about

このブログについて

Web 開発・インフラ・AI を手を動かして試した記録が中心です。うまくいった話もハマった話も、仕事や日々のこともそのまま書きます。