Move to a larger Rack4 server

When add-ons aren't enough, move to a bigger server without losing data: copy, test before switching DNS, cut over, and keep a way back until it's proven.

If your server is short of one thing, add it with an add-on and stay where you are. If it needs more than the add-ons allow, order a bigger server, copy everything across, test it before any visitor sees it, then switch over. Cancel the old server only after the new one has run your real traffic for a while.

There's no button that changes a server's plan in place, so a move is always a second server. Plan for a few minutes when nothing is written: that's how you avoid losing data during the switch.

First: is an add-on enough?

Add-ons grow a server in place, without a move: up to 2, 4 or 8 GB more RAM, 1, 2 or 4 more vCPUs, and 80, 160 or 320 GB more disk on Budget, Standard and Extreme. RAM and vCPUs take a restart; disk is live. If that covers it, add-ons is all you need. If the add-ons would cost about as much as the next plan, or you need more than the caps, move.

If the problem is monthly transfer rather than CPU, RAM or disk, a transfer pack fixes it without a move.

What moves and what doesn't

Comes with you, because you copy it Stays with the old server
Files, databases, configuration, cron jobs Its IPv4 address (the new server has its own)
Docker volumes and images (pull or copy them) Its snapshots and off-site backups
Users and SSH keys you added yourself Its panel name, tags, notes, uptime monitors and alerts

The new server's address is different, so anything that points at the old one has to change: DNS records, firewall allow-lists elsewhere, API clients, reverse DNS and mail settings.

1. Order the new server

Order the bigger plan with the same distribution and version as the old one, so packages and config files match. If you'd also like to upgrade the distribution, do that as a separate step later: one change at a time is much easier to undo.

Shortcut if the old server has off-site backups: instead of an empty server, choose new server… next to its latest backup. The new server starts as a copy of the old one, and you can skip to step 4 after a final sync of anything written since that backup. Off-site backups explains it. The copy keeps the old server's settings, including cron jobs and services that send mail or call webhooks; see step 4 below.

2. Let the two servers reach each other

You'll copy straight from the old server to the new one over SSH. Make a key for that on the old server, and put its public half on the new one:

bash
# on the old server
ssh-keygen -t ed25519 -f ~/.ssh/move_ed25519 -N ""
cat ~/.ssh/move_ed25519.pub

Add the printed line to /root/.ssh/authorized_keys on the new server, as in Add or replace an SSH key. Then test, from the old server, with the new server's address:

bash
ssh -i ~/.ssh/move_ed25519 root@203.0.113.50 hostname

Both servers in the same location? Put them on your private network first and copy over the private addresses instead: it's faster, nobody else can reach it, and it doesn't count towards transfer.

If that says No route to host: both servers are on the same host machine, and servers there can't reach each other directly; that keeps one customer's server from listening in on another's. Send the traffic through the gateway instead, by adding a route on each server to the other's address (the gateway is the via address in ip route show default):

bash
# on the old server (203.0.113.42), towards the new one
sudo ip route add 203.0.113.50/32 via 203.0.113.1

# on the new server (203.0.113.50), towards the old one
sudo ip route add 203.0.113.42/32 via 203.0.113.1

These routes last until the next reboot, which is all a move needs. On our test servers, this took the connection from No route to host to working, at well under a millisecond.

3. Copy the data

Databases first. A database's files copied while it's running can be inconsistent, so dump it. For MariaDB or MySQL, on the old server:

bash
mariadb-dump --single-transaction --routines --triggers shop > /root/shop.sql

For PostgreSQL, sudo -u postgres pg_dump -Fc shop > /root/shop.dump. Repeat for each database.

Then the files, from the old server. Do a dry run first: -n shows what would be copied without copying anything.

bash
rsync -aHAX --numeric-ids -n --stats -e "ssh -i ~/.ssh/move_ed25519" /var/www/ root@203.0.113.50:/var/www/
rsync -aHAX --numeric-ids -e "ssh -i ~/.ssh/move_ed25519" /var/www/ root@203.0.113.50:/var/www/
rsync -a -e "ssh -i ~/.ssh/move_ed25519" /root/shop.sql root@203.0.113.50:/root/

The trailing / on both paths means "the contents of this folder"; keep them. -aHAX --numeric-ids keeps owners, permissions, hard links, ACLs and extended attributes as they were. Copy each folder your services use, typically /var/www, /etc/nginx (or your web server's config), /home, app folders under /opt or /srv, Docker volumes in /var/lib/docker/volumes, and your crontab (crontab -l). Don't copy all of /: system files belong to the new server's own system.

On the new server, install the same software, then load the dumps into empty databases:

bash
mariadb -e "CREATE DATABASE shop"
mariadb shop < /root/shop.sql

(pg_restore -d shop /root/shop.dump for PostgreSQL, into an empty database.) Compare a count or two with the old server, for example SELECT COUNT(*) FROM orders;, so you know the copy is complete.

4. Test it before anyone else sees it

Test the new server under your real domain name without changing DNS, by telling only your own computer where to go:

bash
curl --resolve example.com:443:203.0.113.50 https://example.com/

For a browser, add a line like 203.0.113.50 example.com to your computer's hosts file (/etc/hosts on Linux and macOS, C:\Windows\System32\drivers\etc\hosts on Windows), and remove it when you're done. Log in, click around, check that pages, uploads and logins work, and read the logs on the new server.

Two things to watch on a copy:

  • Jobs that act on the outside world. Cron jobs, queues and timers on the new server can send emails, charge cards or call webhooks a second time. Pause them until the cutover (crontab -e and comment them out, systemctl stop the worker), unless they're harmless.
  • HTTPS. A certificate copied from the old server works for testing. For a fresh one, certbot can only verify the domain once DNS points at the new server, so either copy /etc/letsencrypt across or get the certificate right after the switch.

5. Switch over

  1. A day before, lower the TTL on your DNS records to 300 seconds, so the switch spreads quickly.
  2. Stop writes on the old server: put the site in maintenance mode, or stop the app.
  3. Dump the databases again and run the same rsync commands again. Only what changed since the first copy is sent, so it's quick.
  4. Load the fresh dumps on the new server and start its services, including the jobs you paused.
  5. Change the DNS A records to the new address.
  6. Watch the new server's logs, and the old one's: requests still reaching the old server are visitors whose DNS hasn't caught up yet.

6. Keep a way back

Don't cancel the old server yet. Keep it, stopped or with its app stopped, until the new one has handled real traffic for a few days. If something goes wrong, point DNS back at the old address and start its app again; anything written on the new server meanwhile has to be copied back by hand, so decide quickly.

When you're sure, cancel the old server. Unused time on it isn't refunded, so if its renewal is near, plan the move before it. Then tidy up: remove the temporary routes (or reboot), delete ~/.ssh/move_ed25519 on the old server and its line from the new server's authorized_keys, and update monitors, alerts and API scripts to the new server.

We tested the copy and restore steps on this page on two Rack4 servers on 6 November 2026 (Ubuntu 24.04 with MariaDB 10.11 to Debian 13 with MariaDB 11.8), including the No route to host case and the gateway routes that fix it.

Ready when you are

Order a server