Information
This tool moves everything on a server — every site's files, database, and configuration — to a new, empty destination server. Treat the destination as disposable: anything already there will be overwritten. Don't run this against a server that has data you want to keep.
Introduction
Migrately is our custom-built CLI tool that our own support team uses to move WordPress sites on our fully managed service from one server to a brand-new one. This is now available to everyone using GridPane.
What it does
Migrately copies the following from one server to another:
- All WordPress files
- The whole database instance
- The web server config (including your custom configurations such as server-wide 7G rules, cache exclusions, etc)
- The PHP config
- The Redis config
- SSL certificates
This guide will walk you through a standard move step by step. Like most of our articles, this is essentially an exercise in copy-and-paste — you’ll just need to swap in your own server address and a few file paths.
Before You Start
This is a CLI-based tool, so you will need to connect to your servers over SSH to follow this article. If this is your first time connecting to one of your servers, please see the following articles to get started:
Step 1. Generate your SSH Key
Step 2. Add your SSH Key to GridPane (also see Add default SSH Keys)
Step 3. Connect to your server by SSH as Root user (we like and use Termius)
Server Requirements
You’ll need the following to begin using Migrately:
- Two GridPane servers – your old one (the source) and a brand-new, empty one (the destination).
- Both servers need to use the same server stack (both Nginx or both OpenLiteSpeed), and same database engine (both Percona, or both MariaDB) – you can check this in your GridPane dashboard if you’re unsure.
- A rough idea of how much disk space your sites and database currently use, so you can confirm the new server has enough room.
If you’ve created a brand new server but it’s not running the right server stack and/or database engine, simply delete it and create a provision a new one.
DNS Changeover
A word on downtime: Migrately doesn’t pause your live sites while it copies files and databases – visitors can keep browsing, and orders can keep coming in on the old server right up until you’re ready to switch over.
For a clean cutover, stop any writes to the old site (put it in maintenance mode, or simply schedule the move for a quiet time) before the file and database steps, and only point your domain at the new server once everything below shows success.
Step 1: Create Your Settings File
Log in to your old (source) server over SSH and create a settings file that tells migrately where to send everything. Copy and paste the following command to create and open the file:
nano /root/migrately.conf
The example configurations below will rehome your whole server, which means all sites transferred from your old production server to your new production server. If you continue down this section (Option 2), you’ll also find settings for moving a production server to a staging server (where we will set the WP_ENVIRONMENT_TYPE to staging and add the X-Robots-Tag HTTP header to set your sites to no-index).
Option 1: Clone Production to Production
Copy and paste the following lines into your migrately.conf, then replace the two placeholder lines (marked below) with your own new server’s address:
sites: all
server-ssh-login: root@YOUR-NEW-SERVER-IP
dest-path: /var/www
db-user: root
db-backup-dir: /root/migrately-db
restore-mode: direct- Replace YOUR-NEW-SERVER-IP with your new server’s IP address (for example [email protected]).
- Leave the other lines as they are — these are sensible defaults for a standard move.
Save and close the file (in nano, that’s Ctrl+O followed by Enter, then Ctrl+X).
Option 2: Clone Production Server to Staging Server (de-indexed)
The following configuration will set:
define('WP_ENVIRONMENT_TYPE', 'staging');in your wp-config.php files.X-Robots-Tag: noindex, nofollow, nosnippet, noimageindexHTTP header.
These will be set on every site on the destination server, making your destination server fully configured to act as a staging/development environment.
Copy and paste the following, replacing the highlighted IP address with your destination server IP address:
sites: all
server-ssh-login: root@198.99.101.99
dest-path: /var/www
db-user: root
db-backup-dir: /root/migrately-db
restore-mode: direct
environment_type: staging
Save and close the file (in nano, that’s Ctrl+O followed by Enter, then Ctrl+X).
When running your migration, Finalize (menu 10) uses curl --resolve to hit the destination’s IP directly, since DNS still points at the source. This confirms the destination itself is serving the header. More details on this can be found in Step 3.
Important
These settings instruct crawlers to respect the header but can't enforce it. They are not access control and don't block traffic. The easiest way to keep it private is to use a local hosts file redirect when working on development sites.
Step 2: Connect the Two Servers
Log in to your old (source) server over SSH and start the tool with the following command:
migrately
This opens a numbered menu. The first two options set up a secure connection between your two servers:
- Type
1and press Enter — this creates a special SSH key just for this migration. - Type
2and press Enter — this prints that key to your screen.
Next, log in to your new (destination) server and edit the authorized_keys file with the following command:
nano /root/.ssh/authorized_keys
Back on your origin server, copy your newly created key and then paste it into this file – you will see a few keys already there and you can add it at the bottom. Now save the file with CTRL+O followed by Enter, and close the file with CTRL+X.
That’s it! Your two servers can now talk to each other securely.
Step 3: Run the Migration
Because this process can take a while, run it inside a screen session so it keeps running even if your internet connection drops. Copy and paste the following command to get started:
screen -S migrate
Here’s a quick rundown on how and why to use a screen, and how to watch the tool’s progress:
screen -S migratekeeps the job running if your connection drops.- Detach with Ctrl-A then D, and reattach with
screen -r migrate. - Stop it any time with Ctrl-C. Re-running the same command picks up where it left off.
Option 1: Manual Run
Start Migrately with the following command:
migrately -c /root/migrately.conf
You’ll see the same numbered menu as before. This time, work through options 3-10 in this exact order, pressing Enter after each one to return to the menu:
| Type this | What it does |
|---|---|
3 |
Runs Redis migration |
4 |
Creates your sites on the new server |
5 |
Creates any additional/alias domains |
6 |
Copies all your site files |
7 |
Copies your entire database |
8 |
Moves your web server settings and SSL certificates |
9 |
Moves your PHP settings |
10 |
Finishes up and switches everything on |
Option 2: Run 3→10 and then 14 to Exit
The following command will run options 3 → 4 → 5 → 6 → 7 → 8 → 9 → 10, one by one, and then 14 to exit:
printf '3\n\n4\n\n5\n\n6\n\n7\n\n8\n\n9\n\n10\n\n14\n' | migrately -c /root/migrately.conf
(Typing 14 at any point exits the tool.)
You can open the Migrately back up again once this is complete by entering:
migrately
If you get disconnected
If your screen session gets disconnected partway through, don’t worry — just log back in and reattach with:
screen -r migrate
Migrately keeps working in the background even while you’re disconnected.
Step 4: Check Everything Came Across
Once step 10 finishes, it’s worth double-checking your data landed correctly. Back at the menu, type:
11
This compares posts, users, plugins, and themes between your old and new server and tells you if anything doesn’t match.
Once you’re happy everything looks right, you can safely point your domain’s DNS to the new server.
Optional: Matching Your Backup Settings
If your old server had scheduled backups set up, you can copy those settings across too — but you must do this last, only once you trust the migration has completed the previous steps successfully.
- Type
12to match your local backup schedule - Type
13to match your remote (cloud) backup storage and schedule
Both of these are safe to run more than once — if a setting already matches, nothing changes.
If a Site Gets Skipped
If any single site couldn’t be moved (for example, it didn’t finish building in time at step 4), Migrately won’t stop the whole migration – it will skip just that one site, tell you clearly which site and which step, and keep going with everything else.
At the very end, you’ll see a summary listing anything that needs attention, along with what to do about it (usually: go back to option 4 to build the missing site, then re-run the step it was skipped at for just that site).
Don’t point your domain at the new server until every site in that summary has been resolved.
Step 5: Wrapping Up
You can exit the Migrately CLI tool by entering:
14
When migrately finishes, it returns an exit status that tells you how the run went. Below is a breakdown of all possible outcomes:
| Status | What happened | What you'll see / what it means |
|---|---|---|
| 0 | The run reached option 14 (exit). | The input stream completed. It does not guarantee every site verified successfully. |
| 1 | Input ran out before option 14. | A message lists which options did complete. |
| 1 | Option 12 or 13 was selected, but a site's backup configuration couldn't be matched or was put on hold by a committed handoff. | The output includes a section called SITES WITH INCOMPLETE SELECTED WORK IN THIS RUN, listing each site, the stage, the reason, and the fix. The site itself may still be fully migrated. |
| 1 | A step failed. | Check the output for the failing step. |
| 1 | The run finished but skipped some sites (not on the destination, or a per-site transfer failed). | The output includes a section called SITES SKIPPED OR FAILED IN THIS RUN, listing each site and the step where it was skipped. |
| 1 | The script was started on a server that is itself a claimed destination. | Run it from the source server instead. |
| 1 or 255 | SSH failure. | See the note below. |
| 2 | Auth normalisation couldn't confirm a rollback. | Verify the auth state manually. |
| 73 | The destination refuses the run because it is claimed by a different source. | Another source already owns this destination. |
| 74 | The destination refuses the run because its own migrately session is running. | Wait for that session to finish. |
| 75 | The destination refuses the run because of a committed handoff freeze, or another migrately already holds this source's lock. | Wait for the freeze or the other run to clear. |
| 130 | You pressed Ctrl-C. | The run was cancelled manually. |
Notes on SSH failures
- A connection failure mid-run returns 1 or 255, depending on which call hit it.
- Building a site restarts the destination’s sshd, so the next option may briefly fail with “Connection refused.”
- Either way, migrately tries to recover its workers and release its claim on the destination. Check
/var/log/migrately-cleanup.logto see whether both succeeded. - The fix is usually to re-run the same stream. Sites that were already built are detected as present.
Tip
Run unattended jobs inside screen or tmux. The exit-status behavior is the same either way, but a dropped terminal won't kill the job.
Troubleshooting
If you run into a message you don’t recognize, or a step fails partway through, your session log will have the full details — check the terminal output, or if you used script to record your session, review that log file. You can always safely re-run any step; migrately is designed to pick up where it left off.
