Creating Staging Environments
WPHammer creates staging environments as subdirectories within the same Forge site. This means staging shares the server and domain with production — accessible at https://yourdomain.com/staging-directory/ — without requiring a separate Forge site or server.
Creating a staging environment
To create a staging environment, provide:
- Directory name — the subdirectory name for staging (2–20 characters, alphanumeric with dashes and underscores). Cannot start with
wp-and certain reserved names are blocked. Must be unique per site. - Media mode — how to handle the
wp-content/uploadsdirectory
Each site can have up to 3 staging environments.
Media modes
The MediaMode enum controls how media files are handled during staging creation:
| Mode | Behavior | Trade-off |
|---|---|---|
| Copy | Full copy of wp-content/uploads to staging |
Safest — staging has its own copy. Uses more disk space. |
| Skip | No media files copied | Fastest — saves disk space. Images will show as broken in staging. |
| Symlink | Staging symlinks to production's uploads directory | Space-efficient — but changes to media in staging affect production. |
What the setup pipeline does
When you create a staging environment, WPHammer dispatches the CreateStagingPipeline — a six-step deployment:
1. Create staging database and user
The CreateStagingDatabaseJob uses the Forge API to create a dedicated database and database user for the staging environment. Credentials are stored encrypted on the Staging model.
2. Copy site files
The CopyStagingFilesJob uses rsync over SSH to copy production files to the staging subdirectory. It excludes .git, the staging directory itself, and handles media files according to the selected mode — copying, skipping, or creating a symlink.
3. Configure WordPress
The ConfigureStagingWpJob updates the staging site's wp-config.php with:
- Staging database credentials (
DB_NAME,DB_USER,DB_PASSWORD) WP_ENVIRONMENT_TYPEset tostagingDISABLE_WP_CRONset totrue(prevents scheduled tasks from running in staging)WP_HOMEandWP_SITEURLpointed to the staging URL
4. Clone database
The CloneStagingDatabaseJob exports the production database using WP-CLI, imports it into the staging database, and runs a comprehensive search-replace to update all production URLs to staging URLs. It also sets blog_public to 0 to discourage search engine indexing and flushes all caches.
5. Configure nginx
The ConfigureStagingNginxJob creates an nginx location block for the staging subdirectory, configures the PHP-FPM socket, sets up the tower-conf directory structure, and reloads nginx.
6. Apply protections
The ApplyStagingProtectionsJob installs safeguards to prevent staging from accidentally affecting production or the outside world:
- robots.txt — writes
Disallow: /to block search engine crawling - Email blocking — installs a mu-plugin (
staging-disable-mail.php) that prevents all outgoing email - Admin banner — installs a mu-plugin (
staging-admin-banner.php) that displays a yellow banner in the WordPress admin indicating this is a staging environment - Magic login — installs the wp-cli-login companion plugin for easy access
The staging status is set to Active and last_synced_at is recorded.
Staging status
The StagingStatus enum tracks the lifecycle:
- Creating — the setup pipeline is running
- Active — staging is ready and accessible
- Syncing — data is being synced from production
- Pushing — changes are being promoted to production
- Refreshing — staging is being refreshed from production
- Deleting — staging is being torn down
- Failed — an operation failed
The isBusy() method returns true for any transitional state (Creating, Syncing, Pushing, Refreshing, Deleting), which prevents concurrent operations on the same staging environment.
HTTP Basic Auth protection
You can add HTTP Basic Auth to a staging environment for additional access control. This creates a security rule on the server via the Forge API with a username and password you specify. The rule restricts access to the staging subdirectory, requiring credentials before any page loads.
Deleting staging environments
The DeleteStagingAction handles complete teardown:
- Marks staging status as Deleting
- Deletes the database user via the Forge API
- Deletes the staging database via the Forge API
- Removes the security rule if one exists
- Removes the nginx configuration via SSH
- Removes the staging directory from the server
- Deletes the
Stagingrecord
Related
- Syncing Staging — Refreshing staging from production
- Pushing to Production — Promoting staging changes
- Site Overview — Sites and their staging environments