WordPress staging that pushes back: a real second site
What a WordPress staging copy needs to be worth trusting: its own database and certificate, two ways out of search results, and a push that backs up first.
Why most staging is not trusted
People stop using staging for two reasons. Either the copy is not really separate, so testing on it is not safe. Or there is no dependable way to get the tested work back to the live site, so everything is done twice and the second time is by hand, on production.
A staging setup worth having answers four questions. Is it a separate site? Can search engines find it? What happens to it when live changes? And how does the work get back?
A second site, not a second directory
A copy in a subdirectory shares the live site's PHP settings and often its database server credentials. A copy that shares the live database is not a copy at all.
In KLYRN a staging copy is a real second site: its own nginx vhost, its own PHP-FPM pool, its own database and its own Let's Encrypt certificate.
klyrn site staging create example.com
klyrn site staging create example.com --domain test.example.com
klyrn site staging show example.com
The default name is staging.example.com. The copy lives in the same hosting account as the live site, with the same Unix user and the same disk allowance. That is deliberate: putting it anywhere else would make staging a way to move data between tenants.
KLYRN refuses to make one when the site is not WordPress, is suspended, is itself a staging copy, or already has one.
Kept out of search results, twice
A staging copy in a search index is duplicate content at best and a leak of unpublished work at worst. WordPress has a setting for this, blog_public, and KLYRN sets it to 0 on the copy. Any plugin can undo that, so it is not the only measure.
The staging vhost also always sends X-Robots-Tag: noindex, nofollow, noarchive. Nothing inside WordPress can remove a header that nginx adds.
Refreshing from live
klyrn site staging refresh example.com
A refresh takes live again and discards everything done on the copy. It reuses the staging database, rewrites the addresses back to the staging name and applies the noindex setting again.
wp-config.php is not copied after the first time, in either direction. That file names the database user and password, and it carries the site's authentication salts. Copying it across would sign out every logged-in user and could leave a site pointing at a database it cannot open.
Pushing back to live
klyrn site staging push example.com --confirm example.com
klyrn site staging push example.com --confirm example.com --files-only
klyrn site staging push example.com --confirm example.com --data-only
You have to type the live domain. Pushing overwrites a production website, and a confirmation you can click through is not a confirmation.
The push then runs in a fixed order:
- Back live up with the real backup engine. If the backup fails, nothing is changed and the job stops there.
- Push the files with rsync, leaving out
wp-config.php, the caches and.git. - Push the database, streamed from one database into the other, so the server never needs twice the site's size in free space.
- Restore live's identity. Addresses are rewritten from the staging name back to the live name through WP-CLI, so serialised PHP survives, and indexing is switched back on. Live must not inherit staging's noindex.
Files only, data only, or both
The choice matters on any site that takes writes. A full push replaces the live database with staging's, so orders, comments and sign-ups made on live since the copy was taken are gone from the site. They are in the backup the push took, and getting them out is manual work.
For a shop or a busy blog, --files-only is usually the right push: a theme change or a plugin update is files. Use a full push for a site whose content only changes when you change it.
When the work is done, the copy is deleted like any other site:
klyrn site delete staging.example.com --remove-files