ナミスマート合同会社

Pulumi と SOPS でインフラを 1 つのリポジトリに集約する

更新: 2026年9月6日 PulumiIaCCloudflareセキュリティ

当社のプロダクトは Cloudflare・GitHub・Stripe・Supabase・Storyblok・Resend の上に乗っている。 設定は 1 つのリポジトリにまとめ、API があるものはコードで持っている。その構成を書く。

Pulumi + TypeScript

Cloudflare アカウントは「1 アカウントに 1〜3 ドメイン」で分けている。誤操作や障害の影響を プロダクト間に広げないためである。アカウントが増えるたびにプロバイダ定義が増えるので、 アカウントの一覧(config/accounts.ts)を回してプロバイダを組み立てられる Pulumi + TypeScript にした。

for (const account of cloudflareAccounts) {
  providers[account.name] = new cloudflare.Provider(account.name, {
    apiToken: process.env[account.tokenRef], // config には値ではなく秘密の名前
  });
}

プロダクト側はどのアカウントに乗るかだけを宣言し、対応するプロバイダが注入される。 アカウントの追加は配列に 1 要素足す作業になる。Stripe は公式の stripe/stripe、Storyblok と Resend はコミュニティ製プロバイダを Terraform provider bridge 経由で使っている。

秘密は暗号化したままコミットする

  • 実際の値は SOPS で暗号化して secrets/*.enc.yaml としてコミットする
  • 復号鍵(age の秘密鍵)と Pulumi の passphrase だけを 1Password に置く
  • config/ には値ではなく秘密の名前(tokenRef)だけを書く

秘密の変更が Pull Request の差分になるので、誰がいつどのトークンを差し替えたかが履歴に残る。 新しい端末の準備は 2 つの鍵と git clone だけで済み、鍵のローテーションは全ファイルに sops updatekeys をかければ終わる。

API トークンも Pulumi に発行させる

人が値を持つ Cloudflare の API トークンはアカウントごとに 1 本だけである。そのトークンで Pulumi を認証し、用途別のトークン(デプロイ、R2 / D1、Secrets Store、Zero Trust、DNS)は cloudflare.ApiToken として発行する。権限は config/products.ts に宣言する。

deployTokenPermissions: [
  "Workers Scripts Write",  // wrangler deploy(Worker)
  "Pages Write",            // Pages のデプロイ
  "D1 Write",               // D1 binding + マイグレーション適用
  "Account Settings Read",  // wrangler がアカウント情報を読む
],
deployTokenZonePermissions: ["Workers Routes Write"],

発行したトークンは tokens stack に置き、消費側は StackReference で受け取る。 mint した ApiToken.value を下流のプロバイダに直接つなぐと、値が preview 時点で未確定になり、 差分が無いリソースが +- replace と表示されたり data source が空応答でクラッシュしたりする。 StackReference の値は適用済みの確定値なので preview 時に既知になる。

bridge した Cloudflare プロバイダは permissionGroups の変更を検出しないので、権限を 足したときは pulumi up --replace <urn> でトークンを作り直す。

API が無く手作業に残った箇所

次の 4 つは API が無く、画面での操作でしか行えないので、泣く泣く手順書化している。

  • Stripe アカウントの作成。 Terraform プロバイダに作成のリソースが無い。
  • GitHub App の作成。 作成後の秘密鍵と ID は infra が管理する。
  • Cloudflare Email Routing の有効化。 MX / DKIM の自動レコードは編集がロックされていて、 管理対象はルールだけである。
  • メール転送先アドレスの検証。 確認メールのリンクを開く操作は自動化できない。

結果

新しいプロダクトの追加は config/products.ts への 20 行ほどの追記になり、リポジトリ、 デプロイ用トークン、DNS、Pages プロジェクト、GitHub の Environment と secret が揃う。


ナミスマート合同会社

業界最速、最安、高品質なアプリ開発。開発のご相談はお問い合わせからどうぞ。

お問い合わせ