Type something to search...
How to Set Up a WordPress Staging Site?

How to Set Up a WordPress Staging Site?

A plugin update that looked routine takes down the checkout page on a Friday afternoon. A theme change that looked fine on the developer's laptop breaks the mobile menu for real visitors. Almost every WordPress disaster story has the same root cause: the change was tested for the first time on the live site. A staging site fixes that. It is a private copy of your production site, with the same theme, plugins, content, and server setup, where you can update, redesign, and experiment without any visitor seeing the result until you are sure it works.

This article covers what a staging site is and how it fits into a safe workflow, the three ways to create one (through your host, with a plugin, or manually with WP-CLI), how to keep staging private and out of search engines, how to stop it from sending emails or processing payments, and how to move changes back to production without overwriting new orders, comments, or form entries.

What Is a Staging Site?

A staging site is a clone of your live WordPress site that runs on a separate URL, such as staging.example.com, and is hidden from the public. It sits between local development and production:

EnvironmentWhere it runsDataPurpose
LocalYour computerSample or copied dataBuilding themes, plugins, and features
StagingSame or similar server as liveRecent copy of productionTesting updates and changes in real conditions
ProductionLive serverReal, changing dataServing visitors and customers

Local environments such as WordPress Playground, wp-env, or Docker are great for writing code, but they are not identical to your host. Staging runs on the same kind of server, with the same PHP version, caching, and configuration, so it catches problems a local copy can miss. For local options, see how to use WordPress Playground to test themes and plugins in the browser and how to run WordPress locally with Docker Compose.

Use staging for:

  • WordPress core, plugin, and theme updates, especially major versions.
  • PHP version upgrades before your host switches them on production.
  • Design changes and new page templates.
  • New plugins, particularly those that change the database or front end.
  • Custom code before it goes live.

Before You Start: Take a Backup

Creating a staging site involves copying databases and files, and the reverse process, pushing to production, can overwrite live data. Take a full backup of production first and confirm you can restore it. If you do not have a reliable backup routine yet, start with how to create a backup for a WordPress website.

Option 1: Use Your Host's Staging Tool

Many managed WordPress hosts include one-click staging. Look for a Staging button or tab in your hosting dashboard, or in the site's tools section. The typical workflow is:

  1. Click Create staging for your site.
  2. Wait while the host copies files and the database to a staging URL.
  3. Log in to the staging site with the same credentials as production.
  4. Make and test your changes.
  5. Use Push to live when you are ready, often with a choice of files only, database only, or both.

Host staging is the easiest option because the host handles the URL, the copy, search engine blocking, and often password protection. Before relying on it, check:

  • Whether the push is selective. Can you push files without the database? Can you choose specific tables?
  • Whether staging is identical to production. Same PHP version, same caching layer, same server type.
  • Whether staging is protected. Some hosts add password protection automatically; others leave it public on a temporary domain.

If your host offers staging, use it. The rest of this article is still useful, because the same rules about privacy, email, and safe pushes apply.

Option 2: Use a Staging Plugin

If your host has no staging tool, a plugin can create a copy inside your existing hosting account. WP Staging is a widely used example. The free version creates a staging copy in a subfolder of your site with a separate set of database tables; pushing changes back to production is a paid feature.

The typical steps:

  1. Install and activate the staging plugin on production.
  2. Open its admin page and create a new staging site.
  3. Choose which tables and folders to include. You can usually exclude large folders such as old backups and caches.
  4. Start the clone and wait for it to finish.
  5. Open the staging site from the link the plugin provides and log in.

Plugin-based staging is convenient, but keep in mind:

  • It shares your server. Heavy testing on staging uses the same CPU and memory as production.
  • It lives inside your site's folder, so security and backup tools may need to be told about it.
  • Restrictions vary by plan, especially for pushing changes back.

Option 3: Create a Staging Site Manually

Doing it yourself gives you full control and works with any host that provides SSH access. These steps assume production lives at https://www.example.com and staging will live at https://staging.example.com on the same server.

Step 1: Create the Subdomain

Create staging.example.com in your hosting control panel and point its document root to a new folder, for example /var/www/staging. If DNS is managed outside your host, add an A or CNAME record for the subdomain; the details are in how to set up subdomains in DNS settings. Then issue an SSL certificate for the subdomain, so staging uses HTTPS just like production.

Step 2: Create a Separate Database

Create a new database and database user for staging in your control panel. Never point staging at the production database. If you can, give the staging user permissions on the staging database only.

Step 3: Copy the Files

Copy the production files to the staging folder over SSH:

# Terminal
rsync -a --delete \
  --exclude 'wp-content/cache/' \
  --exclude 'wp-content/backups/' \
  --exclude 'wp-content/updraft/' \
  /var/www/production/ /var/www/staging/

Excluding caches and backup folders keeps the copy small and avoids duplicating gigabytes of old archives.

Step 4: Export and Import the Database

WP-CLI makes the database copy straightforward:

# Terminal
cd /var/www/production
wp db export /tmp/production.sql --single-transaction

cd /var/www/staging
# Update wp-config.php with the staging database credentials first (Step 5)
wp db import /tmp/production.sql
rm /tmp/production.sql

The --single-transaction option produces a consistent export of InnoDB tables without locking the live site. Delete the SQL file afterwards, because it contains every user's data, including password hashes and email addresses.

Step 5: Update wp-config.php

Edit /var/www/staging/wp-config.php so it uses the staging database and identifies itself as a staging environment:

<?php
// /var/www/staging/wp-config.php (relevant lines)

define( 'DB_NAME', 'example_staging' );
define( 'DB_USER', 'example_staging_user' );
define( 'DB_PASSWORD', 'a-strong-unique-password' );
define( 'DB_HOST', 'localhost' );

define( 'WP_ENVIRONMENT_TYPE', 'staging' );

define( 'WP_HOME', 'https://staging.example.com' );
define( 'WP_SITEURL', 'https://staging.example.com' );

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );

define( 'DISABLE_WP_CRON', true );

Each line has a reason:

  • WP_ENVIRONMENT_TYPE set to staging lets themes and plugins detect the environment through wp_get_environment_type(). Some plugins automatically disable features outside production.
  • WP_HOME and WP_SITEURL force the staging URL, so a mistake in the database cannot redirect you to production.
  • Debug logging writes errors to wp-content/debug.log without showing them to anyone who opens the site.
  • DISABLE_WP_CRON stops scheduled tasks, such as subscription renewals, newsletter sends, and syncs with external services, from running on the copy.

Also generate new authentication keys and salts from the WordPress.org secret key service, so login cookies from production do not work on staging.

Step 6: Replace URLs in the Database

The database still contains https://www.example.com in post content, options, and widget settings. Replace it with WP-CLI, which handles serialized data correctly:

# Terminal
cd /var/www/staging
wp search-replace 'https://www.example.com' 'https://staging.example.com' \
  --all-tables-with-prefix --skip-columns=guid --precise --dry-run

wp search-replace 'https://www.example.com' 'https://staging.example.com' \
  --all-tables-with-prefix --skip-columns=guid --precise

wp cache flush
wp rewrite flush

Run the dry run first and review the counts. --skip-columns=guid leaves post GUIDs alone, which WordPress recommends, because they are identifiers, not links. Never run a text editor find-and-replace on the SQL file: changing string lengths corrupts serialized PHP data and breaks widgets and plugin settings.

Keeping Staging Private

A staging site that anyone can visit is a problem. It can be indexed by search engines as duplicate content, and it exposes unfinished work and sometimes real customer data.

Block Search Engines

Tell WordPress to discourage indexing:

# Terminal
wp option update blog_public 0

This is the same as ticking Search engine visibility under Settings, Reading. It adds a noindex robots directive, but well-behaved crawlers can still request the pages, and links to staging can still surface. Treat it as a second layer, not the main one.

Add Password Protection

The reliable protection is HTTP authentication at the server level, which blocks everyone, including crawlers, before WordPress loads.

On Apache, create a password file outside the web root and protect the site with .htaccess:

# Terminal
htpasswd -c /home/example/.htpasswd-staging stagingteam
# /var/www/staging/.htaccess (add at the top)
AuthType Basic
AuthName "Staging"
AuthUserFile /home/example/.htpasswd-staging
Require valid-user

On Nginx, add the equivalent to the staging server block:

# /etc/nginx/sites-available/staging.example.com
location / {
    auth_basic "Staging";
    auth_basic_user_file /etc/nginx/.htpasswd-staging;
    try_files $uri $uri/ /index.php?$args;
}

Add a server-wide X-Robots-Tag: noindex, nofollow header as well, so any page that slips through is still marked as not indexable. Many control panels also offer a Directory Privacy or Password Protect Directories feature that does the same thing without editing files.

Making Staging Safe to Use

A cloned site behaves like the real one, which includes sending emails and talking to payment providers. Neutralize those before you start testing.

Stop Outgoing Email

You do not want customers to receive order confirmations or password reset emails from staging. Since WordPress 5.7, the pre_wp_mail filter can short-circuit wp_mail(). Add a must-use plugin that only activates on non-production environments:

<?php
// wp-content/mu-plugins/staging-safety.php

/**
 * Plugin Name: Staging Safety
 * Description: Blocks outgoing email and marks the admin bar outside production.
 */

if ( 'production' === wp_get_environment_type() ) {
return;
}

// Block all outgoing email and log it instead.
add_filter( 'pre_wp_mail', function ( $return, $atts ) {
error_log( sprintf(
'[staging] Email blocked. To: %s | Subject: %s',
is_array( $atts['to'] ) ? implode( ', ', $atts['to'] ) : $atts['to'],
$atts['subject']
) );
return true; // Pretend the email was sent.
}, 10, 2 );

// Make it obvious which environment you are in.
add_action( 'admin_bar_menu', function ( $wp_admin_bar ) {
$wp_admin_bar->add_node( array(
'id'    => 'environment-type',
'title' => strtoupper( wp_get_environment_type() ),
) );
}, 1 );

The admin bar label is a small touch that prevents a common mistake: making changes on production while thinking you are on staging, or the reverse.

Disable Payments and Integrations

  • Payment gateways: switch them to test or sandbox mode on staging, or disable them. Never process real payments on a copy.
  • Webhooks and APIs: CRMs, email marketing tools, and inventory systems may receive duplicate data from staging. Disconnect them or point them at sandbox accounts.
  • Analytics: exclude the staging hostname from your analytics property so test visits do not distort reports.
  • Scheduled tasks: keep DISABLE_WP_CRON on unless you are specifically testing cron behavior.

Protect Customer Data

If production holds personal data, such as customers, orders, and form submissions, consider anonymizing it on staging. At a minimum, limit staging access to the people who need it, use strong passwords, and refresh staging rather than letting old copies pile up.

Testing on Staging

With staging ready, follow a consistent routine for each change:

  1. Refresh staging from production so it matches the current state.
  2. Apply the change: update plugins, switch PHP, deploy theme code.
  3. Check the critical paths: home page, key landing pages, forms, search, login, cart, and checkout.
  4. Read the logs: wp-content/debug.log and the server error log.
  5. Test on mobile and in at least two browsers.
  6. Write down what you changed, so you can repeat it exactly on production.

For plugin and theme updates in particular, how to update WordPress plugins and themes covers a safe update order.

Pushing Changes to Production

This is where staging workflows usually go wrong. Production keeps changing while you test: new orders, comments, form entries, user registrations, and posts. If you push the entire staging database to production, all of those are overwritten with older data from when staging was created.

Follow these rules:

  • Files are safe to push. Themes, plugins, and custom code can be deployed from staging to production, ideally through Git or rsync of specific folders.
  • Databases rarely are. Only push the database if the site has no user-generated data, such as a brochure site with a single editor, and nobody has edited production since staging was created.
  • Repeat settings changes on production. For plugin settings, menus, and widgets, the safest approach is to repeat the same steps on production, using the notes you made while testing.
  • Use selective pushes when available. Host tools and paid staging plugins often let you push specific tables, for example only the options table, while leaving orders and users alone.

A typical file deployment over SSH:

# Terminal
# 1. Back up production first
cd /var/www/production
wp db export ~/backups/pre-deploy-$(date +%F-%H%M).sql --single-transaction

# 2. Push only the theme and a specific plugin
rsync -a --delete /var/www/staging/wp-content/themes/my-theme/ /var/www/production/wp-content/themes/my-theme/
rsync -a --delete /var/www/staging/wp-content/plugins/my-plugin/ /var/www/production/wp-content/plugins/my-plugin/

# 3. Clear caches on production
wp cache flush

For plugin updates you tested on staging, it is usually cleaner to run the same update on production with wp plugin update plugin-name than to copy plugin folders.

If you ever need to move a full site, not just changes, to another server, that is a migration rather than a staging push; see how to migrate a WordPress website to a new hosting provider.

Common Problems and Fixes

  • Staging redirects to the live site. The siteurl and home options still contain the production URL. Run wp search-replace again or define WP_HOME and WP_SITEURL in the staging wp-config.php.
  • Images on staging load from production. URLs in post content were not replaced. Re-run the search-replace with --all-tables-with-prefix and confirm the dry run counts.
  • Widgets or plugin settings vanished after the copy. Serialized data was corrupted by a plain text replacement. Re-import the database and use wp search-replace.
  • Customers received emails from staging. Email was not blocked. Add the pre_wp_mail safety plugin before testing, and check scheduled tasks.
  • Staging appears in Google. It was public. Add HTTP authentication, set blog_public to 0, and request removal of the URLs in Google Search Console.
  • New orders disappeared after pushing to live. The full database was pushed. Restore the pre-deploy backup and recover new data from it, then push only files in future.
  • Staging is slow or uses too much disk space. Large backups and caches were copied. Exclude them when copying files.

WordPress Staging Site FAQ

If the site matters to your business, yes. Even small sites break after plugin or PHP updates, and staging lets you find out safely. At minimum, test major updates on a staging copy and keep reliable backups.

Not if it is private. Protect staging with HTTP authentication and discourage indexing. A public, indexable staging copy can be treated as duplicate content and compete with your live pages.

Yes. Many hosts include staging at no extra cost, free staging plugins can create a copy within your hosting account, and the manual method only needs a subdomain, a database, and SSH access.

Refresh it from production before each round of testing, so you test against current content, plugins, and settings. An old staging copy can hide problems that only appear with recent data.

Only when production has no new data since staging was created. On sites with orders, comments, form entries, or user signups, pushing the full database overwrites that data. Push files and repeat settings changes instead.

It tells WordPress whether the site is local, development, staging, or production. Themes and plugins can read it with wp_get_environment_type to disable emails, payments, analytics, or indexing outside production.

Conclusion

A staging site turns risky changes into routine ones. Whether you use your host's one-click tool, a staging plugin, or a manual copy with WP-CLI, the goal is the same: a private, current copy of production on the same kind of server, where updates, redesigns, and new code can fail without anyone noticing.

Set it up carefully once, with HTTP authentication, noindex, WP_ENVIRONMENT_TYPE set to staging, cron disabled, email blocked, and payments in test mode, and it becomes a safe place to work. Then respect the one rule that prevents most staging disasters: push files and code to production, but be very careful about pushing the database over live data.

Here are some useful references for going deeper on WordPress staging:

  1. WP-CLI: wp search-replace — options for safe URL replacement, including serialized data.
  2. WP-CLI: wp db export — exporting databases from the command line.
  3. WordPress Developer Resources: wp_get_environment_type() — environment types and how to set them.
  4. WordPress Developer Resources: pre_wp_mail filter — short-circuiting outgoing email.
  5. WordPress.org Plugins: WP Staging — a plugin for creating staging copies within your hosting account.
Tags :
Share :

Related Posts

WordPress optimization with specific recommended approach

WordPress optimization with specific recommended approach

Whether you run a high traffic WordPress installation or a small blog on a low cost shared host, you should optimize WordPress and your server to run

Continue Reading
Creating and Customizing WordPress Child Themes

Creating and Customizing WordPress Child Themes

Creating a child theme in WordPress is a best practice for making modifications to a theme. By using a child theme, you can update the parent theme w

Continue Reading
Understanding the Distinction Categories vs. Tags in WordPress

Understanding the Distinction Categories vs. Tags in WordPress

WordPress, a powerful content management system, offers a plethora of features to organize content effectively. Among these features, categories and

Continue Reading