Pulumi と SOPS でインフラを 1 つのリポジトリに集約する
当社のプロダクトは 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 が揃う。
ナミスマート合同会社
業界最速、最安、高品質なアプリ開発。開発のご相談はお問い合わせからどうぞ。