Skip to main content

Migrating WordPress to a VDS: A Step-by-Step Guide

WordPress · 29.01.2025 · 4 min read
Illustration for “Migrating WordPress to a VDS: A Step-by-Step Guide”

Preparation

Before migrating: make a full backup (database + files), note the PHP/MySQL versions on the old server, and install matching ones on the new one.

💡 It's better to migrate at night — minimal traffic, lower risk of losing database transactions.

Step 1: Export the Database

# On the old server
mysqldump -u wpuser -p wppassword wordpress_db > /tmp/wp_export.sql
# Transfer to the new server
scp /tmp/wp_export.sql root@NEW_SERVER_IP:/tmp/

Step 2: Transfer Files via rsync

rsync -avz --progress   /var/www/wordpress/   root@NEW_SERVER_IP:/var/www/wordpress/

Step 3: Create the Database and Import

# On the new server
mysql -u root -p -e "CREATE DATABASE wordpress_db CHARACTER SET utf8mb4;"
mysql -u root -p -e "CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'strong_password';"
mysql -u root -p -e "GRANT ALL ON wordpress_db.* TO 'wpuser'@'localhost';"
mysql -u root -p wordpress_db < /tmp/wp_export.sql

Step 4: Configure wp-config.php

define('DB_HOST', 'localhost');
define('DB_NAME', 'wordpress_db');
define('DB_USER', 'wpuser');
define('DB_PASSWORD', 'strong_password');

Step 5: Configure Nginx

server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/wordpress;
    index index.php;

    location / { try_files $uri $uri/ /index.php?$args; }
    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}
⚠️ Don't switch DNS until you've fully tested the site on the new IP. Use /etc/hosts for local testing.

Common Migration Errors

ErrorCauseFix
Error establishing a database connectionwp-config.php on the new server still has the old DB_HOST, DB_USER, or DB_PASSWORDCheck all four DB_* constants against the real credentials of the new database
mysqldump: Got error: 1045: Access denied for userThe database user was not created on the new server, or the password is wrongRecreate the user with CREATE USER and re-issue GRANT
413 Request Entity Too Large when importing via phpMyAdminThe SQL dump size exceeds upload_max_filesize or client_max_body_sizeImport from the console instead: mysql -u root -p wordpress_db < wp_export.sql
This site can't provide a secure connection after switching DNSNo SSL certificate has been issued yet for the domain on the new serverIssue a Let's Encrypt certificate (certbot) before switching DNS or right after
404 Not Found on every page except the homepagetry_files isn't configured in Nginx on the new server, or the permalink rules weren't reloadedCheck the Nginx config and refresh permalinks: Settings → Permalinks → Save Changes

Comparing Migration Methods

MethodControl over the processSize limitBest for
mysqldump + rsync (this method)FullNoneLarge sites and non-standard server setups
Duplicator / All-in-One WP MigrationMediumUp to 500 MB–2 GB on the free versionSmall sites, migration without SSH access
Hosting panel migration toolLowDepends on the panelMoving between plans of the same provider

When This Method Is Not a Good Fit

  • The old server has no SSH access (typical shared hosting) — use a panel export or a migration plugin instead
  • The site is part of a WordPress Multisite network with shared tables across dozens of subdomains — migration needs a separate domain-mapping procedure
  • The old IP runs a mail server or other services tied to that specific address — migrate those separately and in advance
  • The business needs zero downtime — that calls for a blue-green setup with a load balancer, not a direct DNS switch

A detailed comparison of file-transfer tools is in "Transferring Website Files: rsync, SCP, and FTP", and mysqldump flags are covered in "mysqldump: MySQL Database Backup and Restore Guide".

Verifying the Result

After migrating, confirm the site works correctly on the new server:

# WordPress core file integrity
wp core verify-checksums

# The table count in the new database should match the old one
mysql -u wpuser -p -e "SHOW TABLES FROM wordpress_db;" | wc -l

# The homepage returns 200
curl -s -o /dev/null -w "%{http_code}\n" -H "Host: example.com" http://NEW_SERVER_IP/

# Check permalinks for 404s
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/2026/01/test-post/

If the site was set up from scratch, it's worth checking against "Install WordPress on a VPS Without Hosting: Full Setup" for the baseline PHP and Nginx environment requirements.

A manual migration gives full control over every step, but it demands care: don't rush the verification stage before switching DNS, or any mistakes will have to be fixed under live traffic instead.

Was this article helpful?
← Back to Knowledge Base Ask Support