Guide PHP & Development

How to set up a staging environment

A subdomain, its own database, and a safe way to copy data across — what a staging environment needs before you can trust it.

Updated 8 min read Intermediate

A staging environment is a working copy of a site — same code, same data, same server environment as far as possible — that nobody but you actually depends on. Its entire purpose is to be the place a change breaks something, rather than the live site. Anything with a genuine cost of failure — a PHP upgrade, a major plugin update, a schema change — belongs on staging first, tested there, and only then applied to the site that matters.

Step 1: create a subdomain

The most common structure is a subdomain such as staging.yourdomain.com, created through your control panel and pointed at its own folder, separate from the live site's folder entirely. This keeps the two completely independent — a change to staging's files cannot accidentally touch the live folder, because they are not the same folder.

Step 2: copy the files across

rsync is a natural fit here, since it only transfers what has changed on subsequent syncs rather than the whole site every time:

rsync -avz -e ssh youraccount@yourserver.example.com:~/public_html/ ~/staging.yourdomain.com/

Note the direction — this pulls a copy of the live site into the staging folder, which is the direction you want when setting staging up or refreshing it later to match what is actually live.

Step 3: give staging its own database

Staging must never share a database with the live site. If it did, testing a data-modifying change on staging would modify live data at the same time, which defeats the entire purpose of having a separate environment in the first place. Create a new database through your control panel, then export the live database and import it into the new one:

mysqldump -u liveuser -p livedatabase > live-export.sql
mysql -u staginguser -p stagingdatabase < live-export.sql

Step 4: point the copied site at the new database

Edit the staging copy's configuration file — wp-config.php for WordPress, .env for Laravel, or whatever your application's equivalent is — so the database name, username and password point at the staging database rather than the live one. This is the single most important step in the whole process, and the one worth double-checking directly rather than assuming the copy carried it over correctly.

Confirm which database you are pointed at before testing anything destructive

Before running a migration, a bulk update, or anything else you specifically built staging to test safely, verify the site is actually reading from the staging database — a quick check of a config value, or looking for a row you know only exists in one of the two databases, is enough. A staging environment quietly still pointed at the live database provides none of the protection it was set up for.

Step 5: keep it private

A staging site is not meant to be found, indexed, or used by anyone but you and your team. Two layers, used together, cover this properly:

  • Block search engines with a noindex meta tag or a rule in robots.txt scoped to the staging subdomain specifically, not the live site's own file.
  • Password-protect the whole folder at the server level, using HTTP basic authentication through your control panel or an .htaccess rule — see using .htaccess for the syntax. This is the layer that actually stops an uninvited visitor from reaching the content at all, rather than just asking search engines politely not to list it.

Keeping staging useful over time

A staging environment that has drifted far from what is actually live tells you less than one refreshed recently — a test that passes against six-month-old data does not guarantee the same result against what the live site holds today. Refresh the files and database periodically, particularly before testing anything significant such as a PHP version upgrade, so what you are testing against is close enough to reality to be trusted.

What staging is for, and what it is not

Staging is for catching a breaking change before it reaches visitors — a plugin update, a code change, a configuration edit, a version upgrade. It is not a substitute for a backup, and it is not the same thing as a full disaster-recovery copy kept somewhere separate from the live server; those solve a different problem entirely. Use staging to test changes deliberately, and keep proper backups for the case where something goes wrong despite the testing.

Once the environment exists, it becomes the natural home for testing far more than just the occasional big upgrade — a new plugin, an edited template, a database search-and-replace — anything you would rather get wrong on a copy nobody else sees than on the site your visitors are using right now.

Related reading