wordpress-migration
Skill0 starsChanged 3 months agoMITView on GitHub
Plan, execute and verify a WordPress site migration between servers or domains. Use when the user is moving, transferring, cloning or relaunching a WordPress site, changing its domain or hosting, promoting staging to production, or when they mention wp-cli migration, search-replace of a site URL, serialized data breakage, permalink 404s after a move, redirect loops from siteurl/home mismatch, or a leftover noindex after go-live.
1 other project uses a version of this.
Adopted by
Most recently taken up by
- BrivaHamisi/laravel-shipkittheir own version, first seen Sep 26, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- BrivaHamisi/laravel-shipkit★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
The file
Files
WordPress Migration
Release candidate. 2026-08-26にXserver上の使い捨てWordPressで、 事前調査・DB複製・URL置換・HTTP表示・rollbackのE2Eを完走済み。
サーバー移行・ドメイン変更・ステージング本番化を、事故を起こさずに完了させるためのSkill。
移行が失敗する原因のほとんどは手順を知らないことではなく、手順を知っていても人間が取りこぼすこと。 このSkillは、取りこぼしやすい箇所を順序として固定する。
同梱スクリプトは、事前調査・URL置換・移行後検証を補助する。
search_replace_plan.sh は既定でdry-runのみ。DBを書き換える--executeは、空でないバックアップ、
dry-run完走、確認入力(または明示的な--yes)が揃った場合だけ実行する。
利用者の本番環境を触る前に、必ず下の「絶対に守る順序」を満たしているか確認する。
担当する範囲
- 移行の型の判定と実行計画の提示
- シリアライズデータを壊さないURL置換の実行手順
- 移行後の公開URL検証
- 手順の正本(
references/RUNBOOK.md)と障害対応(references/TROUBLESHOOTING.md)
担当しない: 実際のDNSレコード変更、サーバー契約、決済。これらは必ず利用者本人が実施する。
絶対に守る順序
- バックアップが取れていない移行は始めない。 DBダンプとファイル一式の両方。 ダンプが空でないこと、末尾まで書けていることを確認する。復元コマンドを先に控える。
- URL置換は必ず dry-run が先。 生SQLの
sed/REPLACE()でURLを置換しない。 WordPress はオプションやメタ値に PHP のシリアライズ文字列を格納しており、 文字列長のバイト数がヘッダに埋まっている。長さの違うドメインへ素朴に置換するとs:19:"http://old.example"の19が実長と食い違い、値が丸ごと復元不能になる。 必ずwp search-replace(シリアライズを解して再直列化する)を使う。 - DNS切替は最後。 切替前に hosts 指定で新サーバーへ向け、本番URLのまま完全に動作確認する。
- 切替後に
blog_publicを確認する。 ステージングで検索避けを有効にしたまま本番へ移すのは 最も損失が大きく、最も気づかれにくい事故。 - 破壊的コマンドは、実行前に内容と影響範囲を利用者へ提示して同意を取る。 黙って本番を変更しない。
進め方
移行を始めるときは、会話履歴だけで進捗を管理しない。scripts/migration_project.py で
Migration Projectを作り、各Phaseの証跡が揃ったときだけ状態を進める。
python scripts/migration_project.py init --project ./migration-project --manifest ./manifest.json
python scripts/migration_project.py status --project ./migration-projectmigration_project.py 自体は状態・証跡管理のみで、転送やDB変更を自動実行しない。
実作業はRUNBOOKと各スクリプトの安全ゲートに従う。
Step 1: 移行の型を確定する
references/RUNBOOK.md の Phase 0 の表で、A(サーバーのみ)/B(ドメインのみ)/
C(両方)/D(ステージング本番化)/E(HTTPS化)のどれかを確定する。
型によってURL置換の要否が変わる。型Aで置換を実行してはいけない。
Step 2: 現状を測る(読み取りのみ)
移行元で実行する。すべて参照系で、書き込みは行わない。
wp core version
wp option get siteurl ; wp option get home
wp option get blog_public # 0 なら検索避けが有効
wp option get permalink_structure
wp db prefix
wp core is-installed --network && echo "multisite"
wp plugin list --status=active
wp db size --human-readable
du -sh wp-content/uploads
wp config list --strict | grep -Ei 'WP_SITEURL|WP_HOME|WP_CONTENT_URL|COOKIE_DOMAIN|DOMAIN_CURRENT_SITE|FORCE_SSL|WP_CACHE|DISALLOW_FILE_MODS'結果を表にして利用者へ提示する。ここで移行方式が決まる。 DBやuploadsが大きい場合、ワンクリック系の移行プラグインは実行時間上限・アップロード上限に当たって 途中で失敗し、しかも中途半端に成功したように見える。その場合は RUNBOOK のCLI手順に切り替える。
利用者に必ず確認すること:
- 移行元/移行先のホスティングと、SSHまたはWP-CLIが使えるか
- ドメインは変わるか(型A〜Eのどれか)
- コンテンツ凍結できる時間帯(ECや会員サイトでは必須)
- メール送信(SPF/DKIM)、外部API、決済のIP制限、CDN、外部cron、Webhookなど 旧IP・旧ドメインに依存している仕組み
Step 3: 手順を組む
references/RUNBOOK.md を読み、Step 2 の結果に合わせて実行計画を提示する。
勝手に本番へ変更を加えない。DNSのTTL引き下げ(48〜72時間前)、SSL証明書の事前発行、
コンテンツ凍結の告知は、切替当日では間に合わない。 計画時点で日程に落とす。
Step 4: バックアップ
wp db export ~/backup/pre-migration-$(date +%Y%m%d%H%M).sql
ls -l ~/backup/pre-migration-*.sql # 0バイトでないこと
tail -c 200 ~/backup/pre-migration-*.sql # 末尾まで書けていること
tar czf ~/backup/pre-migration-files-$(date +%Y%m%d%H%M).tar.gz wp-content wp-config.php .htaccessバックアップは移行元サーバーの外にも1部置く。復元手順を利用者へ先に渡す。
Step 5: URL置換(型 B / C / D / E のみ)
dry-run を先に、6形式すべてを個別のパスとして扱う。 順序も重要で、
https:// と http:// を先に処理してからプロトコル相対形に進む(逆にするとスキーム引き上げが漏れる)。
OLD=old.example.com
NEW=https://new.example.jp
NEWHOST=new.example.jp
SR="--all-tables-with-prefix --precise --report-changed-only --skip-columns=guid"
# --- 1) まず全パスを dry-run。DBは変更されない ---
wp search-replace "https://$OLD" "$NEW" $SR --dry-run
wp search-replace "http://$OLD" "$NEW" $SR --dry-run
wp search-replace "//$OLD" "//$NEWHOST" $SR --dry-run
wp search-replace "https:\\/\\/$OLD" "https:\\/\\/$NEWHOST" $SR --dry-run # JSONエスケープ形
wp search-replace "http:\\/\\/$OLD" "https:\\/\\/$NEWHOST" $SR --dry-run
wp search-replace "\\/\\/$OLD" "\\/\\/$NEWHOST" $SR --dry-run各オプションの理由(省略しない):
--precise— wp-cli は既定で一部を SQL 側の REPLACE で処理しうる。全行をPHP側で処理させ、 シリアライズ済みデータを取りこぼさない。移行は一発勝負なので速度を捨てる。--all-tables-with-prefix— 既定はコアが認識するテーブルのみ。プラグインが作ったwp_接頭辞つきテーブル(フォームログ、EC注文明細)が漏れる。--skip-columns=guid— guid は投稿の恒久識別子でURLではない。書き換えるとRSSが全記事を再配信する。- JSONエスケープ形 — Elementor等はJSONを入れ子で保存するため、
\/\/形も別パスで置換する。
dry-run の結果を利用者へ提示し、同意を得てから --dry-run を外して同じ順序で実行する。
実行直前に必ずもう一度DBをエクスポートする。
wp db export ~/pre-replace-$(date +%Y%m%d%H%M).sql # ロールバックの唯一の手段
# ...同じ6コマンドを --dry-run なしで実行...
wp cache flush ; wp rewrite flush --hard ; wp transient delete --all
wp option get siteurl ; wp option get home ; wp option get blog_public
wp db search "$OLD" --all-tables-with-prefix --stats # 0件が正常置換したのに変わらない場合は、wp-config.php の WP_SITEURL / WP_HOME 定数がDBを
上書きしている(最頻)。TROUBLESHOOTING の S16 を見る。
- ホスト名単体(スキーム無し)の置換を既定にしない。
info@old.example.comのような メールアドレスや本文中の言及まで巻き込む。必要な場合だけ、影響を提示して同意を取る。 - dry-run が 0 件なら、対象DBが違う/すでに置換済み/
--oldの指定が格納形式と一致していない。wp db searchで実際の出現箇所を確認する。
Step 5-B: WP-CLI が使えない環境(共有レンタルサーバー)
日本の制作案件では、移行元・移行先のどちらかがSSHもWP-CLIも使えない共有レンタルサーバー であることが多い。その場合でも Step 5 の原則は変えない。変えるのは置換をどこで行うかだけ。
Step 5 と Step 5-B は、どちらが上位ということはない。移行元・移行先の環境で決まる。 型を確定した直後に、次の順で環境を確定させる。ここを飛ばして手順を組むと現場で止まる。
- そのプランでSSHが使えるか。 主要各社とも提供しているが条件付きで、 下位プランでは提供されない場合がある(例: ロリポップはスタンダード以上、 さくらのレンタルサーバはスタンダード以上)。引き継ぎ案件ではプランを選べないことが多い。
- SSHの認証方式。 公開鍵のみでパスワード認証不可の事業者がある(例: エックスサーバー)。 鍵の発行と登録に時間がかかるので、作業当日に気づくと詰む。
wpが実際に入っているか。 どの事業者もWP-CLIの標準提供を明記していない。 さくらのレンタルサーバは、PHP CLI について「運用方法はお客様に委ねられ、 インストール方法はサポート対象外」と明記している。入っている前提で書かない。wp --version || echo "WP-CLI が無い → Step 5-B へ"- 名前の似た別物と混同しない。 エックスサーバーの「XServer CLI」は
サーバー設定を操作する公式ツール(Node.js と APIキーが必要)であって、WP-CLI ではない。
これがあるからといって
wp search-replaceが使えるわけではない。
いずれかの理由でWP-CLIを使えないと確定したら、以下の Step 5-B へ進む。 プランや仕様は変わるので、各社の公式仕様ページで都度確認すること。
使えない場合の手順:
- DBを取り出す。 phpMyAdmin の「エクスポート」、または事業者のバックアップ機能を使う。
形式はSQL、文字セットは元のDBに合わせる(
utf8mb4をutf8で出すと絵文字が壊れる)。 - ローカルにWP-CLIが使える場所を用意し、そこへインポートして置換する。
ローカルのMySQL/MariaDB、または
npx @wp-playground/cliのような使い捨て環境でよい。 置換は Step 5 と同じ6形式・同じオプション・dry-run先行で行う。 - 置換済みのDBをエクスポートし、移行先へインポートする。
phpMyAdmin のインポートはファイルサイズ上限に当たりやすい。分割するか、
事業者のインポート機能を使う。途中で切れたまま「完了」に見えることがあるので、
インポート後に投稿件数と
siteurlを必ず照合する。 - ファイルは FTP/SFTP で運ぶ。数万ファイルのFTP転送は欠落しても気づけないので、 転送後にファイル数とサイズを両側で照合する。
この経路で絶対にやってはいけないこと:
- phpMyAdmin の「検索と置換」やSQLの
UPDATE ... REPLACE()でURLを一括置換すること。 シリアライズ文字列の長さが壊れ、ウィジェット・テーマ設定・ページビルダーが後から消える (症状と復旧はreferences/TROUBLESHOOTING.mdS5)。 WP-CLIが手元に無いことは、生SQLで置換してよい理由にならない。 置換だけのためにローカル環境を用意する手間の方が、確実に安いと利用者へ説明する。 - エクスポートしたDBダンプや
wp-config.phpを、共有設定のクラウドストレージへ置くこと。 認証情報を含むので、暗号化し、期限を決めて削除する。
なお、この経路では Step 2 の調査もWP-CLIで行えない。管理画面(設定 > 一般、設定 > 表示設定の
検索避け、設定 > パーマリンク)、phpMyAdmin の wp_options、FTPでの wp-config.php 確認、
サーバーパネルのPHPバージョン表示で同じ項目を埋める。取得できない項目は「OK」にせず未確認と記録する。
Step 6: DNS切替の「前」に検証する
hosts ファイルで自端末だけ新サーバーへ向け、本番URLのまま確認する。
203.0.113.10 new.example.jp www.new.example.jp確認する項目:
curl -sI https://new.example.jp | head -n 20 # ステータス、リダイレクト、X-Robots-Tag
curl -sIL https://new.example.jp | grep -i '^location' # リダイレクト連鎖とループ
curl -s https://new.example.jp | grep -Ei 'noindex|rel="canonical"|http://'
curl -s https://new.example.jp/robots.txt # Disallow: / が無いことトップ、投稿、固定ページ、アーカイブ、カテゴリ、検索結果、404、フォーム送信(受信箱で確認)、
会員ログイン、カート、管理画面のメディア一覧とプラグイン設定の中身。
wp option get blog_public が 1 であること。
FAILが残っている状態でDNSを切らない。
Step 7: 切替と切替後検証
切替直前に凍結期間中の差分を確認する。増えていたらDBを取り直して Step 4〜5 をやり直す。 切替後、旧サーバーは最低でもTTL経過+7日残す。RUNBOOK Phase 10〜11 の全項目を確認する。
Step 8: 引き渡し
- 検証結果(残った懸念とその許容判断)
- 旧サーバーの保持期限と解約予定日
- ロールバック手順とその有効期限
- 手で戻す必要がある設定(検索避け、
WP_DEBUG、キャッシュ、セキュリティ、cron、メール、Basic認証) - 移行後に別作業として行うこと(PHPアップグレード、プラグイン更新)
止まる条件(利用者に急かされても越えない線)
移行は「早く終わらせる」より「戻せる状態を保つ」方が優先。次の状況では作業を進めず、 理由と代わりに何をするかを利用者へ返す。
- バックアップが無い、または復元できるか分からない。 「後で取る」「たぶん取ってある」「ダンプはあるが中身は見ていない」はすべて未取得として扱う。 先に取得と復元可能性の確認(Step 4)を提案する。
- 包括的な事前同意を根拠に、以降の確認を省略するよう求められた。 「全部同意済みとみなして」「自分のサイトだから確認不要」であっても、 DBを書き換える操作の直前には、その操作ごとに内容と件数を提示する。 同意は「方針への同意」であって「個々の破壊的操作への白紙委任」ではない。 利用者の所有権が確認できることは、確認を省略する理由にならない。
- dry-run の結果を見ていない、または結果が想定と食い違う。 0件、桁が違う、想定外のテーブルが出た場合は止めて原因を先に説明する。
- 型Aなのに URL 置換を求められた。 不要である理由を説明し、実行しない。
- DNS切替前の検証が終わっていない。 hosts 検証(Step 6)で未解決の問題が残る状態で切替えない。
- 移行とPHP・プラグインの一括更新を同時にやるよう求められた。 障害の切り分けが不可能になる。
- 本番DBへバックアップを試し戻しするよう求められた。 検証は使い捨て環境で行う。
止まるときは「できません」で終わらせない。何が足りないか、それを満たすのに何分かかるか、 満たさずに進めた場合に何が起きるかを具体的に示し、判断材料を渡す。
使うときの注意
- 利用者が所有・管理するサイトに対してのみ使う。
- 移行とPHPアップグレードを同時に行わない。 障害の切り分けが不可能になる。
- 判断できない状態を「たぶん大丈夫」で通さない。懸念として明示して利用者に返す。
- 復旧の見込みが立たない場合、時間を使い切る前にロールバック(RUNBOOK Phase 13)へ切り替える。 判断のデッドラインは作業開始前に合意しておく。
参照
references/RUNBOOK.md— 移行の型判定から事前調査、日程、バックアップ、ファイル/DB移行、 wp-config再作成、URL置換、hosts検証、切替、切替後検証、引き渡し、ロールバック、実行前チェックリストreferences/TROUBLESHOOTING.md— S1〜S16の症状別対処(白画面、DB接続エラー、リダイレクトループ、 パーマリンク404、シリアライズ破損、画像の旧ドメイン残存、混在コンテンツ、noindex残存、 robots.txt、DNS未浸透、メール不達、cron停止、ログイン不可、置換が反映されない)
MIT License. Provided as-is, without warranty. Part of PENGIN Tools.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

