IPv4 & IPv6 Leasing - Any RIR, Any LocationOrder Now
Hostperl

WordPress Staging to Production Migration in 2026

By Raman Kumar

Share:

Updated on Aug 3, 2026

WordPress Staging to Production Migration in 2026

Move the site only after the checks pass

A WordPress staging migration is the safest way to launch changes without exposing them to customers too early. You build and test on staging, then move the finished site to production with backups, database checks, DNS updates, and a quick smoke test. If your site runs on a Hostperl VPS, this gives you a clean launch path instead of a rushed late-night swap.

This guide assumes two environments: STAGING_DOMAIN, such as staging.example.com, and PROD_DOMAIN, such as example.com. It also assumes SSH_HOST is your VPS IP, APP_USER is your non-root admin account, and WEB_ROOT is the WordPress document root, for example /var/www/example.com/public_html.

Connect to the server and identify the OS

On your local computer, start by opening an SSH session. Keep the root session open until your non-root admin login works.

ssh root@203.0.113.10

Replace 203.0.113.10 with your VPS IP. If your provider already gave you a default admin account, use that instead, for example ssh admin@203.0.113.10.

On the VPS as root, detect the operating system before you install or edit anything.

cat /etc/os-release

You should see either Ubuntu/Debian or AlmaLinux/Rocky Linux. The next steps are split by distribution so you do not mix package managers or firewall tools.

Prepare a non-root admin account

If you already have a working sudo user, skip ahead. Otherwise, create one now and verify it before you touch root access.

Ubuntu and Debian on the VPS as root:

adduser APP_USER
usermod -aG sudo APP_USER
mkdir -p /home/APP_USER/.ssh
chmod 700 /home/APP_USER/.ssh
cp /root/.ssh/authorized_keys /home/APP_USER/.ssh/authorized_keys
chown -R APP_USER:APP_USER /home/APP_USER/.ssh
chmod 600 /home/APP_USER/.ssh/authorized_keys

AlmaLinux and Rocky Linux on the VPS as root:

useradd -m APP_USER
passwd APP_USER
usermod -aG wheel APP_USER
mkdir -p /home/APP_USER/.ssh
chmod 700 /home/APP_USER/.ssh
cp /root/.ssh/authorized_keys /home/APP_USER/.ssh/authorized_keys
chown -R APP_USER:APP_USER /home/APP_USER/.ssh
chmod 600 /home/APP_USER/.ssh/authorized_keys

Replace APP_USER with your chosen username, such as hostperladmin. Open a second terminal on your computer and test the new login before closing root.

ssh APP_USER@203.0.113.10
sudo -v
pwd

If that works, the account can log in and run elevated commands. Keep the original root session open until you confirm it.

Update packages and install the tools you need

Run updates first. That lowers the chance of running into an old PHP extension or security bug during the migration.

Ubuntu and Debian on the VPS as APP_USER:

sudo apt update
sudo apt -y upgrade
sudo apt -y install rsync unzip curl mariadb-client php-cli php-mysql php-zip php-curl php-mbstring php-xml php-gd php-intl

AlmaLinux and Rocky Linux on the VPS as APP_USER:

sudo dnf -y update
sudo dnf -y install rsync unzip curl mariadb php-cli php-mysqlnd php-zip php-curl php-mbstring php-xml php-gd php-intl

If you run a managed stack on a Hostperl VPS, this is usually the point where customers ask support to confirm PHP versions, database connectivity, and file ownership before launch. That is often faster than troubleshooting after the domain has already switched.

Back up production before you copy staging

Never overwrite a live WordPress site without a backup you can restore immediately. Take a file backup and a database dump from production first.

On the VPS as APP_USER, create a backup directory and export the database. Replace PROD_DB_NAME, PROD_DB_USER, and PROD_DB_PASS with your production database values.

mkdir -p ~/wp-migration-backups/$(date +%F)
mysqldump -u PROD_DB_USER -p'PROD_DB_PASS' PROD_DB_NAME | gzip > ~/wp-migration-backups/$(date +%F)/production-db.sql.gz
rsync -a --delete WEB_ROOT/ ~/wp-migration-backups/$(date +%F)/files/

Check that both archives exist and are not empty.

ls -lh ~/wp-migration-backups/$(date +%F)/
gzip -t ~/wp-migration-backups/$(date +%F)/production-db.sql.gz

You should see a valid file size and no gzip errors. If the database dump fails, fix the credentials before you move on.

Sync staging into production carefully

This is the core of the WordPress staging migration. Put the live site in maintenance mode first if traffic matters, then copy the final files from staging to production.

On the VPS as APP_USER, replace the placeholders with your real paths. Do not delete production files until you have verified the staging copy is complete.

cd /path/to/staging-site
rsync -a --delete --exclude='wp-config.php' ./ WEB_ROOT/

If your staging site uses a different database, export that database and import it into production.

mysqldump -u STAGING_DB_USER -p'STAGING_DB_PASS' STAGING_DB_NAME | gzip > ~/staging-db.sql.gz
gunzip -c ~/staging-db.sql.gz | mysql -u PROD_DB_USER -p'PROD_DB_PASS' PROD_DB_NAME

Then update the production configuration file so WordPress points to the production database. Open the file with your editor.

nano WEB_ROOT/wp-config.php

Make sure these values match production:

define('DB_NAME', 'PROD_DB_NAME');
define('DB_USER', 'PROD_DB_USER');
define('DB_PASSWORD', 'PROD_DB_PASS');
define('DB_HOST', '127.0.0.1');

Save and exit with Ctrl+O, Enter, then Ctrl+X. If your database lives on another host, change DB_HOST accordingly.

Fix URLs, permalinks, and cached assets

Staging often keeps old URLs in the database. Replace them before you bring the site live, or users will hit broken links and mixed content.

On the VPS as APP_USER, use WP-CLI if it is installed. This is safer than editing serialized data by hand.

cd WEB_ROOT
wp search-replace 'https://staging.example.com' 'https://example.com' --skip-columns=guid --all-tables
wp rewrite flush --hard

Now remove stale cache files. If you use a caching plugin, clear that too from the WordPress dashboard after the move.

rm -rf WEB_ROOT/wp-content/cache/*

For hosts that serve multiple customer sites, this step matters because stale object cache or full-page cache often makes a migration look broken even when the files are right. Hostperl teams often see this during staged WooCommerce launches and agency handovers.

Set the correct ownership and permissions

WordPress should not be writable by everyone. Set the site to the web server user or your deployment user, depending on your stack.

Ubuntu and Debian on the VPS as APP_USER:

sudo chown -R www-data:www-data WEB_ROOT
sudo find WEB_ROOT -type d -exec chmod 755 {} \;
sudo find WEB_ROOT -type f -exec chmod 644 {} \;

AlmaLinux and Rocky Linux on the VPS as APP_USER:

sudo chown -R apache:apache WEB_ROOT
sudo find WEB_ROOT -type d -exec chmod 755 {} \;
sudo find WEB_ROOT -type f -exec chmod 644 {} \;

These permissions are standard for WordPress hosting. If you use PHP-FPM with a separate site user, keep that ownership model consistent instead of mixing it with one-off changes.

Enable SSL and confirm the virtual host

Before DNS points fully to production, make sure your web server block already matches the live domain. The exact config depends on Nginx or Apache, but the certificate workflow is the same: create the DNS record, issue the certificate, then test it.

If you need a clean walkthrough for the launch side, Hostperl’s WordPress VPS setup guide and the SSH, UFW, and Fail2Ban guide cover the earlier server hardening steps that usually come before a migration.

Use Certbot if the certificate is not already in place.

Ubuntu and Debian on the VPS as APP_USER:

sudo apt -y install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com

AlmaLinux and Rocky Linux on the VPS as APP_USER:

sudo dnf -y install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com

When Certbot finishes, it should report automatic renewal is enabled. Test the renewal path.

sudo certbot renew --dry-run

Check the site from the server and from your browser

Do not call it done until you test both the server and the public URL. Start with local service checks.

systemctl status nginx --no-pager
systemctl status php8.2-fpm --no-pager
systemctl status mariadb --no-pager

Service names can differ slightly by version. If your PHP service uses another version, run systemctl list-units --type=service | grep php and use the name you actually have.

Then check the site from the VPS itself.

curl -I https://example.com
curl -s https://example.com | head

You want a 200 or 301 response and HTML content from the production domain. Finally, test in a browser: open the homepage, log in to WordPress admin, save permalinks, and place a test WooCommerce order if the site sells products.

Use a support-friendly rollback path

If something fails, rollback should be a file copy and database restore, not guesswork. Keep the production backup you created earlier, then reverse the file sync and database import.

gunzip -c ~/wp-migration-backups/DATE/production-db.sql.gz | mysql -u PROD_DB_USER -p'PROD_DB_PASS' PROD_DB_NAME
rsync -a --delete ~/wp-migration-backups/DATE/files/ WEB_ROOT/

Replace DATE with the backup folder name you created. After restore, rerun the same curl and login tests.

Troubleshoot the most common migration failures

1. WordPress shows a database connection error. Check the credentials and the database service.

grep -n "DB_" WEB_ROOT/wp-config.php
systemctl status mariadb --no-pager
mysql -u PROD_DB_USER -p'PROD_DB_PASS' -e 'SHOW DATABASES;'

If login fails, correct the password or host in wp-config.php.

2. The site loads on HTTP but not HTTPS. Check the certificate and the web server config.

sudo certbot certificates
sudo nginx -t
sudo systemctl reload nginx

If Nginx syntax fails, fix the reported config file before reloading.

3. Images and CSS return 404 after launch. Look for bad URLs or wrong file ownership.

wp search-replace 'http://staging.example.com' 'https://example.com' --skip-columns=guid --all-tables
ls -ld WEB_ROOT/wp-content WEB_ROOT/wp-content/uploads

4. Admin login loops or permission errors appear. Clear cookies, then confirm the site URL settings.

wp option get home
wp option get siteurl

They should both return the production domain.

If you are moving a live WordPress or WooCommerce site, Hostperl can help you size the VPS, stage the cutover, and keep the launch window short. A well-planned Hostperl VPS gives you the control you need, while our shared hosting plans suit smaller WordPress sites that do not need a full server.

For agencies and site owners who want fewer surprises on launch day, that usually means better rollback options, faster support handoff, and less downtime during the move.

FAQ

Should I migrate WordPress during low traffic hours?

Yes. Use your quietest traffic window so cache refreshes, redirects, and DNS propagation affect fewer visitors.

Do I need to change DNS if only moving staging to production on the same server?

Not always. If the production domain already points to the right server, you may only need the database, files, and SSL checks.

What is the safest way to test before launch?

Use a staging subdomain, a fresh backup, and a browser smoke test for the homepage, admin login, contact form, and checkout flow.

Can I use this process for WooCommerce?

Yes, but add a checkout test and confirm payment gateway callbacks, shipping rules, and order emails after the cutover.

What should I check first if the site breaks after migration?

Start with wp-config.php, database service status, SSL certificate status, and the web server error log. Those four checks catch most launch issues.