Hostinger VPS Hosting

How to Migrate a WordPress Site to a New VPS Server

March 19, 20245 min read

Moving a WordPress site to a new server doesn't have to be a nightmare. Whether you're upgrading to a faster VPS, switching hosting providers, or setting up a completely new environment, migrations are a normal part of managing a website — and they don't have to cost you a full day of frustration.

But not all migrations are equal. A 500 MB blog behaves very differently from a 20 GB site with tens of thousands of images. A plugin that handles the small site flawlessly might choke and timeout on the large one.

This guide covers two proven approaches:

  1. Plugin-based migration — perfect for small to medium sites (under 2–3 GB). No command line needed.
  2. SSH + wget direct server migration — the professional method that works for any site, of any size. File transfers happen directly between servers — no downloading to your laptop, no re-uploading, no timeouts.

If your site is large, if you've hit plugin timeouts before, or if you simply want the most reliable and fastest method possible, the SSH method is what you're looking for. It's easier than it sounds, and every command is explained below.


Video Tutorial

Before reading on, here's a complete walkthrough video if you prefer to follow along visually:

WordPress Migration Tutorial Video

Method 1: Plugin-Based Migration (Small to Medium Sites)

If your site is under 2–3 GB and you'd rather avoid the command line entirely, the Backup Migration plugin is an excellent choice. It handles everything through the WordPress dashboard and is especially beginner-friendly.

Step 1: Install and Run a Backup on Your Old Site

Install the Backup Migration plugin on your source (old) website directly from the WordPress Dashboard under Plugins → Add New, or download it from wordpress.org/plugins/backup-backup.

Once activated, the plugin adds its own menu item in your dashboard. Go to What will be backed up? and select all components — plugins, themes, files, folders, and databases. Save your selection.

Click Create backup now! to start. For smaller sites this typically completes in a couple of minutes. When done, download the backup zip file to your local storage as a safety copy.

Backup Migration Plugin Settings

For sites larger than 2 GB, consider the premium version of Backup Migration which handles larger archives without PHP timeout issues.

Step 2: Restore on the New Site

Set up WordPress on your destination server (most hosts offer one-click installs), then install the same Backup Migration plugin.

Go to Manage & Restore Backup(s). You have three options:

A) Super-quick migration — paste the backup file URL from the old site (found inside the plugin as a small link icon) and click Restore now! Best when both sites are online simultaneously.

B) Manual upload — upload the backup zip file you downloaded. Click Restore next to it. Use this when you have the file locally.

C) External storage (Google Drive) — link your Google account, sync your backup files, and restore from the cloud. Great if you store backups regularly.

Saved Backups in Plugin

Once restored, your site is live on its new host. Set up redirects from the old domain using the Redirection plugin if needed.


Method 2: SSH + wget Migration (Large Sites — Any Size)

This is the method to use when you have a big site, a VPS server, and want the fastest, most reliable migration possible. Instead of downloading a huge backup to your laptop and uploading it again, everything transfers directly between the two servers.

Why that matters:

  • No dependency on your home or office internet connection
  • Data center links run at 1 Gbps or faster — a 10 GB backup that would take hours locally might finish in minutes
  • No browser timeouts, no incomplete file errors
  • Works for sites of literally any size

What You Need Before Starting

  • SSH access to your old server (the one you're migrating away from)
  • A fresh new VPS (a clean install is recommended)
  • Your domain name, and the ability to update its DNS when ready
  • Basic comfort opening a terminal — every command below is explained in plain English

Recommended VPS providers for the new server:

  • UpCloud VPS — consistently fast performance, excellent uptime SLAs, great for WordPress
  • Contabo VPS — budget-friendly with generous specs, solid for general use

Phase 1: Prepare the Old Server

SSH into your old server first. All commands in this phase run on the old server — not the new one.

Step 1: Optional — Clean Up WordPress First

Before creating a backup, take a few minutes to remove unnecessary weight from your WordPress install. This directly reduces your backup size and speeds up every step that follows.

In your WordPress dashboard:

  • Plugins → Installed Plugins — deactivate and delete anything you're not actively using
  • Appearance → Themes — remove any themes that aren't your active theme
  • Media Library — delete unused images and files if your hosting provider's interface makes it easy

Even removing a few large unused media files can shave hundreds of MB off your backup.

Step 2: Back Up Your Database

Your WordPress database contains everything that isn't a file — every post, page, comment, user account, plugin setting, WooCommerce order, and site configuration. We export it using mysqldump, a tool built into MySQL/MariaDB on virtually every server.

mysqldump -u DB_USER -p DB_NAME > sqldump_backup.sql

What each part means:

  • mysqldump — the database export tool that comes with MySQL/MariaDB
  • -u DB_USER — replace DB_USER with your actual database username
  • -p — tells it to prompt you for the password (more secure than typing it directly in the command)
  • DB_NAME — replace with your actual database name
  • > sqldump_backup.sql — the > redirects the output into a file named sqldump_backup.sql

You'll be prompted to enter the database password. Type it and press Enter (you won't see characters — that's normal security behaviour).

The result is a plain-text .sql file containing every table and row from your database. For a typical blog this might be 10–50 MB. For a WooCommerce store with years of order history it could be several hundred MB.

Where to find your database credentials: Open the file wp-config.php in your site's root directory. Look for the lines defining DB_NAME, DB_USER, and DB_PASSWORD.

Step 3: Back Up Your wp-content Folder

The wp-content folder is the most important part of your WordPress files. It contains:

  • uploads/ — every image, PDF, video, and media file your site has ever used
  • plugins/ — all your installed plugins and their files
  • themes/ — all your themes

We do not need to back up the WordPress core files (wp-admin/, wp-includes/, etc.) because we'll install a fresh copy on the new server. This actually works in your favour — you get a clean, up-to-date WordPress core without any cruft from the old install.

First, navigate to the root directory of your website:

cd /var/www/domain.com/htdocs/

Replace domain.com with your actual domain. The exact path varies by hosting setup — common alternatives include /var/www/html/, /home/username/public_html/, or /var/www/vhosts/domain.com/httpdocs/. If you're not sure, try ls /var/www/ to see what directories exist.

Now create a compressed archive of just the wp-content folder:

tar -czvf wp_content_bck.tar.gz wp-content/

Breaking down this tar command:

  • tar — the archiving tool (think of it as a command-line zip utility, but more powerful)
  • -ccreate a new archive
  • -z — compress using gzip (significantly reduces file size)
  • -vverbose output (shows you each file being added — useful to confirm it's working)
  • -f wp_content_bck.tar.gz — the output file will be named wp_content_bck.tar.gz
  • wp-content/ — the folder we're archiving

You'll see a stream of filenames in the terminal as files are added. For a large site with thousands of images, this can take a few minutes. When it finishes and returns you to the command prompt, the archive is complete.

Step 4: Move Backup Files to a Web-Accessible Directory

For the new server to download these files using wget, they need to be reachable via a plain HTTP URL. The simplest way is to move them to /var/www/html/, which is served by your web server.

mv wp_content_bck.tar.gz /var/www/html/
mv sqldump_backup.sql /var/www/html/

The mv command moves (not copies) files from one location to another. After running these, your backup files will be accessible at:

  • http://YOUR_OLD_SERVER_IP/wp_content_bck.tar.gz
  • http://YOUR_OLD_SERVER_IP/sqldump_backup.sql

Security note: These files will be publicly downloadable from the internet for the duration of the migration. They contain your full site data, including user information. Keep the migration window as short as possible, and delete these files from /var/www/html/ immediately after the new server has downloaded them.


Phase 2: Set Up the New Server

Open a new terminal window and SSH into your new server. From here on, all commands run on the new server.

Step 5: Download the Backup Files from the Old Server

Start from the /root home directory:

pwd

pwd stands for Print Working Directory. It simply shows you your current location. You should see /root. If not, navigate there:

cd /root

Now download both backup files from your old server in a single command:

wget http://OLD_SERVER_IP/wp_content_bck.tar.gz && wget http://OLD_SERVER_IP/sqldump_backup.sql

Replace OLD_SERVER_IP with your old server's actual IP address (e.g., 198.51.100.42).

What's happening here:

  • wget is a command-line download tool. Unlike a browser download, it runs entirely on the server, won't time out, and keeps running even if you disconnect from SSH
  • The && chains two commands together — the second only runs if the first succeeds
  • Since both servers are in data centers, they're connected via high-speed data center links. A 5 GB backup that would take 45 minutes over a home connection might only take 2–3 minutes server-to-server

Watch the progress bars as the files download. When both reach 100%, you're ready for the next step.

Step 6: Install a WordPress Server Stack on the New VPS

We'll use WordOps — an excellent open-source server manager that installs Nginx, PHP, MariaDB, Let's Encrypt SSL, and everything WordPress needs with just a few commands. It's the fastest and most reliable way to set up a production-ready WordPress environment on a fresh VPS.

Install WordOps:

wget -qO wo wops.cc && sudo bash wo

Breaking this down:

  • wget -qO wo wops.cc — quietly (without progress output) downloads the WordOps installer script and saves it as a local file named wo
  • sudo bash wo — executes that installer script with elevated (root) privileges

The installer will set up the LEMP stack (Linux, Nginx, MariaDB, PHP) and takes a few minutes. You'll see installation progress in the terminal.

After it completes, reload your shell to activate tab-completion for wo commands:

bash -l

Now install the full WordPress server stack:

wo stack install

This installs the complete set of components: Nginx web server, PHP-FPM, MariaDB database, Redis (for object caching), and additional tools. You'll see each component being installed. Grab a coffee — this takes 3–5 minutes.

Step 7: Create a Fresh WordPress Site with SSL

With the stack ready, create a new WordPress installation for your domain:

wo site create domain.com --wp --php84 -le --force

What each flag does:

  • wo site create domain.com — tells WordOps to create a new site for your domain
  • --wp — installs a fresh copy of WordPress
  • --php84 — uses PHP 8.4 (the current stable release — best for performance and security)
  • -le — automatically obtains and configures a Let's Encrypt SSL certificate, enabling HTTPS for free
  • --force — proceeds without stopping on non-critical warnings

Important: For Let's Encrypt to work, your domain's DNS A record must already point to this new server's IP address. If you haven't changed DNS yet, omit -le for now and run wo site update domain.com -le later after DNS propagates.

After this command finishes, you have a fully functioning blank WordPress site. You can verify by opening http://domain.com in your browser — you should see a fresh WordPress install.

Step 8: Remove the Default wp-content Folder

The fresh WordPress install created its own default wp-content folder with placeholder themes and plugins. We need to completely remove it and replace it with your actual site's content from the backup.

Navigate to the site's files:

cd /var/www/domain.com/htdocs/

Remove the default wp-content:

rm -r wp-content/

rm -r removes a directory and everything inside it recursively. There's no undo for this command, so use it carefully. In this case it's completely intentional — we're making room for the real wp-content from your backup.

Step 9: Move the Backup Archive and Extract It

Go back to /root where you downloaded the backup files:

cd /root

Move the archive to the site directory:

mv wp_content_bck.tar.gz /var/www/domain.com/htdocs/

Navigate to the site directory:

cd /var/www/domain.com/htdocs/

Extract the archive:

tar -xzvf wp_content_bck.tar.gz

Extraction flags — the mirror image of when we created the archive:

  • -x — extract (the opposite of -c for create)
  • -z — decompress from gzip compression
  • -v — verbose (shows filenames as they're extracted)
  • -f wp_content_bck.tar.gz — the archive file to extract from

You'll see all the filenames scroll past as they're extracted. When the command finishes, you'll have a fully restored wp-content/ folder with all your uploads, plugins, and themes exactly as they were on the old server.

Step 10: Get the New Database Credentials

WordOps created a wp-config.php with freshly generated database credentials when it installed WordPress. We need to import our old database into this new database — which means we need to know those new credentials.

Open the wp-config.php file:

nano ../wp-config.php

.. means "go one directory up" from where we are. Since we're in htdocs/, this opens wp-config.php in the site root. Look for the three lines defining DB_NAME, DB_USER, and DB_PASSWORD.

Copy those three values. Then exit without saving: press Ctrl + X. Nano will ask if you want to save — press N.

Create a temporary scratch file so you have the credentials visible during the import step:

cd /root
nano temp

Paste the credentials you just copied, then save and exit: Ctrl + XYEnter.

Confirm the file was saved correctly:

cat temp

cat displays a file's contents directly in the terminal — a quick sanity check before proceeding.

Step 11: Import the Database

With the credentials confirmed, import your old site's database into the new server's database:

mysql -u DB_USER -p DB_NAME < sqldump_backup.sql

Replace DB_USER and DB_NAME with the values from the temp file you just viewed.

  • mysql — the MySQL command-line client used to run queries and import data
  • -u DB_USER — the database username from the new server's wp-config.php
  • -p — prompts you to enter the database password (also from wp-config.php)
  • DB_NAME — the new server's database name
  • < sqldump_backup.sql — the < feeds your SQL backup file into MySQL as input

MySQL will process the file and rebuild every table, post, page, comment, plugin setting, order, and user from your old database into the new one. For large databases this can take a few minutes — be patient and let it finish.


Phase 3: Finalize and Verify

Step 12: Fix File Permissions

File permissions tell the operating system who can read, write, and execute each file and directory. After migration, permissions can sometimes be off — causing WordPress to show broken images, fail to upload files, or throw permission errors in the admin panel.

Set the correct ownership (so Nginx can read and write your files):

chown -R www-data:www-data /var/www/domain.com/

Set the correct permissions for directories (755 = owner can read/write/execute, others can read/execute):

find /var/www/domain.com/htdocs/ -type d -exec chmod 755 {} \;

Set the correct permissions for files (644 = owner can read/write, others can read only):

find /var/www/domain.com/htdocs/ -type f -exec chmod 644 {} \;

Why these specific values?

  • www-data is the system user that Nginx runs as. Setting ownership to www-data:www-data ensures the web server can access your files
  • 755 on directories lets the web server navigate into them
  • 644 on files lets the web server read them, but prevents execution (a security best practice for web-facing files)

Step 13: Clean Up the Temporary Credentials File

The temp file contains your database credentials in plain text. Delete it now that the import is done:

cd /root
rm -r temp

Step 14: Secure Your Backup Files for Future Reference

Keep your backups archived neatly in case you need to reference them:

cd /root
mkdir backupfiles
mv wp_content_bck.tar.gz backupfiles/
mv sqldump_backup.sql backupfiles/

mkdir creates the backupfiles directory, and mv moves both archive files into it. This keeps your /root directory clean while preserving the backups for a week or two — just in case an issue surfaces that requires re-checking something. Once you're fully confident the migration is solid, delete the entire backupfiles/ folder.

Also remember to delete the backup files from the old server's /var/www/html/ directory:

# Run this on the OLD server
rm /var/www/html/wp_content_bck.tar.gz
rm /var/www/html/sqldump_backup.sql

Step 15: Test Thoroughly Before Pointing DNS

Before announcing the new server to the world, test everything:

  1. Browse your site — check that your homepage, blog posts, and key pages load correctly
  2. Check all images — scroll through a few posts to confirm media files display properly
  3. Log in to wp-admin — verify all your settings, menus, and widgets are intact
  4. Test plugins — activate any plugins that need reactivating after migration
  5. Test forms — submit a test contact form if you have one
  6. Check SSL — confirm the padlock appears in the browser address bar

How to test before changing DNS: Add a temporary entry to your local machine's hosts file. On macOS/Linux, open /etc/hosts in a text editor with sudo:

NEW_SERVER_IP domain.com

This makes your browser route domain.com to the new server's IP — but only on your machine. No one else is affected. Remove this line after you've confirmed everything works and changed DNS officially.


Full Command Reference (Quick Copy-Paste)

Here's everything condensed for quick reference:

On the old server:

# Export the database
mysqldump -u DB_USER -p DB_NAME > sqldump_backup.sql

# Archive wp-content (from your site root)
cd /var/www/domain.com/htdocs/
tar -czvf wp_content_bck.tar.gz wp-content/

# Move both files to the public web directory
mv wp_content_bck.tar.gz /var/www/html/
mv sqldump_backup.sql /var/www/html/

On the new server:

# Download backups directly from the old server (replace OLD_SERVER_IP)
cd /root
wget http://OLD_SERVER_IP/wp_content_bck.tar.gz && wget http://OLD_SERVER_IP/sqldump_backup.sql

# Install WordOps and the WordPress stack
wget -qO wo wops.cc && sudo bash wo
bash -l
wo stack install

# Create WordPress site with PHP 8.4 and SSL
wo site create domain.com --wp --php84 -le --force

# Replace the default wp-content with your backup
cd /var/www/domain.com/htdocs/
rm -r wp-content/
cd /root
mv wp_content_bck.tar.gz /var/www/domain.com/htdocs/
cd /var/www/domain.com/htdocs/
tar -xzvf wp_content_bck.tar.gz

# Get DB credentials from the new wp-config.php
nano ../wp-config.php

# Import the database (use the credentials from wp-config.php)
mysql -u DB_USER -p DB_NAME < /root/sqldump_backup.sql

# Fix file permissions
chown -R www-data:www-data /var/www/domain.com/
find /var/www/domain.com/htdocs/ -type d -exec chmod 755 {} \;
find /var/www/domain.com/htdocs/ -type f -exec chmod 644 {} \;

# Clean up
cd /root
rm -r temp
mkdir backupfiles
mv wp_content_bck.tar.gz backupfiles/
mv sqldump_backup.sql backupfiles/

Common Issues and Fixes

Images not showing after migration: This is almost always a file permissions issue. Re-run the chown and chmod commands from Step 12.

wp-admin login not working: The database import may have brought over the old site URL. Run this in MySQL or phpMyAdmin: UPDATE wp_options SET option_value='https://domain.com' WHERE option_name='siteurl' OR option_name='home';

404 errors on posts and pages: Go to Settings → Permalinks in the WordPress dashboard and click Save Changes — this regenerates the Nginx rewrite rules without changing anything.

SSL certificate failed: Check that your domain's DNS A record is pointing to the new server's IP and that DNS has fully propagated (can take up to 48 hours, usually much less). Then run wo site update domain.com -le.

Database import failed with "Access denied": Double-check that you're using the credentials from the new server's wp-config.php, not the old one. The new server created a different database with different credentials.


Conclusion

Migrating a WordPress site is one of those tasks that sounds intimidating until you've done it once. After that, it becomes routine.

For small sites, the Backup Migration plugin handles everything through a friendly dashboard — no terminal needed. For larger sites, the SSH + wget method is the professional choice: it's faster, more reliable, and scales to any site size because the heavy lifting happens entirely within high-speed data center networks.

The key principle to remember: keep transfers on the server network. By pulling your backup from the old server directly to the new one with wget, you completely bypass your home internet connection as a bottleneck. You get data center speeds, no timeouts, and a clean migration every time.

If you're choosing a new VPS to migrate to, I recommend UpCloud for high-performance workloads, or Contabo if you need great specs at a more affordable price point.

Happy migrating!