Terraform R2 Backend 移行手順 (O-10)
現状 (2026-04-28)
- R2 bucket
parky-terraform-state: ✅ 既に存在 (CF account5d8f6201...) - R2 API Token: ❌ 未発行 (CF API では発行不可、Dashboard 操作必要)
- Terraform state: dev のみ local 状態 (
infra/terraform/envs/dev/terraform.tfstate)。stg / prod は state 未生成 - Backend 設定ファイル: scaffold (
infra/terraform/backend.tf.example) のみ存在 - Terraform 専用 CF API token: ✅ 発行済 (S-11 / 1P item
3vlg2ojdtsffd6j4xde3aiveqa)
移行手順
1. R2 API Token 発行 (Dashboard)
CF API では発行不可。Dashboard から手動で実施:
- Cloudflare Dashboard → R2 → Manage R2 API Tokens → Create API Token
- 設定:
- Token name:
parky-terraform-state-rw - Permissions:
Object Read & Write - Specify bucket(s):
parky-terraform-stateのみ - TTL: なし (永続) — Terraform CI 用なので revoke 時は手動
- Token name:
- 発行された Access Key ID + Secret Access Key を控える (Secret はこの 1 回のみ表示)
2. 1Password に保存
# op-cache-bypass: one-time write
export OP_SERVICE_ACCOUNT_TOKEN=$(cat ~/.op/sa_token.txt)
op item create \
--vault="p3ezteh54f3msvl4wqyw7gbiam" \
--category="API Credential" \
--title="Cloudflare|R2 Access Key|Terraform State" \
"access_key_id[concealed]=<paste>" \
"secret_access_key[concealed]=<paste>" \
"bucket=parky-terraform-state" \
"endpoint=https://5d8f6201999f8965395396c4674cbe2d.r2.cloudflarestorage.com" \
"issued_on=YYYY-MM-DD" \
"purpose=Terraform R2 backend state storage"
その後 item ID を控え、reference_1password_items.md に追記。
3. backend.tf を各 env に配置
cd infra/terraform
for env in dev stg prod; do
cp backend.tf.example envs/$env/backend.tf
sed -i "s|<env>|$env|g" envs/$env/backend.tf
done
4. ローカル env vars 注入 (terraform init 用)
# 1Password から R2 access key 取得
ITEM_ID="<step 2 で控えた item id>"
export AWS_ACCESS_KEY_ID=$(bash scripts/op-cache/op-cache.sh get \
"op://p3ezteh54f3msvl4wqyw7gbiam/${ITEM_ID}/access_key_id")
export AWS_SECRET_ACCESS_KEY=$(bash scripts/op-cache/op-cache.sh get \
"op://p3ezteh54f3msvl4wqyw7gbiam/${ITEM_ID}/secret_access_key")
# CF API token (Terraform-only) も別途
export CLOUDFLARE_API_TOKEN=$(bash scripts/op-cache/op-cache.sh get \
"op://p3ezteh54f3msvl4wqyw7gbiam/3vlg2ojdtsffd6j4xde3aiveqa/credential")
5. State 移行 (各 env で 1 回だけ)
cd infra/terraform/envs/dev
terraform init -migrate-state
# 既存 terraform.tfstate → s3://parky-terraform-state/dev/terraform.tfstate へ転送
stg / prod は state 未生成なので terraform init だけで OK (新規 backend 取得)。
6. State 移行確認後、local backup 削除
cd infra/terraform/envs/dev
terraform plan # 0 diff であること
# OK なら local state file を削除
rm -f terraform.tfstate terraform.tfstate.backup terraform.tfstate.*.backup
7. CI workflows の更新
.github/workflows/terraform.yml (or 該当 deploy workflow) に追加:
- name: Load secrets from 1Password
uses: 1password/load-secrets-action@<sha>
with:
export-env: true
env:
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SA_TOKEN }}
AWS_ACCESS_KEY_ID: op://...
AWS_SECRET_ACCESS_KEY: op://...
CLOUDFLARE_API_TOKEN: op://p3ezteh54f3msvl4wqyw7gbiam/3vlg2ojdtsffd6j4xde3aiveqa/credential
ロールバック
State 移行後に問題が起きた場合:
- R2 bucket から state を
aws s3 cp(R2 endpoint 指定) で local にダウンロード - backend.tf を削除 (または
localに戻す) terraform init -migrate-state -force-copyで local に戻す
完全 rollback できるよう、移行直後の R2 state object を別 key (*.bootstrap-snapshot) に複製しておくと安全。
関連
- TF 専用 CF API token (S-11): 1P item
3vlg2ojdtsffd6j4xde3aiveqa(PJ|Parky vault) - backend.tf scaffold:
infra/terraform/backend.tf.example - 元の Terraform inventory:
.work/parky/terraform-inventory/inventory_2026_04_26.md