Contents
📖 目次
- 前提条件と全体像
- 環境構築 – Wrangler と KV の設定
- ローカル開発とシンプルな REST API 実装
- 認証・永続化 – KV と Durable Objects のベストプラクティス
- CI/CD – GitHub Actions で自動デプロイ & シークレット管理
- 高度なトピック – Python ランタイム・セキュリティ・コスト最適化・モニタリング
- まとめと次のステップ
前提条件と全体像
| 項目 | 内容 |
|---|---|
| 対象読者 | フロントエンド中心の開発者、スタートアップエンジニア、サーバーレスに興味がある方 |
| 前提知識 | JavaScript/TypeScript の基本、GitHub と CI/CD の概念 |
| 必要ツール | Node.js ≥ 20, npm (or pnpm), Git, Cloudflare アカウント, GitHub リポジトリ |
全体像
1. wrangler で Workers プロジェクトを作成 → ローカル (wrangler dev) でテスト。
2. KV に API キー(暗号化または Secret)を格納し、Durable Objects でデバイス/セッション情報を管理。
3. GitHub Actions が push/merge を検知して wrangler publish → 本番環境へ自動デプロイ。
4. Cloudflare の組込み WAF・Rate Limiting と Workers Insights で運用監視。
⚠️ 注意:本稿の数値(リクエスト上限、CPU 料金等)は執筆時点(2024‑08) の公式情報です。最新情報は必ず Cloudflare の Pricing ページ を確認してください。
環境構築 – Wrangler と KV の設定
1. Wrangler のインストールとプロジェクト作成
|
1 2 3 4 |
npm install -g wrangler # または npm i -D wrangler wrangler init edge-auth-api --type=javascript cd edge‑auth‑api |
wrangler.toml が自動生成されます。2024 年以降は compatibility_date と [vars] / [kv_namespaces] の明示が必須です。
2. wrangler.toml(最新版)例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
name = "edge-auth-api" main = "src/index.ts" compatibility_date = "2024-07-01" # 最新ランタイムを固定 [build] command = "npm run build" # 非機密設定はここに書く [vars] ENVIRONMENT = "production" RATE_LIMIT_PER_MIN = "1000" # KV バインディング(名前空間は Cloudflare ダッシュボードで作成) [kv_namespaces] binding = "KV_AUTH" id = "<YOUR_KV_NAMESPACE_ID>" # Durable Objects の宣言 [[durable_objects]] name = "SESSION_STORE" class_name = "SessionDO" |
ポイント
- compatibility_date がないとデプロイ時にエラーになります。
binding名はコード側 (env.KV_AUTH) と同一にしてください。
3. Cloudflare アカウント作成・無料プランの確認
- https://dash.cloudflare.com/sign-up にアクセスしメール認証でアカウントを取得。
- ダッシュボード左メニュー Workers → Create a Service を選択し「Free」プランでサービスを作成。
| プラン | 月間リクエスト上限 | KV ストレージ上限 |
|---|---|---|
| Free | 100 000 リクエスト | 1 GB |
| Workers Bundled (従量課金) | 無制限($0.000015 / ms) | 5 GB + 追加課金 |
出典:公式ドキュメント https://developers.cloudflare.com/workers/platform/limits/
ローカル開発とシンプルな REST API 実装
fetch ハンドラの基本形(TypeScript)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// src/index.ts export default { async fetch(request: Request, env: Env): Promise<Response> { const url = new URL(request.url); // GET /hello?name=xxx if (request.method === "GET" && url.pathname === "/hello") { const name = url.searchParams.get("name") ?? "World"; return new Response(`Hello, ${name}!`, { status: 200 }); } // POST /echo (JSON をそのまま返す) if (request.method === "POST" && url.pathname === "/echo") { const body = await request.json(); return new Response(JSON.stringify(body), { status: 200, headers: { "Content-Type": "application/json" }, }); } // 未マッチは 404 return new Response("Not Found", { status: 404 }); }, }; |
Env 型は src/env.d.ts に次のように定義すると、KV バインディングや Durable Object が補完されます。
|
1 2 3 4 5 |
interface Env { KV_AUTH: KVNamespace; SESSION_STORE: DurableObjectNamespace; } |
ローカルテスト
|
1 2 3 4 |
npm ci # 依存関係インストール wrangler dev # http://127.0.0.1:8787 がローカルエンドポイントになる curl "http://127.0.0.1:8787/hello?name=Cloudflare" |
console.log の出力はターミナルに即座に表示されます。デバッグ時は wrangler tail で実稼働環境のログもリアルタイム取得可能です。
認証・永続化 – KV と Durable Objects のベストプラクティス
1. API キー管理(暗号化または Secret 推奨)
重要:KV は平文で保存されるため、機密情報を直接格納すると漏洩リスクがあります。
以下のいずれかの方法で対策してください。
| 方法 | メリット | 実装例 |
|---|---|---|
| Wrangler Secret(Cloudflare 側暗号化) | 完全に暗号化・ローテーションが容易 | wrangler secret put API_MASTER_KEY → 取得したキーは Workers の env.API_MASTER_KEY で参照 |
| 自前暗号化 + KV | アプリ側で暗号方式を選択可能(例:AES‑GCM) | 暗号化関数 encrypt(key, plain) と復号 decrypt(key, cipher) を実装し、env.KV_AUTH.put() に格納 |
Secret 版サンプル
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// src/auth.ts export async function authorize(request: Request, env: Env): Promise<Response | null> { const apiKey = request.headers.get("x-api-key"); if (!apiKey) return new Response("Missing API key", { status: 401 }); // Cloudflare Secret に保存したマスターキーでハッシュ比較 const expectedHash = await crypto.subtle.digest( "SHA-256", new TextEncoder().encode(env.API_MASTER_KEY) ); const providedHash = await crypto.subtle.digest( "SHA-256", new TextEncoder().encode(apiKey) ); if (Buffer.from(expectedHash).toString("hex") !== Buffer.from(providedHash).toString("hex")) { return new Response("Invalid API key", { status: 403 }); } return null; // 認証成功 } |
出典:Cloudflare Docs – Secrets
2. Durable Objects でセッション/HWID 管理
Durable Objects は単一インスタンスがシングルスレッドで実行されるため、競合が起きにくい点が KV と大きく異なります。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// src/session_do.ts export class SessionDO { constructor(private state: DurableObjectState, private env: Env) {} async fetch(request: Request): Promise<Response> { const url = new URL(request.url); if (url.pathname === "/session/create") { const sessionId = crypto.randomUUID(); await this.state.storage.put("sessionId", sessionId); return new Response(JSON.stringify({ sessionId }), { status: 201 }); } // セッション取得 const sessionId = await this.state.storage.get<string>("sessionId"); if (!sessionId) return new Response("No session", { status: 404 }); return new Response(JSON.stringify({ sessionId }), { status: 200 }); } } |
ハンドラ側からの呼び出し例:
|
1 2 3 |
const stub = env.SESSION_STORE.idFromName(userId).getStub(); const resp = await stub.fetch("https://dummy/session/create", { method: "POST" }); |
ポイント:Durable Objects のインスタンスは
idFromNameでユーザーごとに固定でき、同時書き込みがシリアライズされます。
CI/CD – GitHub Actions で自動デプロイ & シークレット管理
1. ワークフローファイル deploy.yml
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
name: Deploy Workers on: push: branches: [main] pull_request: types: [closed] jobs: deploy: if: github.event.pull_request.merged == true || github.ref == 'refs/heads/main' runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v3 with: node-version: "20" - name: Install dependencies run: npm ci # Cloudflare API Token を GitHub Secrets から取得し、wrangler に渡す - name: Publish Workers env: CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }} CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }} run: npx wrangler publish --env production |
シークレットの設定手順
- Cloudflare ダッシュボードで API Tokens → Create Token(「Edit Workers」権限)を作成。
- GitHub リポジトリの Settings > Secrets and variables > Actions に
CF_API_TOKENとCF_ACCOUNT_IDを追加。
出典:GitHub Docs – Encrypted secrets
2. 環境変数 vs シークレットの使い分け
| 種類 | 用途 | 保存場所 |
|---|---|---|
Vars (wrangler.toml の [vars]) |
本番/ステージングごとの設定(例:レートリミット) | リポジトリに平文で保存(機密情報は NG) |
Secrets (wrangler secret put, GitHub Secrets) |
API キー、DB パスワード、JWT シークレット等 | Cloudflare 側または GitHub の暗号化ストレージ |
ベストプラクティス:機密情報は必ず Secret に格納し、コード中にハードコーディングしないこと。
高度なトピック – Python ランタイム・セキュリティ・コスト最適化・モニタリング
1. Python (3.11) ランタイムで Workers を書く
2024‑07 以降、Cloudflare は wasm‑compatible Python 3.11 を公式サポートしています。
制限は主に「C 拡張不可」「サイズ上限 10 MB(gzip 後)」です。
worker.py の例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import json from workers import Response, Request def on_fetch(request: Request, env): url = request.url if "/ping" in url: return Response("pong", status=200) if request.method == "POST" and "/echo" in url: payload = json.loads(request.text()) return Response(json.dumps(payload), headers={"Content-Type": "application/json"}, status=200) return Response("Not Found", status=404) |
wrangler.toml へ Python 用ルールを追加:
|
1 2 3 4 |
[[rules]] type = "CompiledWasm" globs = ["worker.py"] |
出典:公式ブログ – Python on Workers (2024)
2. 組込みセキュリティ機能の設定
| 機能 | 設定場所 | 主な用途 |
|---|---|---|
| WAF | Dashboard → Firewall → Managed Rules | OWASP Top 10 の自動防御 |
| Rate Limiting | Dashboard → Firewall → Tools → Rate Limiting | 秒間リクエスト上限のカスタム設定 |
| DDoS 防御 | デフォルトで有効 | 大量トラフィックから保護 |
カスタムレートリミット YAML(例)
|
1 2 3 4 5 6 7 8 9 10 11 |
name: api-rate-limit description: "Edge API の過剰アクセス防止" threshold: 1000 # 秒間上限 period: 60 # 集計ウィンドウ (秒) action: mode: block response_body: '{"error":"Too many requests"}' match: url: "https://api.example.com/*" methods: ["GET", "POST"] |
出典:Cloudflare Docs – Rate Limiting
3. コスト最適化と有料プランの目安
| プラン | 月間リクエスト上限 | KV ストレージ | CPU 時間単価 |
|---|---|---|---|
| Free | 100 k | 1 GB | 無料枠内 (合計 10 s) |
| Workers Bundled | 無制限 | 5 GB + 追加課金 | $0.000015 / ms |
| Enterprise | カスタム SLA | 任意 | ボリューム割引あり |
コスト削減テクニック
- Cache API を活用し、同一 GET のレスポンスを Edge にキャッシュ(TTL 10 s 推奨)。
wrangler.tomlのminify = trueとwebpack/esbuildの Tree‑shaking でバンドルサイズ削減。- KV の TTL を設定し、不要データを自動削除(例:
env.KV_AUTH.put(key, value, { expirationTtl: 86400 }))。
出典:公式プラン比較 https://developers.cloudflare.com/workers/platform/pricing/
4. デバッグ・モニタリング
| 手段 | 用途 |
|---|---|
console.log + wrangler tail |
ローカル/本番のリアルタイムログ取得 |
| Workers Insights ダッシュボード | CPU 時間、エラーレート、キャッシュヒット率を可視化 |
| Alert (Dashboard → Alerts) | 指定閾値超過時にメール/Slack 通知 |
wrangler tail の使用例
|
1 2 3 |
# 本番環境の JSON 形式ログをストリーム npx wrangler tail --env production --format json |
ハンドラ内でのベストプラクティス:
|
1 2 3 4 5 6 7 8 9 10 |
export default { async fetch(request: Request, env: Env) { const start = Date.now(); console.log("incoming", { method: request.method, url: request.url }); // ...処理... console.log("latency_ms", Date.now() - start); return new Response("OK"); }, }; |
出典:Workers Docs – Tail logs
まとめと次のステップ
- 環境構築 →
wrangler init+ 正しいwrangler.toml(compatibility_date, KV, DO)。 - API 実装 →
fetchハンドラでシンプルなエンドポイントを作り、wrangler devでローカルテスト。 - 認証 → 機密情報は必ず Secret または暗号化した上で KV に保存し、Durable Objects で状態管理。
- CI/CD → GitHub Actions と Cloudflare Secrets を組み合わせて自動デプロイを実現。
- 運用 → WAF・Rate Limiting のカスタム設定、Workers Insights でモニタリング、コストは無料枠から段階的に拡張。
次のアクション
- 本リポジトリ(例:github.com/yourname/edge-auth-api)をクローンし、手順通りにデプロイしてみましょう。
- 必要に応じて Python ランタイムや Durable Objects のスキーマ拡張を検討してください。
質問・フィードバックは Issues へどうぞ! 🎉