WordPressからHugoへ安全に切り替えた手順

シリーズ「Hugo移行記」の記事

haruki256.comをWordPressからHugoへ切り替えるとき、僕が重視したのは、問題が起きた場合にWordPressへ戻せることでした。

WordPressを先に削除してHugoを配置すると、表示に問題が見つかったときの対応が増えます。そこで、WordPressは公開フォルダの外へ残し、事前に展開したHugoとフォルダを入れ替える方法を取りました。

この記事では、2026年7月21日にcoreserverで実施したバックアップ、Hugoの事前配置、本番切り替え、確認、元へ戻す手順をまとめます。

まず全体像

WordPressのバックアップを取得し、Hugoを公開外へ展開してから公開フォルダを入れ替え、確認に失敗した場合はWordPressへ戻す流れ
WordPressを削除せず、Hugoの準備と戻す方法をそろえてから公開先を入れ替えました。

WordPressへ戻せることを切り替え条件にした

切り替え前の公開先は public_html で、その中にWordPress本体、テーマ、プラグイン、アップロード画像がありました。Hugoでは生成済みの静的ファイルだけを同じ場所へ置きます。

僕の環境では、次の条件を満たすまで公開先を変更しないことにしました。

  • 切り替え直前のデータベースとWordPressファイルを手元に保存する
  • 公開先とは別のフォルダでHugoを展開し、必要なファイルを確認する
  • WordPressを削除せず、別名のフォルダとして残す
  • Hugoの確認に失敗したらWordPressのフォルダ名を戻す
  • 同じサーバーにある別ドメインのフォルダには触らない

既存のバックアップがあっても、切り替え直前の状態とは限りません。今回は当日に取り直したバックアップを確認してから進めました。

切り替え直前のバックアップを取った

WordPressは、ファイルだけをコピーしても記事や設定のすべては戻せません。記事本文やWordPressの設定はデータベースにあるため、データベースとファイルを2点セットで保存しました。

  • データベース:SQLを書き出してGZipで圧縮
  • ファイル:public_html 全体をtar.gzで圧縮

ファイル側には wp-config.phpwp-contentwp-adminwp-includes が含まれることを確認しました。データベースも圧縮ファイルを最後まで展開できることを確認しています。

サーバーから手元へ取得した後は、サーバー側とローカル側のMD5を比較しました。2つの値が一致したため、転送中にファイルが変わっていないことを確認できました。

バックアップにはデータベースの接続情報も含まれます。そのため公開リポジトリへ入れず、ブログのソースとは別に保管しています。

Hugoを公開フォルダの外で準備した

Hugoはローカルで本番設定のビルドを行いました。プレビュー用サーバーが生成先を使用しているとWindowsでクリーン処理に失敗することがあったため、プレビューを止めるか、確認専用の生成先を使います。

hugo --cleanDestinationDir --panicOnWarning
hugo list published
git diff --check

ビルドが成功するだけでは、予定した内容だけが入っているとは限りません。生成後は次の点も確認しました。

  • トップ、記事、ショート、固定ページ、404、RSS、サイトマップがある
  • CSS、JavaScript、SVGが生成されている
  • 下書きと保管中の旧記事が入っていない
  • デザイン確認用のモックページが入っていない

確認後、生成物をtar.gzへまとめてMD5を記録しました。サーバーへ転送した後も同じMD5になることを確かめ、public_html-hugo-next-<切り替えID> という公開外のフォルダへ展開しました。

この時点では、公開中のWordPressに変更はありません。Hugo側の index.html404.html.htaccess、記事ファイルを確認してから入れ替えへ進みました。

公開フォルダを入れ替えた

切り替え前に、public_html とその親フォルダが同じファイルシステムにあることを確認しました。そのうえで、WordPressのフォルダ名を変え、準備済みのHugoを public_html にしました。

実際の処理を整理すると、次の形です。切り替えIDは実施日時から作った文字列を使いました。

release_id='YYYYMMDD-HHMMSS'
site="$HOME/domains/haruki256.com"
live="$site/public_html"
stage="$site/public_html-hugo-next-$release_id"
wordpress="$site/public_html-wordpress-$release_id"

set -eu
test -d "$live/wp-content"
test -f "$live/wp-config.php"
test -f "$stage/index.html"
test ! -e "$wordpress"

mv "$live" "$wordpress"
if ! mv "$stage" "$live"; then
  mv "$wordpress" "$live"
  exit 1
fi

test は、操作対象が想定したWordPressとHugoであることを確認するために置いています。退避先がすでに存在する場合も処理を止めます。

2回目の mv に失敗した場合は、WordPressを public_html へ戻します。WordPressのデータベースは変更していないため、この段階の失敗ではデータベースを復元する必要はありません。

公開後はページと配信ファイルを確認した

フォルダを入れ替えた後は、トップが表示されたことだけで完了にしませんでした。今回確認したのは次の項目です。

  • トップ、記事2本、ショート一覧と個別ページ、固定ページが200になる
  • CSS、JavaScript、SVG、RSS、サイトマップが200になる
  • ショートから対応記事へ移動できる
  • 存在しないURLと公開しない旧記事URLが404になる
  • wp-login.phpwp-admin/wp-json/ が公開されていない
  • HTTPからHTTPSへ301で転送される
  • WordPress固有のレスポンスヘッダーがなくなっている

これらはサーバー内からの curl と、手元からのHTTPアクセスの両方で確認しました。主要ページの内容も確認し、別のページが200を返しているだけではないことを確かめています。

問題があればWordPressのフォルダ名を戻す

Hugoの公開後に問題が見つかった場合は、Hugoを削除せず別名へ動かし、退避していたWordPressを public_html へ戻します。

site="$HOME/domains/haruki256.com"
live="$site/public_html"
wordpress="$site/public_html-wordpress-<切り替えID>"
failed="$site/public_html-hugo-failed-<戻す作業のID>"

set -eu
test -f "$live/index.html"
test -d "$wordpress/wp-content"
test -f "$wordpress/wp-config.php"
test ! -e "$failed"

mv "$live" "$failed"
if ! mv "$wordpress" "$live"; then
  mv "$failed" "$live"
  exit 1
fi

この戻し方では、問題があったHugoも調査用に残ります。WordPress側のファイルやデータベースが壊れている場合だけ、切り替え直前のバックアップから復元します。

WordPressを残したままHugoへ切り替えられた

実際の切り替えでは、Hugoの公開、主要URLの確認、404、HTTPSへの転送まで完了しました。WordPressは公開フォルダの外に残しているため、外部からWordPressの管理画面やAPIへはアクセスできません。

切り替え後のHugo更新でも、同じ考え方を使っています。新しいHugoを公開外へ展開し、現在のHugoを直前版として残してから入れ替えています。旧WordPressの退避フォルダは通常更新では触りません。

今回の条件では、バックアップだけでなく、切り替え前のWordPressと直前のHugoをフォルダとして残すことで、問題が起きた場合に戻す作業を短くできました。