ブログをZolaに移行、AWSの後始末
技術検証目的で1年ほど運用していたNext.js + Amazon Amplify 構成のブログを、静的サイトジェネレーターZolaに移行しました。 移行先の選定、200記事のMarkdown変換、そしてAWSリソースの 網羅的な削除作業まで、移行の記録を残します。 技術検証目的で1年ほどNext.js + Amazon Amplify構成のブログを運用していました。 目的も達成したので静的サイトジェネレーター(以下、SSGと記載)に移行しましたが、意外と移行先の選定や AWSの後始末に手間取りました。その記録を残します。 移行先のSSGには Zola を選びました。 Python系(Pelican, Nikola)は 以前使った経験があり、遅さに辟易していたので避けました。 Hugo も使用経験があるため、比較的新しく人気のあるZolaを 選びました。 Rust製のシングルバイナリで、node_modulesやpip installが不要です。 MDX形式の200記事程度あったので、 Markdownへの変換は、Claude Codeで作成した 移行ツール で対応しました。 ホスティング先はCloudflareを想定していました。 Cloudflare PagesはV2以降で 移行で最も手間がかかったのはAWSの閉鎖です。 Amplifyは便利ですが、裏でCloudFront、S3、IAMロールなど多くのリソースを自動生成します。 管理コンソールでは複数サービスの画面を行き来することになり、見落としが発生しやすいと感じました。 そのため、今回はすべてCLIで調査・削除しました。 まず、Amplifyが作成した可能性のあるリソースを網羅的に確認します。 今回確認されたリソースと、Amplifyアプリ削除時の自動削除有無は以下の通りです。 調査が終わったら、リソースを削除していきます。 以下ではコマンド例を示していますが、実際の削除作業では各コマンドの出力を目視で 確認し、削除対象が正しいことを1つずつ確かめながら進めました。 AWSリソースの削除は取り消しができないため、慎重に作業することをおすすめします。 Amplify Hosting(WEB_COMPUTEタイプ)の場合、アプリを削除するとCloudFrontと S3バケットは自動削除されます。 IAMロールは自動削除されないため、手動で削除します。ロールを削除する前に、 アタッチされているポリシーをすべてデタッチする必要があります。 ACM証明書はCloudFrontで使用中だと削除できないため、CloudFront削除後に 実行します。ACM証明書はus-east-1リージョン固定です。 DNSはFastmailで管理していたため、Amplify用のCNAMEレコードを削除し、 GitHub Pages用の設定に変更しました。 削除後は、各リソースが消えていることを確認します。CloudTrailで削除イベントも 確認できます。 Zolaはシングルバイナリで依存関係がなく、node_modulesの管理から解放されます。 Rust製で高速、テンプレートエンジンもJinja2ライクで書きやすいです。プラグイン なしでSASSコンパイルやシンタックスハイライトまで対応しており、長期運用での 保守コストの低さが魅力です。GitHub Pages + Cloudflare CDNの構成も安定して います。 Amazon Amplifyは構築が簡単な反面、閉鎖時は複数サービスにまたがるリソースの確認が 必要です。CloudFrontとS3はAmplifyアプリ削除時に自動削除されますが、IAM ロール、ACM証明書、DNSレコードは手動削除が必要です。 管理コンソールでは見落としが発生しやすく、かといって個人ブログでCloudFormationを使うほどでもない。 そんなケースではCLIで網羅的に確認し、ログに残しながら作業を進めると安心です。
Table of Contents
Zola への移行
サービス Zola 対応 備考 Cloudflare Pages V1 のみ V2/V3 で zola: not found エラーNetlify あり 2025年9月〜 月20デプロイ制限 GitHub Pages GitHub Actions 制限なし、無料 ZOLA_VERSION 環境変数を無視する問題があります。 Issue も2年放置されています。 Netlifyは無料プランのデプロイ制限が厳しいため、GitHub Pages + Cloudflare CDNを採用しました。AWS リソースの調査と閉鎖
# Amplify アプリ一覧(リージョン指定必須)
aws amplify list-apps --region ap-northeast-1
# CloudFront ディストリビューション
aws cloudfront list-distributions \
--query 'DistributionList.Items[*].[Id,Origins.Items[0].DomainName,Status]' \
--output table
# S3 バケット(Amplify が作成したバケットを探す)
aws s3 ls | grep -E 'amplify|blog'
# IAM ロール(Amplify 関連)
aws iam list-roles \
--query 'Roles[?contains(RoleName,`amplify`)].RoleName' --output table
# ACM 証明書(カスタムドメイン用、us-east-1 固定)
aws acm list-certificates --region us-east-1 \
--query 'CertificateSummaryList[*].[DomainName,CertificateArn]' \
--output tableサービス リソース 自動削除 Amplify blog-yostos アプリ - CloudFront Amplify 管理のディストリビューション ✓ S3 amplify-xxx-deployment バケット ✓ IAM AmplifySSRLoggingRole 等 ✗ ACM blog.yostos.org 証明書 ✗ # アプリ ID を確認して削除
aws amplify list-apps --region ap-northeast-1 \
--query 'apps[?name==`blog-yostos`].appId' --output text
aws amplify delete-app --app-id <APP_ID> --region ap-northeast-1# ロールにアタッチされたポリシーを確認
aws iam list-attached-role-policies --role-name <ROLE_NAME>
aws iam list-role-policies --role-name <ROLE_NAME>
# ポリシーをデタッチしてからロールを削除
aws iam detach-role-policy --role-name <ROLE_NAME> --policy-arn <POLICY_ARN>
aws iam delete-role --role-name <ROLE_NAME>aws acm list-certificates --region us-east-1 \
--query 'CertificateSummaryList[?DomainName==`blog.yostos.org`]'
aws acm delete-certificate --certificate-arn <CERT_ARN> --region us-east-1# CloudFront(Amplify 管理分が消えていること)
aws cloudfront list-distributions \
--query 'DistributionList.Items[*].Id' --output text
# S3(amplify 関連バケットが消えていること)
aws s3 ls | grep amplify
# CloudTrail で削除イベントを確認
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=DeleteApp \
--region ap-northeast-1まとめ