Move a site from shared hosting to a VPS
Copy your files and database across, test the site on the new server before anyone sees it, keep your email working, and switch DNS with no downtime.
To move a site from shared hosting to a VPS, set up the same software on the new server, copy the files and database across, test the site there through your own hosts file, then point DNS at the new server and keep the old account for a week. Done in that order, visitors never see a broken site.
The part people forget is email. If your mailboxes live on the shared host, read the email section before you change any DNS.
Before you start: take stock
Log in to your hosting control panel and write down:
- What the site runs on: PHP version, database (MySQL or MariaDB), any PHP extensions it relies on. Most cPanel hosts show these under "Select PHP Version".
- Every domain and subdomain pointing at the account.
- Cron jobs, under "Cron Jobs". They won't move by themselves.
- Email: mailboxes, forwarders and autoresponders on the account.
- Where DNS is hosted. If your nameservers belong to the host, you'll need to move DNS too (see below).
Lower the DNS TTL a day ahead
The TTL on a DNS record is how long other servers may cache it. If it's a day, the switch takes a day to reach everyone. At your DNS provider, set the TTL on your site's A and AAAA records to 300 seconds (five minutes) a day before the move. Put it back up afterwards.
Build the new server
Set up the same stack on the VPS. For a WordPress or other PHP site, that's nginx, PHP-FPM and MariaDB: Host WordPress on a VPS walks through it, and for any PHP site the steps are the same apart from the WordPress download. Do the first hour checklist as well, so the server is secure before the site goes live.
Use the same major PHP version as the old host, or newer if your site supports it.
Copy the files
If your host gives you SSH access, rsync from the VPS is the quickest way. Replace the user, host and paths with yours:
apt install -y rsync
rsync -avz --progress user@oldhost.example.net:public_html/ /var/www/example.com/Without SSH, download the files from the control panel's file manager as a zip (or with an SFTP client such as FileZilla), upload it with scp, and unpack it:
scp site.zip root@203.0.113.10:/var/www/
ssh root@203.0.113.10
apt install -y unzip
cd /var/www && unzip site.zip -d example.com
chown -R www-data:www-data /var/www/example.comCopy the database
Export it from the old host with phpMyAdmin (Export, format SQL), or with mysqldump if you have SSH there:
mysqldump --single-transaction --no-tablespaces -u olduser -p olddb > site.sql--no-tablespaces stops the newer mysqldump asking for a privilege that shared hosting accounts don't have.
On the VPS, create an empty database and user (the WordPress guide has the commands), then import. If you picked the WordPress one-click app, they already exist: the database and user are both wordpress, and the password is in /root/wordpress-db.txt.
mariadb newdb < site.sqlUpdate the app's config with the new database name, user and password. For WordPress that's wp-config.php; set DB_HOST to localhost.
Test before you switch
You want to see the site on the new server while the world still goes to the old one. Your computer's hosts file does that: it overrides DNS for you alone.
Add a line with the VPS's address and your domain:
- Linux and macOS:
/etc/hosts, edited withsudo. - Windows:
C:\Windows\System32\drivers\etc\hosts, edited in Notepad run as administrator.
203.0.113.10 example.com www.example.comNow your browser loads the site from the VPS. It'll be plain HTTP for now, since the certificate comes after the switch. Click through it properly: pages, forms, logins, uploads, anything with a payment. Check the logs on the server while you do:
tail -f /var/log/nginx/error.logMissing PHP extensions show up here. Install them (apt install php-<name>) and restart PHP-FPM.
Remove the line from your hosts file when you're done.
Keep email working
A VPS doesn't come with mailboxes. If your email is on the shared host, you have three options:
- Leave it there for now. Keep the hosting account and leave the
MXrecords pointing at it. Only change theArecords for the website. This is the safest choice for the move itself. - Move it to an email provider (Fastmail, Proton, Google Workspace, Microsoft 365, or your registrar's mail). Set the provider up, copy old messages across with its import tool, then change the
MX, SPF and DKIM records to theirs. - Run your own mail server. Possible, but a lot of work to do well, and sending needs port 25, which is blocked by default on new VPSNine servers.
Most people pick option 2. Either way, don't cancel the shared hosting until email is sorted.
Your site still needs to send email itself, for contact forms and password resets. Use an SMTP relay or transactional email service on port 587 rather than sending directly; Sending email: port 25 explains why.
Switch DNS
If the host runs your DNS (your nameservers are theirs), first copy every record to a DNS provider you control, including MX and TXT, and switch nameservers to it. Then:
- Put the old site in maintenance mode, or stop making changes, so nothing is written there after the final copy.
- Run the database export and import again, and
rsyncthe files again.rsynconly sends what changed, so it's quick. - Change the
Arecord for the domain andwwwto the VPS's IPv4, and addAAAArecords for its IPv6 if IPv6 works. - Once
getent hosts example.comon the VPS shows the new address, get the certificate:certbot --nginx -d example.com -d www.example.com. Serve a site with nginx and HTTPS has the details.
With a five-minute TTL, most visitors are on the new server within the hour.
Afterwards
- Recreate the cron jobs on the VPS with
crontab -e. For WordPress, a real cron job callingwp-cron.phpis more reliable than WordPress's built-in one. - Set up backups on the new server. Shared hosts often did this quietly; on a VPS it's yours. Backups you should run covers it.
- Put the DNS TTL back up to an hour or more.
- Keep the old hosting account for a week, in case something turns up missing, then cancel it.
Doing it on VPSNine
If the site is WordPress, the WordPress one-click app builds nginx, PHP-FPM and MariaDB for you on the first boot. Skip its installer. Import your database into the one the app created, copy your wp-content over the new one, and keep the new wp-config.php, which has the right database details; just set $table_prefix in it to the one from your old wp-config.php. For other PHP sites, the LEMP stack app gives you the same stack without WordPress.
Budget, with 2 GB of memory, is plenty for most sites coming off shared hosting. The plans page has the sizes, and your first order has a 14-day money-back guarantee.