Copied to clipboard

WP-Migrate Documentation

A CLI tool for migrating WordPress sites between servers. Automatically detects SSH, SFTP, or FTP access and uses the fastest method available.

Installation

macOS & Linux

Run the installer script which automatically detects your system and downloads the correct binary:

bash
$ curl -fsSL https://wp-migrate.dev/install.sh | bash

This installs wp-migrate to /usr/local/bin (requires sudo).

Windows

Download wp-migrate-windows.exe from the latest release and add it to your PATH.

Manual Installation

Download the appropriate binary for your platform from GitHub Releases:

Quick Start

Interactive Wizard

The easiest way to run a migration is with the interactive wizard:

bash
$ wp-migrate

The wizard will prompt you for source and destination credentials, then run the migration automatically.

Command-Line Mode

For automation or scripted migrations, generate a sample config, edit it, then run the migration:

bash
$ wp-migrate init                       # writes a documented config.yaml
$ wp-migrate validate -c config.yaml    # check it before running
$ wp-migrate migrate -c config.yaml     # run the full migration

Licensing

WP-Migrate includes 3 free migrations to try the tool. After that, you'll need to purchase a license.

Activating a License

bash
$ wp-migrate activate YOUR-LICENSE-KEY

Deactivating a License

To move your license to a new machine:

bash
$ wp-migrate deactivate

Check License Status

bash
$ wp-migrate status
License Types

Single User ($39) - 2 machine activations, unlimited migrations.
Agency ($149) - Unlimited activations, unlimited migrations.

Configuration

Create a YAML configuration file for scripted or repeatable migrations:

yaml
# config.yaml — generate with `wp-migrate init`
source:
  host: oldsite.com
  user: oldsite_user
  pass: "${SOURCE_PASS}"   # Environment variable
  type: auto             # auto | ssh | sftp | ftps | ftp
  # key_file: ~/.ssh/id_rsa   # Optional: SSH key instead of password
  wp_path: /public_html

destination:
  host: newsite.com
  user: newsite_user
  pass: "${DEST_PASS}"
  type: auto
  wp_path: /public_html
  # Database credentials (required for SFTP/FTP, optional with SSH+WP-CLI)
  db_host: localhost
  db_name: newsite_wp
  db_user: newsite_dbuser
  db_pass: "${DEST_DB_PASS}"
  new_url: https://newsite.com

Configuration Reference

Key Description Required
host Server hostname Yes
user Connection username Yes
pass Connection password (supports env vars) Yes*
type Connection type: auto (default), ssh, sftp, ftps, or ftp No
port Connection port (defaults based on type: 22 for SSH/SFTP, 21 for FTP) No
key_file Path to SSH private key (instead of pass) No
key_passphrase Passphrase for an encrypted SSH key No
wp_path Path to WordPress installation Yes
db_host Database hostname Dest only
db_name Database name Dest only
db_user Database username Dest only
db_pass Database password Dest only
new_url New site URL for search-replace Dest only
server_ip Server IP for pre-DNS testing No

* pass is required unless you authenticate with an SSH key_file. Database credentials are required for SFTP/FTP transfers and optional when SSH + WP-CLI is available.

Legacy field names

Older configs using ftp_host, ftp_user, ftp_pass, ftp_type, and ftp_port still work as aliases for host, user, pass, type, and port. New configs should use the shorter names above.

Security Tip

Never commit passwords to version control. Use environment variables like ${VAR_NAME} in your config file, then set them in your shell before running.

Multisite

Multisite networks are auto-detected from the source wp-config.php, so a normal migrate handles a whole network with no extra config. Add an optional multisite block only to override behaviour or remap specific subsites:

yaml
# Optional — only needed to override auto-detection
multisite:
  enabled: true          # omit to auto-detect; false forces single-site handling
  subdomain: true        # omit to inherit source SUBDOMAIN_INSTALL
  subsite_mappings:     # optional: remap specific subsites
    - old: shop.oldsite.com
      new: shop.newbrand.com

To import a standalone site into an existing network as a new subsite, set mode: multisite-import with a multisite_import block and run wp-migrate import-to-network -c config.yaml:

yaml
mode: multisite-import
# destination.new_url is the NETWORK's base URL in this mode
multisite_import:
  subsite_slug: myblog       # required; lowercase letters/digits/hyphens
  default_role: editor      # role for source users lacking one (default: subscriber)
  # network_admin_user: admin  # optional: grant this network user admin on the subsite

Commands

Command Description
wp-migrate Run the interactive migration wizard (no arguments)
wp-migrate start Start the wizard, optionally pre-loading a config
wp-migrate init Write a sample, documented config file
wp-migrate validate -c <file> Validate a migration config file
wp-migrate test-connection -c <file> Test source/destination connections
wp-migrate migrate -c <file> Run a full migration (files + database + URL replace)
wp-migrate import-to-network -c <file> Import a standalone site into an existing multisite network
wp-migrate export -c <file> Export the source database only
wp-migrate import -c <file> --sql <file> Import a database to the destination
wp-migrate verify -c <file> Show pre-DNS-cutover testing instructions
wp-migrate verify-site -c <file> HTTP-check the migrated site before DNS cutover
wp-migrate deploy-agent -c <file> Deploy the PHP agent to a server and verify it works
wp-migrate cleanup -c <file> Remove PHP agents and temporary files from servers
wp-migrate activate <key> Activate license on this machine
wp-migrate deactivate Deactivate license from this machine
wp-migrate status Show license and trial status
wp-migrate --version Show version information
wp-migrate --help Show help (works on any subcommand too)

Common Flags

Flag Description
--config, -c Path to YAML configuration file
--dry-run Show what would be done without making changes
--skip-files Skip file transfer (database only)
--skip-db Skip database migration (files only)
--skip-search-replace Skip URL search-replace (same-URL migrations with DNS cutover)
--source-url Override the source site URL used to reach the agent
--yes, -y Skip the confirmation prompt

Pre-DNS Testing

Test your migrated site before switching DNS by adding the server_ip option to your destination config:

yaml
destination:
  # ... other settings ...
  new_url: https://newsite.com
  server_ip: 192.168.1.100  # Destination server IP

After migration completes, add an entry to your local /etc/hosts file:

bash
192.168.1.100  newsite.com

Now you can visit https://newsite.com in your browser to test the migrated site on the new server before updating DNS.

How It Works

WP-Migrate automatically detects the best available method for each server:

1. Server Detection

When connecting to a server, WP-Migrate checks for:

2. File Transfer

3. Database Migration

4. URL Replacement

WP-Migrate performs serialization-aware search-replace:

Multisite

WP-Migrate supports WordPress multisite in two ways:

Migrate an entire network (network → network)

Auto-detected from the source wp-config.php — just run a normal migration. Network constants are regenerated for the new host and every subsite's URLs (including the wp_blogs / wp_site domain columns) are rewritten.

bash
$ wp-migrate migrate -c config.yaml

Import a standalone site into an existing network

Add mode: multisite-import and a multisite_import block (see Configuration), then preview and run:

bash
$ wp-migrate import-to-network -c config.yaml --dry-run   # preview
$ wp-migrate import-to-network -c config.yaml             # run

WP-Migrate registers a new subsite, imports the source's tables under a new wp_{N}_* prefix, merges users (matching by login/email), relocates media to wp-content/uploads/sites/{N}/, and rewrites URLs — leaving the rest of the network untouched. The network's wp-config.php and database are preserved.

Security

PHP Agent Security

When SSH is not available, WP-Migrate deploys a temporary PHP agent for database operations. The agent includes multiple security measures:

Credentials

Recommended Practices

Support

Need help? Here's how to get support:

Priority Support

Agency license holders receive priority email support with faster response times.