Tech カテゴリのイメージ

LightsailからCloudflare Pagesへ移行。旧サーバーを止めたらブログが見えなくなった

Cloudflareの管理画面では公開成功。独自ドメインも有効。そこまで確認してLightsailを止めたら、いつものURLからブログが開かなくなった。

移行先が落ちたわけではなかった。自宅回線で使っているDNSが、まだ停止したAWSの接続先を返していた。同じドメインでも、どのDNSに問い合わせるかで行き先が違っていた。

2026年9月2日、vasteelabをAWS Lightsailから、非公開GitHubリポジトリとCloudflare Pagesで運用する構成へ移した。Codexに作業を頼み、途中で止まったチャットの履歴も引き継ぎながら進めた。サイトのコピーより、公開の確認と運用の引き継ぎに学びがあった。

Astroのブログを、GitHubへのpushで公開する形へ

移行前のブログは、Lightsail上のApacheから配信していた。記事はMarkdown、ブラウザアプリはHTMLや画像・音声のファイル。Astroでビルドし、生成されたファイルを公開ディレクトリへコピーする構成だった。

少し前には、CodexとClaude Codeの両方からブログを編集できるようにした。今回はその続きで、公開先と更新の流れを変えた。

選んだのは、ソースを非公開GitHubに置き、mainへのpushをCloudflare Pagesが受け取ってビルドする形だ。設定後の更新は、記事やアプリを直してGitHubへ送ればよい。毎回ブラウザでファイルをアップロードする必要はなくなった。

移行前
AWS上のソース → Astroでビルド → Apacheの公開先へコピー
移行後
Macで編集 → 非公開GitHubへpush → Cloudflare Pagesでビルド・公開

最初のバックアップ時点では記事499本、アプリ50本あった。公開済みの記事URLは維持し、ソースだけでなく画像・音声も取得した。手元でビルドできることを確かめてから、GitHubとCloudflareを連携した。

最初に詰まったのは、ビルド設定だった

GitHubとの連携ができても、それだけでAstroのサイトが正しく公開されるとは限らなかった。初回はビルドコマンドと出力先が未設定で、意図した生成済みサイトを配信する状態になっていなかった。

修正した設定は次のとおりだ。

項目今回の設定
本番ブランチmain
ビルドコマンドnpm run build
出力ディレクトリdist
ルートディレクトリリポジトリルート
Node.js検証した版を.node-versionに固定

Cloudflareのビルド設定の公式資料でも、Astroのコマンドはnpm run build、出力はdistとされている。今回は静的サイトとしてビルドする構成で、この設定へ直して再デプロイした。

ここで見るべきなのは、管理画面の成功表示だけではない。トップページ、記事、アプリが実際に開くか。存在しないURLで404になるか。ソースや内部資料を公開していないか。非公開GitHubに置いたつもりでも、公開対象の選び方は別に確認する必要がある。

CloudflareへのDNS移行と、Pagesへの接続は別だった

次に、ドメインのネームサーバーをCloudflare指定のものへ変更した。しばらく待つと、管理画面に「Your domain is now protected by Cloudflare」と表示された。

ただ、この表示はブログの配信元までPagesに切り替わったことを意味しない。取り込まれたDNSレコードは、もともとのAWSを指していた。

Pagesプロジェクトの「Custom domains」を開くと、独自ドメインはまだ登録されていなかった。そこでvasteelab.comを追加し、既存のAレコードをPages向けのCNAMEへ変更した。www付きも登録した。

Cloudflareのカスタムドメインの手順には、Pagesプロジェクトへのドメイン登録が案内されている。DNSだけを手作業で変えて終えるのではなく、Pages側との関連付けまで進める必要がある。

ネームサーバーを変更すること、Pagesへドメインを登録すること、変更が利用者の回線に反映されること。この三つを一続きの「切り替え完了」と捉えたのが、後のつまずきにつながった。

バックアップ後にも、AWS側のアプリは増えていた

移行準備中も、AWS側ではアプリの追加が進んでいた。最初にコピーしたソースを、そのまま最新版だと思うわけにはいかなかった。

AWSからアプリ本体と共有JavaScript、アプリ一覧をあらためて取得して比較すると、未反映だったのはPattaya Vice Pinballと一覧・回遊リンクだった。HTMLだけでなく、盤面PNGと同梱ライブラリのライセンスもGitへ取り込んだ。

アプリ関連105ファイルを取得版と照合し、ローカルでは511ページのビルド成功を確認した。GitHubへpushしたあと、Cloudflareの該当コミットのデプロイ成功と、本番のピンボールの表示も確認した。

複数のAIに作業を頼んでいると、移行している横で別の場所が更新される。バックアップがあることと、最新の変更が入っていることは別だった。次に同じことをするなら、切り替え直前に差分を取り込み、その後の編集先をGit側にそろえる。

Lightsailを止めたら、いつものURLだけ開かなかった

Pagesへの接続とサイト表示を確認したあと、Lightsailを停止した。するとhttps://vasteelab.com/への接続がタイムアウトした。一方で、確認した環境ではwww付きとpages.devのURLは応答していた。

Codexに調べてもらうと、DNSの問い合わせ先で結果が分かれた。

確認先そのときの結果
Macが自宅ルーター経由で使っていたDNS旧AWSのIPを返す
CloudflareのDNSCloudflareのIPを返す
GoogleのDNSCloudflareのIPを返す
ドメインの権威DNSCloudflareのIPを返す
通常の接続停止したAWSへ向かいタイムアウト
同じホスト名のままCloudflareのIPへ接続HTTP 200

調査で使ったのは、たとえば次のような比較だ。

Terminal window
# 今の回線で使っているDNSの答え
dig vasteelab.com A +noall +answer
# 公開DNSの答え
dig @1.1.1.1 vasteelab.com A +noall +answer
dig @8.8.8.8 vasteelab.com A +noall +answer

このとき分かったのは、Cloudflare側の設定がAWSを指したままなのではなく、自宅ルーター経由の問い合わせで旧接続先が返っていたことだ。ルーター自身のキャッシュなのか、その上流のDNSまで含む問題なのかは、この結果だけでは断定していない。

MacのWi-FiのDNSをCloudflareのDNSへ変更すると、元のhttps://vasteelab.com/からHTTP 200が返り、ブラウザでもブログが開いた。

ただし、これで直るのはそのMacの名前解決だ。他の読者の回線まで切り替わったことにはならない。自分のMacで起きた原因を特定できても、影響が自分一人に限られていたと調べ切れたわけではない。

旧サーバーを止める判断は、もう一段遅らせればよかった

最初は「Cloudflareで公開できているなら、AWSは止めてよい」と考えた。実際には、旧接続先を使う回線が残っていた。公開成功を確認してから、旧サーバーを止めるまでの間に、もう一段確認が必要だった。

次なら、新旧の配信内容をそろえて両方を動かしておき、普段の回線と別の回線で元のURLを確認する。旧レコードのTTLやネームサーバーの切り替え状況も見る。特定の時間が過ぎれば全員の反映が終わる、と一律には決めない。

今回は、他の回線には反映待ちが残り得ると分かったうえで、待つことにした。全利用者からの到達性まで確認できた、という結末ではない。停止による影響を避けたい移行なら、旧サーバーを一時的に再稼働させる余地を残しておくほうがよかった。

もう一つ、料金も分けて考える必要がある。Lightsailは停止しただけではインスタンスの課金が止まらない。AWSの料金FAQでは、停止状態でも料金が発生すると説明されている。削除するかどうかは、バックアップや残っている用途を確認したあとに判断する話だ。

AIの引き継ぎ書も、サーバーから持ち出した

AWSにはブログだけでなく、OpenClawのエージェント「Light」も動いていた。Lightsailを止めれば、こちらも止まる。サイトをPagesへ移しただけでは、Lightが持っている運用の知識まで引き継いだことにはならなかった。

そこで、引き継ぎ書、文章へのフィードバック、記事ネタ、作業履歴など24ファイルをMacへ取得した。原本との一致をチェックサムで確かめ、その後、非公開GitHubにも保存した。

残したかったのは接続手順だけではない。敬語と普通体を混ぜないこと、一般論だけの記事にしないこと、公開済みURLを変えないこと。こうした過去の指摘も、次のAIが続きを書くための情報になる。

古い資料は原本として残し、現在の手順を別にまとめた。以前の「AWSへコピーして公開する」という説明と、今の「GitHubへpushしてPagesで公開する」という説明が同じ場所に並ぶだけでは、次の作業でまた迷うからだ。

リポジトリのAGENTS.mdCLAUDE.mdを入口にして、現行の運用と文体ルールを読めるようにした。内部メモは公開用のdistに含まれないことも確認した。これは知識文書の移行で、Light本体やDiscord連携、自動処理を別の場所で動かす作業までは含めていない。

次の更新からは、GitHubを起点にする

今回の移行で、ブログの更新はGitHubを起点にした流れへ変わった。記事やアプリを編集し、ビルドを確認してpushする。Cloudflareで同じコミットが公開されたことを確かめ、最後に本番URLを見る。

一方で、公開先を変えただけでは消えない作業も残った。Apacheのアクセスログから人気記事を集計していた仕組みは、そのままCloudflareには持っていけない。既存の順位データは保持したが、新しい集計方法への切り替えは別途必要だ。

移行して分かったのは、ファイルの置き場所だけで完了を判断しないほうがよい、ということだった。新しい場所で表示できるか、古い場所を止めても届くか、次の更新を誰がどこから行うか。そこまで記録して、ようやく次の作業を迷わず始められるようになった。