Complat / Cloudflare Deployment Guide
.env の扱い方自分でつくったツールを、はじめてインターネットに公開する人のための手引き。
「何を、どの順番で、AIにどう言えばいいか」と「鍵(.env)をどう守るか」に絞ってまとめています。
技術的な話をする前に、これだけ守れば大きな事故は起きません。逆に言えば、事故はほぼこの3つの違反から起きます。
パスワードやAPIキーは、プログラム本体とは別の場所に置く。ソースコードに直接書かない。これが .env の存在理由そのものです。
画面(フロントエンド)に埋め込んだ値は、どんなに隠しても訪問者に読まれます。「難読化したから大丈夫」はありません。秘密はサーバー側(Cloudflare Workers)にだけ置きます。
コードを書く・直す・テストする、はAIに任せてよい。しかし「インターネットに出す」瞬間だけは人間が承認する。取り消しの効かない操作だからです。
最初につまずくのは、たいてい「誰が何をしているのか分からない」ことです。関わるのは4者だけです。
| 登場人物 | 役割 | ひとことで言うと |
|---|---|---|
| あなたのPC | 作業場所。ソースコードと鍵の原本がある | 自分の机。ここは外から見えない |
| Claude Code Claudeデスクトップアプリの 「Code」タブ/内蔵ターミナル | あなたの指示でコードを書く・実行する | 手を動かす担当。指示した範囲しかやらない |
| Cloudflare | 公開されたツールが実際に動く場所 | お店の物件。ここに置いたものが世界に見える |
| GitHub(使う場合) | コードの保管・履歴管理 | 共有の書庫。ここに鍵を入れるのが最悪の事故 |
【あなたのPC】 【Cloudflare】
┌────────────────────┐ ┌────────────────────┐
│ ソースコード │ ─ 公開 ─▶ │ Pages = 画面 │
│ .env(鍵の原本) │ │ Workers = 処理 │
│ ↑ ここに置く │ │ D1 = データ │
└────────────────────┘ │ Secrets = 鍵の写し │
│ └────────────────────┘
│ Claude Code が読み書きする ▲
▼ │
┌────────────────────┐ 鍵はコードと別ルートで
│ Claude Code │ 1回だけ登録する
└────────────────────┘
✕ .env は「公開」の矢印には絶対に乗せない
Claudeデスクトップアプリ(Mac / Windows)を使う前提で書いています。アプリの中に、性格の違う2つの操作場所があります。この2つを区別できると、以降の説明が一気に読みやすくなります。
| 場所 | 何をするところか | この資料での書き方 |
|---|---|---|
| チャット欄 | 日本語でAIに依頼する。コードを書く・直す・調べるはここ | 「〜と送る」「指示する」 |
| ターミナル | コマンドを自分の手で打つ。鍵の登録と公開はここ | 「〜を実行する」 |
ターミナルは、Claudeデスクトップアプリに内蔵されているものを使ってもいいですし、OS標準のものでも構いません。同じことができます。
| OS | OS標準のターミナル |
|---|---|
| Mac | 「ターミナル」アプリ(command + スペース →「ターミナル」で検索) |
| Windows | 「PowerShell」または「ターミナル」(スタートボタンを右クリック → 一覧にあります) |
ツールが動くには、たいてい「秘密の文字列」が必要になります。メール送信サービスのAPIキー、データベースのパスワード、LINEの接続トークン——こういうものです。
これをソースコードに直接書くと、次の問題が起きます。
そこで、秘密の文字列だけを1つのファイルに切り出す。それが .env(ドット・エンブ)です。
RESEND_API_KEY=re_abc123xxxxxxxxxxxxxxxx
DATABASE_URL=xxxxxxxxxxxxxxxxxxxx
SESSION_SECRET=xxxxxxxxxxxxxxxxxxxx
プログラム側は「RESEND_API_KEY という名前の値を持ってきて」とだけ書きます。中身が何かは知りません。だからコードは人に見せても安全になり、.env だけを厳重に守ればよくなります。
先頭が . のファイルは、Mac・Linuxでは隠しファイル扱いになり、通常のフォルダ表示に出てきません。うっかりメールに添付する事故を減らすための慣習です。
Finderで対象のフォルダを開いた状態で、次のキーを押します。
command + shift + .(ピリオド)
押すたびに表示 ⇄ 非表示が切り替わるトグルです。隠しファイルが表示されているときは、アイコンが少し薄く表示されます。確認が終わったら、もう一度同じキーを押して非表示に戻しておくのが安全です。
| やりたいこと | 操作 |
|---|---|
| Finderで一時的に表示 | command + shift + .(もう一度押すと非表示) |
| 常に表示させる | ターミナルでdefaults write com.apple.finder AppleShowAllFiles -bool truekillall Finder※戻すときは true を false にして同じ2行を実行 |
| ターミナルで一覧を見る | ls -la(-a が「隠しファイルも全部」の意味) |
.env は隠しファイルになりません。 「先頭がピリオドなら隠す」というのはMac・Linuxの決まりごとで、Windowsは別方式(ファイルごとの「隠し属性」)を使うためです。つまり .env はエクスプローラーに最初から見えています。
それでも表示設定を触る必要があるのは、node_modules や .git といった「隠し属性が付いたフォルダ」を確認したいときです。
| バージョン | 操作 |
|---|---|
| Windows 11 | エクスプローラー上部の [表示] → [表示] → [隠しファイル] にチェック |
| Windows 10 | エクスプローラー上部の [表示]タブ → [隠しファイル] のチェックボックスをON |
| 共通(確実) | コントロールパネル →「エクスプローラーのオプション」→[表示]タブ → 「隠しファイル、隠しフォルダー、および隠しドライブを表示する」を選択 |
| PowerShellで見る | Get-ChildItem -Force(-Force が「隠しも含める」の意味) |
.txt など)を隠します。この状態でメモ帳から保存すると、.env のつもりが実際は .env.txt になり、画面上は「.env」に見えるのに、プログラムからは読めないという事故が起きます。.env.txt になる事故)も起きません。プロジェクト直下に .dev.vars という空のファイルを作ってください。中身は私が自分で書きます。open -e .dev.vars(Mac)/ notepad .dev.vars(Windows)と実行すればエディタで開けます。
| 値の例 | .envへ | 理由 |
|---|---|---|
| APIキー・トークン | 入れる | 漏れると他人に使われる・課金される |
| DBのパスワード・接続文字列 | 入れる | データを全部抜かれる |
| セッション用の秘密鍵 | 入れる | ログインを偽装される |
| 管理者のメールアドレス | 入れる | 秘密ではないが、環境ごとに変えたい |
| ツールの名前・色・文言 | 入れない | 秘密ではない。コードに書いてよい |
公開URL(xxx.pages.dev) | 入れない | 誰でも見える情報 |
.env。困らないならコードに書いてよい。
ここが初心者が最も混乱するところです。「.env に書けば全部OK」ではありません。 動く場所が3つあるので、鍵の置き場所も3つあります。
| どこで動く | 鍵の置き場所 | 登録のしかた |
|---|---|---|
| ①自分のPC 開発中・テスト中 |
.env(Workersなら .dev.vars) |
テキストエディタで書くだけ |
| ②Cloudflare上のサーバー Workers=処理担当 |
CloudflareのSecrets | wrangler secret put KEY名またはダッシュボードで入力 |
| ③訪問者のブラウザ Pages=画面担当 |
置けない | 秘密は一切置かない。必要な処理は②に頼む |
.env をCloudflareにアップロードする仕組みはありません(それが安全設計です)。同じ鍵を、手元用とCloudflare用に2回登録する。これが正しい手順です。
# 手元用(ファイルに書く)
echo 'RESEND_API_KEY=re_abc123' >> .dev.vars
# Cloudflare用(コマンドで送る/画面には残らない)
npx wrangler secret put RESEND_API_KEY
# → 入力を求められるので、そこに貼る
フロントエンド(画面)のビルドツールには、VITE_ や NEXT_PUBLIC_ といった接頭辞のついた環境変数をそのままブラウザに埋め込む機能があります。便利ですが、ここにAPIキーを入れると訪問者全員に配布したのと同じです。
VITE_OPENAI_API_KEY=sk-xxxx と書いてPagesに公開 → ブラウザの検証ツールで誰でも読める → 第三者に使われ、API利用料が請求される。VITE_ / NEXT_PUBLIC_ / PUBLIC_ の変数は「公開してよい値」専用だと覚えてください。
wrangler.toml はCloudflareの設定ファイルで、コードと一緒にGitHubへ上がります。ここの [vars] セクションに書いた値は平文でそのまま残ります。
name = "mendan-tool"
compatibility_date = "2026-08-01"
[vars]
APP_NAME = "面談記録" # ← OK(秘密ではない)
# API_KEY = "re_abc123" # ← 絶対にダメ。secret put を使う
[[d1_databases]]
binding = "DB"
database_name = "mendan-tool-db"
database_id = "xxxxxxxx-xxxx-xxxx" # ← ID自体は秘密ではないが、公開リポジトリなら伏せる運用も可
まずは、ツールごとに1つのフォルダを作ります。プロジェクト名は英数字とハイフンだけ(日本語やスペースは避ける)。
mendan-tool/ ← プロジェクトのフォルダ
├── .env ← 鍵。Gitに入れない
├── .dev.vars ← Workers用の鍵。Gitに入れない
├── .env.example ← 「鍵の名前だけ」の見本。Gitに入れる
├── .gitignore ← 何を除外するかの指定
├── wrangler.toml ← Cloudflareの設定
├── package.json
├── src/ ← プログラム本体
└── public/ ← 画像・CSSなど
.gitignore は「このファイルはGitに含めない」という指定です。コードを書き始める前に作ってください。1回でもコミットしてしまうと履歴に残り、消すのが面倒になります。
# 鍵・環境変数(最重要)
.env
.env.*
!.env.example
.dev.vars
.dev.vars.*
*.key
*.pem
# 依存パッケージ・ビルド成果物
node_modules/
dist/
.wrangler/
# OS
.DS_Store
中身を空にした「鍵の一覧表」です。これだけはGitに入れます。あとから自分が見返すときも、他の人に渡すときも、「何の鍵が必要なのか」が分かるようになります。
# このファイルをコピーして .env を作り、値を入れてください
# cp .env.example .env
RESEND_API_KEY= # メール送信用。https://resend.com で取得
SESSION_SECRET= # ログイン用の秘密鍵。openssl rand -hex 32 で生成
ADMIN_EMAIL= # 管理者のメールアドレス
より安全にするなら、鍵の本体をプロジェクトフォルダの外に置き、シンボリックリンク(ショートカット)を張る方法があります。クラウド同期フォルダ(Google Drive / Dropbox / iCloud)の中で作業する場合は、この方法を強く推奨します。同期フォルダに .env を置くと、鍵がクラウドにアップロードされてしまうためです。
# 1. 同期されない場所に鍵の実体を置く
mkdir -p ~/secrets/mendan-tool
open -e ~/secrets/mendan-tool/.dev.vars # テキストエディットで開いて値を書く
chmod 600 ~/secrets/mendan-tool/.dev.vars # 自分だけが読める権限に
# 2. プロジェクト側からリンクを張る
cd ~/projects/mendan-tool
ln -s ~/secrets/mendan-tool/.dev.vars .dev.vars
# 3. 確認(.dev.vars -> /Users/.../.dev.vars と出れば成功)
ls -la .dev.vars
# 1. 同期されない場所に鍵の実体を置く
mkdir "$HOME\secrets\mendan-tool"
notepad "$HOME\secrets\mendan-tool\.dev.vars" # メモ帳で開いて値を書く
# 2. プロジェクト側からリンクを張る
cd "$HOME\projects\mendan-tool"
New-Item -ItemType SymbolicLink -Path ".dev.vars" `
-Target "$HOME\secrets\mendan-tool\.dev.vars"
# 3. 確認
Get-Item .dev.vars | Select-Object Name, LinkTarget
.dev.vars.txt になります。ファイル名を "..dev.vars" のように引用符で囲んで保存するのが確実です。
~/projects/)にプロジェクトを置いてさえいれば、.gitignore だけで十分に安全です。
ここからは実際にコピーして使える指示文です。すべてClaudeデスクトップアプリのチャット欄に貼り付けて送るものです。AIは「言われていないこと」は基本的にやりません。逆に言えば、守ってほしいルールは最初に明文化しておく必要があります。
CLAUDE.md というファイルを置いておけば会話のたびに自動で読み込まれます。下のルールをプロジェクト直下の CLAUDE.md に書いて保存してください。(続けて6-1の本文を貼る)
新しいプロジェクトを始めたら、まずこれを送ります。以降の会話全体に効きます。
このプロジェクトのルールを宣言します。以降、必ず守ってください。 【鍵の扱い】 1. APIキー・パスワード・トークンをソースコードに直接書かないこと。 必ず環境変数(.env / .dev.vars / Cloudflare Secrets)経由で読むこと。 2. 私が鍵の値をチャットに貼ることはありません。 鍵が必要なときは「.env に○○という名前で書いてください」と ファイル名と変数名だけを指示してください。 3. .env / .dev.vars の中身をチャットに出力しないこと。 存在確認は「あるかないか」だけを報告してください。 4. フロントエンドのコード(ブラウザに届くコード)に秘密の値を 一切埋め込まないこと。VITE_ / NEXT_PUBLIC_ 接頭辞の変数には 公開してよい値だけを入れること。 【最初にやってほしいこと】 - .gitignore を作り、.env / .env.* / .dev.vars / node_modules / dist / .wrangler / .DS_Store を除外してください(.env.example は除外しない)。 - .env.example を作り、必要な環境変数の「名前と説明だけ」を 空の値で列挙してください。 【公開(デプロイ)】 - wrangler deploy / wrangler pages deploy などの公開コマンドは、 実行前に必ず「何を・どこに・どのURLで公開するか」を提示し、 私の承認を得てから実行してください。無断で実行しないこと。
ポイントは「値を渡さない」こと。AIには「箱を作れ」とだけ言い、中身は自分で入れます。
メール送信機能を追加します。Resend の API キーが必要です。 - 変数名は RESEND_API_KEY にしてください。 - .env.example に空の項目と説明コメントを追加してください。 - コードからは環境変数経由で読む形にしてください。 - 実際の値は私が自分で .dev.vars に書きます。 値を聞かないでください。また、書き終わったかどうかも ファイルの存在確認だけで判断してください。
手元の .dev.vars に入っている変数を、Cloudflare 側の Secret として 登録したいです。実行すべきコマンドを一覧で出してください。 - コマンドは私が自分のターミナルで実行します。 - あなたが実行する必要はありません。 - 値はコマンドの引数に含めず、対話入力で渡す形にしてください。
提示されるのは、こういうコマンドのはずです。
npx wrangler secret put RESEND_API_KEY
npx wrangler secret put SESSION_SECRET
# 実行すると入力欄が出るので、そこに値を貼る。
# コマンド履歴には値が残らない。
npx wrangler secret put KEY --text "re_abc123"~/.zsh_history)に平文で残り続けます。必ず対話入力を使ってください。
公開の準備ができているか、実行前に確認してください。 1. git status で .env / .dev.vars が追跡対象に入っていないこと 2. git log で過去に鍵らしき文字列がコミットされていないこと ("KEY" "SECRET" "TOKEN" "PASSWORD" などで grep) 3. ビルド後の成果物(dist/ など)に秘密の値が含まれていないこと 4. Cloudflare 側に必要な Secret が全部登録されていること (wrangler secret list で名前だけ確認) 確認結果を報告したうえで、公開するプロジェクト名とURLを提示し、 私が「OK」と答えてから実行してください。
指示だけでは不安な場合、Claude Codeには「特定のコマンドを機械的にブロックする」仕組み(Hooks/permissions)があります。.claude/settings.json に拒否リストを書いておけば、AIがうっかり実行しようとしても止まります。
{
"permissions": {
"deny": [
"Bash(wrangler deploy:*)",
"Bash(wrangler pages deploy:*)",
"Bash(git push:*)",
"Read(./.env)",
"Read(./.dev.vars)"
]
}
}
各ステップに、どこで操作するかを付けています。ターミナル は自分の手で打つ場所、チャット欄 はAIに日本語で頼む場所です。
npx というコマンドを使うために必要です。nodejs.org から LTS版 をダウンロードしてインストール。node -v を実行して v20.x.x のような数字が出ればOK。
npx wrangler login を実行。ブラウザが開くので「Allow」を押す。これで手元のPCとCloudflareがつながります。npx wrangler whoami。自分のメールアドレスが出れば成功。.gitignore と .env.example、CLAUDE.md がこの時点で完成します。
npx wrangler dev を動かしながらブラウザで確認する。この段階ではまだ誰にも公開されていません。
.dev.vars に自分で値を書く。チャット欄には貼らない。
npx wrangler secret put 変数名 を必要な数だけ実行し、対話入力で値を貼る。
npx wrangler pages deploy dist などを、内容を確認したうえで実行。xxxxx.pages.dev というURLが発行されます。
.env をコミットすると、あとから削除しても履歴には残り続けます。最初の git init の直後に .gitignore を作るのが鉄則。VITE_ / NEXT_PUBLIC_ 接頭辞の変数はブラウザに配布されます。「難読化」「Base64エンコード」も無意味です。wrangler secret put で。やってしまったときは、順番が決まっています。あわてて履歴を消すのは2番目以降です。
.dev.vars と Cloudflare の Secret の両方を新しい値に更新する。
git filter-repo 等)は影響が大きいので、詳しい人と一緒にやる。
.gitignore に .env / .env.* / .dev.vars が入っているgit status で .env 系が追跡対象に出てこないKEY SECRET TOKEN PASSWORD で検索して、直書きがないdist/ など)を同じ語で検索して、秘密が混ざっていないwrangler.toml の [vars] に秘密が書かれていないwrangler secret list)noindex 設定が入っている| 用語 | 意味 |
|---|---|
| デプロイ | 手元で作ったものを、インターネット上の公開場所に置くこと。「公開する」とほぼ同義 |
| 環境変数 | プログラムの外側から渡す設定値。.env に書くのはこれ |
| APIキー | 外部サービスを使うための身分証。漏れると他人があなたの名前で使える(=課金される) |
| Cloudflare Pages | 画面(HTML/CSS/JS)を置く場所。訪問者のブラウザに届く側 |
| Cloudflare Workers | 処理を実行するサーバー。秘密の鍵を安全に置けるのはここ |
| Cloudflare D1 | データを保存するデータベース |
| Secrets | Cloudflare側に登録した鍵。一度入れると画面から読み出せなくなる(=安全) |
| wrangler | Cloudflareを操作するコマンドツール。「ラングラー」と読む |
| .gitignore | 「このファイルはGitに含めない」という指定ファイル |
| コミット | 変更をGitの履歴に記録すること。記録したものは消しにくい |
| フロントエンド | 訪問者のブラウザで動く部分。中身は全部見られる |
| バックエンド | サーバー側で動く部分。訪問者からは中身が見えない |
| シンボリックリンク | 別の場所にあるファイルへのショートカット。実体は動かさずに参照だけ張る |
| Revoke | 発行済みの鍵を無効化すること。漏洩時の最優先アクション |