2026年8月22日
2026年8月22日
WordPress移行後に404エラーが出るときの直し方|.htaccess・パーマリンク・URL置換
WordPressをサーバー移転やドメイン変更で移したあとに「トップページは開くのに、記事や固定ページがすべて404になる」という症状は、多くの場合、URLの書き換え(リライト)がWebサーバー側で働いていないことが原因です。データベースに古いURLが残っていると、別の症状(旧ドメインへ飛ばされる、画像が出ない)も重なります。
この記事では、症状から原因を切り分け、Apache・Nginxそれぞれの設定、パーマリンクの再保存、データベース内のURL置換の順に説明します。コマンド例は2026年10月時点のWP-CLI 2系、Apache 2.4、Nginxを前提にしています。
作業の前にバックアップを取る
URLの置換はデータベースを書き換えます。失敗したときに戻せるよう、先に書き出しておきます。
# WordPress のディレクトリで実行する
cd /var/www/html
wp db export ~/before-fix-404.sql
症状から原因を切り分ける
| 症状 | 考えられる原因 |
|---|---|
| トップページは開くが、記事・固定ページ・カテゴリーが404 | .htaccess が無い、Apacheが .htaccess を読んでいない、mod_rewrite が無効、Nginxに try_files が無い |
| ページを開くと旧ドメインへ転送される | home・siteurl の値、または wp-config.php の WP_HOME・WP_SITEURL が旧ドメインのまま |
| ページは開くが、画像や内部リンクが旧ドメインを向いている | 本文やウィジェット、テーマ設定に旧URLが残っている |
| サブディレクトリに移したら404 | .htaccess の RewriteBase と転送先、またはNginxの location が旧パスのまま |
切り分けの近道は、パーマリンクを使わないURLで開いてみることです。https://新ドメイン/?p=記事ID で記事が表示されるなら、記事のデータは移行できており、問題はURLの書き換えにあります。記事IDは管理画面の投稿一覧で編集リンクにマウスを重ねると post=123 の形で確認できます。
home と siteurl を確認する
最初に、サイトのURLとして登録されている値を確認します。
wp option get home
wp option get siteurl
旧ドメインや旧パスが出た場合は、新しい値に更新します。
wp option update home 'https://new-domain.example'
wp option update siteurl 'https://new-domain.example'
値が正しいのに旧ドメインへ転送される場合は、wp-config.php に次の定数が書かれていないかを確認します。定数があると、データベースの値より優先されます。
define( 'WP_HOME', 'https://new-domain.example' );
define( 'WP_SITEURL', 'https://new-domain.example' );
旧ドメインのまま書かれていれば新しい値に直すか、行ごと削除してデータベースの値を使います。2つの設定の違いはWordPressアドレスとサイトアドレスの違いで説明しています。
Apacheの場合:.htaccess とサーバー設定を確認する
.htaccess があるか
FTPクライアントの多くは、名前が . で始まるファイルを初期設定で表示しません。そのため、移行の際に .htaccess だけがコピーされていないことがあります。新しいサーバーのWordPressのディレクトリで確認します。
ls -la /var/www/html/.htaccess
cat /var/www/html/.htaccess
WordPress本体が書き込む部分は、# BEGIN WordPress と # END WordPress の間です。ルートにインストールした場合は次の内容になります。
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
ファイルが無い場合や中身が違う場合は、後述の「パーマリンクを保存し直す」で作り直せます。手で作る場合は上の内容で保存し、パーミッションを644にします。
Apacheが .htaccess を読んでいるか
自分で構築したVPSやクラウドのサーバーでは、Apacheの設定で .htaccess が無視されていることがよくあります。Apache 2.4の AllowOverride の初期値は None で、この場合 .htaccess の内容は読まれません。UbuntuやDebianの初期設定でも、/etc/apache2/apache2.conf の /var/www/ は AllowOverride None になっています。
WordPressを置いたディレクトリの設定(/etc/apache2/apache2.conf やバーチャルホストの設定ファイル)を、次のように変更します。
<Directory /var/www/html>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
RewriteEngine などのリライト用の命令を .htaccess で使うには、AllowOverride に少なくとも FileInfo が含まれている必要があります。All はその条件を満たします。
mod_rewrite が有効か
# 読み込まれているモジュールに rewrite があるか
apachectl -M | grep rewrite
# 無い場合は有効にする(Ubuntu・Debian)
sudo a2enmod rewrite
# 設定の文法を確認してから反映する
sudo apachectl configtest
sudo systemctl reload apache2
apachectl -M の結果に rewrite_module が出れば有効です。共用のレンタルサーバーでは、これらの設定はサーバー会社側で済んでいるため、.htaccess の有無と中身だけを確認します。
Nginxの場合:try_files を確認する
Nginxは .htaccess を読みません。パーマリンクを動かすには、サーバーの設定にWordPress用の try_files が必要です。WordPressの公式ドキュメントでは、次の形が示されています。
location / {
try_files $uri $uri/ /index.php?$args;
}
旧サーバーがApacheで新サーバーがNginxの場合、この設定が無いと、トップページ以外がすべて404になります。設定を変えたら、文法を確認してから反映します。
sudo nginx -t
sudo systemctl reload nginx
NginxでのWordPressの設定全体はNginxでWordPressを動かす設定で説明しています。
パーマリンクを保存し直す
サーバーの設定が整ったら、WordPress側のリライトルールを作り直します。管理画面で行う場合は次のとおりです。
- 管理画面の「設定」→「パーマリンク」を開く
- 設定を変えずに「変更を保存」を押す
保存すると、データベースのリライトルールが作り直されます。Apacheで .htaccess に書き込める場合は、# BEGIN WordPress から # END WordPress の部分も書き直されます。書き込めない場合は、画面に .htaccess に書く内容が表示されるので、その内容を手で貼り付けます。
WP-CLIで行う場合は、次のコマンドです。
# 現在のパーマリンク構造を確認する(空ならパーマリンクを使っていない)
wp option get permalink_structure
# リライトルールを作り直す
wp rewrite flush
wp rewrite flush --hard は .htaccess も書き直すオプションですが、WP-CLIから .htaccess を作るには、WP-CLIの設定ファイル(wp-cli.yml)に次の記述が必要です。シングルサイトでのみ動きます。
apache_modules:
- mod_rewrite
この設定が無いと、データベースのルールだけが作り直され、.htaccess は書き換わりません。迷ったら管理画面から保存する方法を使います。
データベース内の旧URLを置き換える
ドメインやディレクトリが変わった場合は、本文・ウィジェット・テーマの設定などに旧URLが残ります。WordPressの設定値にはPHPのシリアライズ形式で保存されたものがあり、文字数がデータに含まれているため、SQLの REPLACE で書き換えると壊れることがあります。WP-CLIの wp search-replace はシリアライズされた値も正しく書き換えます。
まず --dry-run で、どのテーブルで何件置き換わるかを確認します。
wp search-replace 'https://old-domain.example' 'https://new-domain.example' \
--all-tables --skip-columns=guid --dry-run
件数に問題がなければ、--dry-run を外して実行します。旧サイトでhttpのURLも混在していた場合は、httpの側も置き換えます。
wp search-replace 'https://old-domain.example' 'https://new-domain.example' \
--all-tables --skip-columns=guid
wp search-replace 'http://old-domain.example' 'https://new-domain.example' \
--all-tables --skip-columns=guid
オプションの意味は次のとおりです。
| オプション | 意味 |
|---|---|
--dry-run |
置換せず、置き換わる件数だけを表示する |
--all-tables |
WordPressに登録されたテーブルだけでなく、データベース内のすべてのテーブルを対象にする。同じデータベースに別のサイトのテーブルがある場合は、代わりに --all-tables-with-prefix を使う |
--skip-columns=guid |
投稿の guid 列を書き換えない。WordPressの公式ドキュメントは、guid はフィードリーダーが記事を識別するための値なので変更しないよう案内している |
--precise |
SQLではなくPHPで1行ずつ処理する。取りこぼしが減るが遅くなる。通常は付けなくてよい |
置換のあと、同じコマンドを --dry-run 付きでもう一度実行し、置き換わる件数が0になっていれば完了です。wp search-replace の詳しい使い方はWP-CLIのsearch-replaceコマンドにまとめています。
最後にキャッシュを消します。
wp cache flush
キャッシュ系のプラグインやCDNを使っている場合は、それぞれの画面からもキャッシュを削除します。
サブディレクトリに移した場合
https://example.com/ から https://example.com/blog/ のように、WordPressをサブディレクトリに移した場合は、.htaccess の RewriteBase と最後の転送先もディレクトリに合わせます。
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /blog/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /blog/index.php [L]
</IfModule>
# END WordPress
この .htaccess は /blog/ ディレクトリの中に置きます。Nginxでは location と転送先をディレクトリに合わせます。
location /blog/ {
try_files $uri $uri/ /blog/index.php?$args;
}
あわせて、home と siteurl を https://example.com/blog に更新し、データベース内の旧URLも前の節の手順で置き換えます。
直ったかを確かめる
# サイトのURL
wp option get home
wp option get siteurl
# パーマリンク構造
wp option get permalink_structure
# 記事のURLが200を返すか(URLは実在する記事に置き換える)
curl -s -o /dev/null -w '%{http_code}\n' https://new-domain.example/sample-post/
ブラウザで確認する場合は、以前に旧ドメインへの転送を記憶していることがあるため、プライベートウィンドウで開くと結果が分かりやすくなります。
まとめ
- トップページだけ開いて他が404なら、まずリライトの設定を疑う。
?p=記事IDで開ければデータは無事 - Apacheは
.htaccessの有無、AllowOverride、mod_rewriteの3点を確認する。Nginxはtry_filesを確認する - サーバー設定を直したら、「設定」→「パーマリンク」で「変更を保存」を押してルールを作り直す
- 旧URLは
wp search-replaceで--dry-runから始めて置き換え、guid列は対象から外す - サブディレクトリに移した場合は、
RewriteBaseと転送先、home・siteurlをディレクトリに合わせる