How to Set Up WordPress Staging on Hostperl VPS

WordPress staging on a VPS: the safe way to test changes
WordPress staging gives you a private copy of your live site so you can test plugin updates, theme edits, WooCommerce changes, and fixes before visitors see them. On a Hostperl VPS, that usually means one extra subdomain, one separate document root, and a database copied from production. If you already host on a Hostperl VPS, this setup keeps release work under control and makes rollback far easier.
This guide follows a fresh-server setup: you will SSH in, confirm the operating system, create a non-root admin, install the required packages, point a staging subdomain at the VPS, secure it with HTTPS, clone WordPress, and verify that the staging site works without touching live traffic.
For broader launch planning, Hostperl customers often pair staging with WordPress staging for safer launches in 2026 and technical SEO checks for AI Overviews before a redesign or content refresh.
Connect to the VPS and confirm the operating system
On your local computer, open your first SSH session to the server.
ssh root@203.0.113.10Replace 203.0.113.10 with the real public IP assigned to your Hostperl server. If your provider gives you a non-root login first, use that same IP and the account name they issued.
On the VPS as root, detect the distribution before you install anything.
cat /etc/os-releaseYou should see either Ubuntu/Debian or AlmaLinux/Rocky Linux. The package and firewall commands below are separated so you do not mix them.
Create a non-root sudo user for staging work
Keep the root session open until the new login works. That way you do not lock yourself out halfway through setup.
Ubuntu and Debian
adduser deployThis creates the deploy account. Set a strong password when prompted.
usermod -aG sudo deployThis grants sudo access through the sudo group.
install -d -m 700 /home/deploy/.sshcp /root/.ssh/authorized_keys /home/deploy/.ssh/authorized_keyschown -R deploy:deploy /home/deploy/.sshchmod 600 /home/deploy/.ssh/authorized_keysOn the VPS as root, confirm the account is ready.
id deployThen open a second terminal on your local computer and test the new login.
ssh deploy@203.0.113.10Once connected, verify sudo access.
sudo -vYou should be asked for the deploy password only if your key does not cover sudo. Keep the root session open until this succeeds.
AlmaLinux and Rocky Linux
useradd -m deploypasswd deployThis creates the account and sets its password.
usermod -aG wheel deployRocky and AlmaLinux use the wheel group for sudo access.
install -d -m 700 /home/deploy/.sshcp /root/.ssh/authorized_keys /home/deploy/.ssh/authorized_keyschown -R deploy:deploy /home/deploy/.sshchmod 600 /home/deploy/.ssh/authorized_keysVerify the account.
id deployThen test a second SSH login from your local computer.
ssh deploy@203.0.113.10sudo -vUpdate the server and install the web stack
WordPress staging only helps if the server underneath it is current. Start with package updates, then install the web server, PHP, database, and tools you need for cloning the live site.
Ubuntu and Debian
On the VPS as the non-root sudo user, update the system and install packages.
sudo apt updatesudo apt -y upgradesudo apt -y install nginx mariadb-server php-fpm php-mysql php-curl php-gd php-mbstring php-xml php-zip unzip rsync curl certbot python3-certbot-nginxCheck versions so you know what is running.
nginx -vphp -vmysql --versionAlmaLinux and Rocky Linux
On the VPS as the non-root sudo user, update the system and install packages.
sudo dnf -y updatesudo dnf -y install nginx mariadb-server php-fpm php-mysqlnd php-curl php-gd php-mbstring php-xml php-zip unzip rsync curl certbot python3-certbot-nginxConfirm the installed versions.
nginx -vphp -vmysql --versionPrepare DNS and firewall rules for the staging subdomain
Use a dedicated hostname such as staging.example.com. Point its A record to the VPS public IP in your DNS panel. If you also manage nameservers and email authentication on the same domain, keep staging separate from mail records so testing does not affect delivery.
If you want a deeper planning checklist for launch work, Hostperl also covers panel migrations without downtime and panel selection for 2026, which helps agencies avoid awkward cutover windows.
Ubuntu and Debian with UFW
sudo ufw allow OpenSSHsudo ufw allow 'Nginx Full'sudo ufw enablesudo ufw status verboseOpenSSH and HTTP/HTTPS should be allowed before you turn UFW on.
AlmaLinux and Rocky Linux with firewalld
sudo systemctl enable --now firewalldsudo firewall-cmd --permanent --add-service=sshsudo firewall-cmd --permanent --add-service=httpsudo firewall-cmd --permanent --add-service=httpssudo firewall-cmd --reloadsudo firewall-cmd --list-allOn SELinux-enabled systems, keep the default policy in place and use the standard web root and ports described here.
Set up MariaDB and create the staging database
Use a separate database for staging. That keeps test imports away from the production site and gives you a clean reset point.
For database hardening and restore planning, see Hostperl’s PostgreSQL hardening guide and backup and restore runbooks. The same discipline applies to MySQL and MariaDB.
sudo systemctl enable --now mariadbsudo mysql_secure_installationFollow the prompts to set a root password, remove anonymous users, disable remote root login, and remove the test database.
sudo mysqlThen create the staging database and user.
CREATE DATABASE wordpress_staging CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wpstaging'@'localhost' IDENTIFIED BY 'use-a-long-random-password';
GRANT ALL PRIVILEGES ON wordpress_staging.* TO 'wpstaging'@'localhost';
FLUSH PRIVILEGES;
EXIT;Replace the sample password with a real secret. You will store it in WordPress later, so keep it private.
Build the staging directory and download WordPress
Create a separate document root for staging. A clean layout makes it easy to tell production from testing.
sudo mkdir -p /var/www/staging.example.com/publicsudo chown -R deploy:deploy /var/www/staging.example.comNow download WordPress into that directory.
cd /tmpcurl -LO https://wordpress.org/latest.tar.gztar -xzf latest.tar.gzrsync -a wordpress/ /var/www/staging.example.com/public/The files should now live under /var/www/staging.example.com/public.
Copy the production site and database into staging
Make a current backup first. If a restore fails, you want a fallback copy before you try again.
These steps are the part most customers care about before a launch. If your production site already has large media libraries, a staging clone prevents the “it worked on my laptop” problem and lets you verify plugin conflicts privately.
sudo mysqldump -u root -p live_wordpress > /tmp/live_wordpress.sqlReplace live_wordpress with your production database name. If your live site runs elsewhere, export it from that system using your normal backup method.
sudo mysql wordpress_staging < /tmp/live_wordpress.sqlNext, copy the production wp-content directory so themes, plugins, and uploads match live.
sudo rsync -a /var/www/example.com/public/wp-content/ /var/www/staging.example.com/public/wp-content/Replace the source path with your real production document root.
Configure WordPress for the staging hostname
Create the WordPress configuration file from the sample and point it at the staging database.
cd /var/www/staging.example.com/publiccp wp-config-sample.php wp-config.phpnano wp-config.phpPaste the following database settings into the file, then save and exit with Ctrl+O, Enter, and Ctrl+X.
define( 'DB_NAME', 'wordpress_staging' );
define( 'DB_USER', 'wpstaging' );
define( 'DB_PASSWORD', 'use-a-long-random-password' );
define( 'DB_HOST', 'localhost' );Set ownership so the web server can read the files but cannot casually rewrite everything.
sudo chown -R deploy:www-data /var/www/staging.example.com/publicsudo find /var/www/staging.example.com/public -type d -exec chmod 755 {} \;sudo find /var/www/staging.example.com/public -type f -exec chmod 644 {} \;Configure Nginx for staging and test syntax before reload
Use a dedicated Nginx server block. This keeps staging isolated from production and makes certificate issuance straightforward.
sudo nano /etc/nginx/sites-available/staging.example.comPaste this full server block, replacing only the domain name if you use a different staging hostname.
server {
listen 80;
server_name staging.example.com;
root /var/www/staging.example.com/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 30d;
access_log off;
}
}Enable the site and test Nginx syntax before reload.
Ubuntu and Debian
sudo ln -s /etc/nginx/sites-available/staging.example.com /etc/nginx/sites-enabled/sudo nginx -tsudo systemctl reload nginxAlmaLinux and Rocky Linux
On RHEL-compatible systems, use /etc/nginx/conf.d/ instead of sites-available.
sudo tee /etc/nginx/conf.d/staging.example.com.conf >/dev/null <<'EOF'
server {
listen 80;
server_name staging.example.com;
root /var/www/staging.example.com/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
EOFsudo nginx -tsudo systemctl reload nginxIf syntax fails, the error message usually points to the file and line number. Fix that before you reload again.
Issue Let’s Encrypt for the staging domain
Once DNS points to the VPS and port 80 is open, request a certificate. That keeps browser warnings out of the way while you test.
sudo certbot --nginx -d staging.example.comEnter the email address you want for renewal notices. Certbot should update the Nginx block and reload it automatically.
Check the renewal timer.
sudo systemctl status certbot.timerFinish WordPress setup in the browser
Visit https://staging.example.com from your browser. If the DNS record is correct and the certificate is live, you should see the WordPress installer or your cloned site.
Log in to the staging dashboard, then change these values before you start testing:
- Site title and timezone
- Plugin update status
- WooCommerce checkout settings if you run a store
- Search engine visibility, which should stay disabled on staging
If you need to adjust URLs inside the cloned database, use the safer search-and-replace workflow described in WordPress Search and Replace on a Live Site in 2026. That matters when the production domain and staging subdomain both appear in content, widgets, or serialized data.
Verify the staging site from server and client
On the VPS as the non-root sudo user, confirm services are active and listening.
sudo systemctl status nginx mariadb php8.3-fpmAdjust the PHP-FPM service name if your distribution ships a different version.
sudo ss -tulpn | grep -E ':80|:443|:3306'You should see Nginx on 80 and 443, and MariaDB on 3306 only if it is listening locally.
On your local computer, run an HTTP check.
curl -I https://staging.example.comExpect a 200, 301, or 302 response depending on your WordPress and redirect settings.
Do one functional smoke test next: log in, open a test post, upload a small image, and confirm the Media Library shows it. If this is WooCommerce, place a test order with a sandbox gateway and verify the order appears in the dashboard.
Common staging problems and how to fix them
- DNS has not propagated: run
dig +short staging.example.comfrom your local computer. If it does not return the VPS IP, update the A record and wait for propagation. - Nginx fails to reload: run
sudo nginx -ton the VPS. The output shows the exact config line to correct. - PHP pages download instead of render: check the PHP-FPM socket path in the Nginx block with
ls /run/php/orls /run/php-fpm/. - WordPress cannot connect to the database: confirm credentials in
wp-config.phpand test login withsudo mysql -u wpstaging -p wordpress_staging. - Certificate issuance fails: verify port 80 is open and the hostname resolves to the VPS before rerunning Certbot.
If you want staging that is ready for client sign-off, Hostperl VPS hosting gives you the control you need without oversizing on day one. For teams that run WordPress or WooCommerce migrations often, pairing a Hostperl VPS with a clear launch process reduces rollback risk and saves support time.
When the site is ready, move the production DNS record, keep the staging copy for regression testing, and verify the live cache after cutover.
FAQ
Should staging use the same domain as production?
No. Use a subdomain such as staging.example.com so cookies, cache, and search indexing stay separate.
Can I clone WooCommerce orders into staging?
You can copy the database, but do not process real payments there. Use sandbox payment settings and test accounts only.
How often should I refresh staging?
Refresh it before major plugin updates, theme changes, store launches, and content edits that affect templates or checkout flows.
Should staging be public?
Usually no. Add HTTP basic auth or IP restriction if the site contains client data or unpublished content.
What should I check before pushing staging live?
Test the homepage, critical forms, checkout, login, image uploads, mobile layout, and cache headers. Then confirm backups are current.
