# 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.

Source: https://vpsnine.com/help/move-from-shared-hosting-to-a-vps · Updated: 2026-10-16

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](https://vpsnine.com/help/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](https://vpsnine.com/help/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:

```bash
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:

```bash
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.com
```

## Copy the database

Export it from the old host with phpMyAdmin (**Export**, format SQL), or with `mysqldump` if you have SSH there:

```bash
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](https://vpsnine.com/apps/wordpress), they already exist: the database and user are both `wordpress`, and the password is in `/root/wordpress-db.txt`.

```bash
mariadb newdb < site.sql
```

Update 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 with `sudo`.
- **Windows**: `C:\Windows\System32\drivers\etc\hosts`, edited in Notepad run as administrator.

```text
203.0.113.10  example.com www.example.com
```

Now 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:

```bash
tail -f /var/log/nginx/error.log
```

Missing 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:

1. **Leave it there for now.** Keep the hosting account and leave the `MX` records pointing at it. Only change the `A` records for the website. This is the safest choice for the move itself.
2. **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.
3. **Run your own mail server.** Possible, but a lot of work to do well, and sending needs port 25, which is [blocked by default](https://vpsnine.com/help/open-port-25) 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](https://vpsnine.com/help/open-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:

1. Put the old site in maintenance mode, or stop making changes, so nothing is written there after the final copy.
2. Run the database export and import again, and `rsync` the files again. `rsync` only sends what changed, so it's quick.
3. Change the `A` record for the domain and `www` to the VPS's IPv4, and add `AAAA` records for its IPv6 if [IPv6 works](https://vpsnine.com/help/ipv6-setup).
4. Once `getent hosts example.com` on 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](https://vpsnine.com/help/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 calling `wp-cron.php` is 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](https://vpsnine.com/help/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](https://vpsnine.com/apps/wordpress) 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](https://vpsnine.com/apps/lemp) 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](https://vpsnine.com/plans) has the sizes, and your first order has a 14-day [money-back guarantee](https://vpsnine.com/help/money-back-guarantee).
