Skip to content

Instantly share code, notes, and snippets.

@Braunson
Created November 28, 2025 19:25
Show Gist options
  • Select an option

  • Save Braunson/41db83ee293a70fd6baecbbc4f48b1ce to your computer and use it in GitHub Desktop.

Select an option

Save Braunson/41db83ee293a70fd6baecbbc4f48b1ce to your computer and use it in GitHub Desktop.
WP-CLI Migration script to move a WordPress Multisite from one domain to another

WordPress Multisite Migration Script using WP-CLI

WordPress Multisite migration: staging.mysite.com -> mysite.com Uses WP-CLI only. Run this on the STAGING server, in the WP root or set WP_PATH.

How to use

chmod +x wp-migrate.sh
./wp-migrate.sh

Then manually update the wp-config.php file and set the DOMAIN_CURRENT_SITE to mysite.com and confirm PATH_CURRENT_SITE, SUBDOMAIN_INSTALL etc where applicable.

Finally log into Network Admin on the new site and confirm sites loads and permalinks work.

#!/usr/bin/env bash
#
# WordPress Multisite migration: staging.mysite.com -> nysite.com
# Uses WP-CLI only. Run this on the STAGING server, in the WP root or set WP_PATH.
#
set -euo pipefail
### CONFIG #####################################################################
# Absolute path to the WordPress install on STAGING
WP_PATH="/var/www/html" # <-- CHANGE THIS
# Old (production) and new (staging) domains (no scheme, no trailing slash)
OLD_DOMAIN="staging.mysite.com" # <-- CHANGE THIS
NEW_DOMAIN="mysite.com" # <-- CHANGE THIS
# Optional: protocol currently used on staging (for info / logging only)
SCHEME="https"
###############################################################################
echo ">>> Changing directory to: ${WP_PATH}"
cd "$WP_PATH"
echo ">>> Checking that WordPress is installed..."
wp core is-installed >/dev/null 2>&1 || {
echo "ERROR: WordPress is not installed here. Check WP_PATH."
exit 1
}
echo ">>> Checking if this is a multisite network..."
IS_MS=$(wp eval 'echo is_multisite() ? "yes" : "no";')
if [ "$IS_MS" != "yes" ]; then
echo "ERROR: This install is NOT multisite. Aborting."
exit 1
fi
echo "OK: Multisite detected."
echo ">>> Showing current network home/siteurl (for reference):"
wp network meta list --fields=network_id,meta_key,meta_value | grep -E 'siteurl|home' || true
echo ">>> Showing current NETWORK domain + path (wp_site):"
wp db query "SELECT * FROM wp_site;" || true
echo ">>> Showing current blogs (wp_blogs) before replacement:"
wp db query "SELECT blog_id, domain, path FROM wp_blogs ORDER BY blog_id;" || true
###############################################################################
# CORE SEARCH-REPLACE
###############################################################################
echo
echo ">>> Running network-wide search-replace:"
echo " ${OLD_DOMAIN} -> ${NEW_DOMAIN}"
echo
# 1) Replace domain everywhere (handles serialized data)
wp search-replace "${OLD_DOMAIN}" "${NEW_DOMAIN}" \
--network \
--all-tables-with-prefix \
--skip-columns=guid \
--precise \
--report-changed-only
echo
echo ">>> Search-replace complete."
echo
###############################################################################
# SANITY CHECKS
###############################################################################
echo ">>> Checking wp_site after replacement:"
wp db query "SELECT * FROM wp_site;" || true
echo
echo ">>> Checking wp_blogs after replacement:"
wp db query "SELECT blog_id, domain, path FROM wp_blogs ORDER BY blog_id;" || true
echo
echo ">>> Listing sites and URLs according to WP-CLI:"
wp site list --fields=blog_id,domain,path,url
echo
echo ">>> Verifying home + siteurl for each site:"
wp site list --field=url | while read -r SITE_URL; do
echo
echo "---- $SITE_URL ----"
wp option get home --url="$SITE_URL" || true
wp option get siteurl --url="$SITE_URL" || true
done
###############################################################################
# REWRITE / CACHE
###############################################################################
echo
echo ">>> Flushing rewrite rules for the network..."
wp rewrite flush --network --hard
echo
echo ">>> Flushing caches (if any)..."
wp cache flush || true
###############################################################################
# REMINDERS
###############################################################################
cat <<EOF
===============================================================================
MIGRATION SCRIPT COMPLETE
===============================================================================
1) Manually confirm wp-config.php contains the correct DOMAIN_CURRENT_SITE:
Example:
define( 'DOMAIN_CURRENT_SITE', '${NEW_DOMAIN}' );
And that PATH_CURRENT_SITE, SUBDOMAIN_INSTALL, etc. are correct for your setup.
2) Confirm staging is accessible at:
${SCHEME}://${NEW_DOMAIN}/
and each sub-site loads correctly.
3) Log into Network Admin on STAGING and quickly re-save permalinks
if needed:
- My Sites -> Network Admin -> Sites/Settings
- My Sites -> Network Admin -> Settings -> Permalinks
4) If you're behind a reverse proxy / CDN, make sure its config also points
to ${NEW_DOMAIN} and doesn't rewrite back to ${OLD_DOMAIN}.
===============================================================================
EOF
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment