SlickStack can create optional staging and development WordPress environments under the same primary domain as production.
The standard roles are:
- staging: a disposable production copy for short-term testing
- development: a more independent workspace for larger changes or new designs
These environments are convenient, but their sync and push commands can overwrite databases and files. Treat them as server-management tools rather than a full deployment platform.
- Environment layout
- DNS, HTTPS, and indexing
- Guest protection
- Staging behavior
- Shared production uploads
- Automatic staging synchronization
- Development behavior
- Development synchronization effects
- Lockdown and Multisite
- Pushing staging to production
- Pushing development to production
- Safe workflow
- Troubleshooting
- Managed boundaries
| Environment | URL | Web root | Database |
|---|---|---|---|
| Production | https://SITE_FULL_DOMAIN |
/var/www/html/ |
DB_NAME, normally production |
| Staging | https://staging.SITE_DOMAIN_EXCLUDING_WWW |
/var/www/html/staging/ |
staging |
| Development | https://dev.SITE_DOMAIN_EXCLUDING_WWW |
/var/www/html/dev/ |
development |
Production is always present. Enable the optional environments in /var/www/ss-config:
STAGING_SITE="true"
DEV_SITE="true"After changing these values, run:
sudo bash /var/www/ss-installThe installer creates the corresponding database, Nginx server block, WordPress files, generated wp-config.php, and permissions.
See SS-Config and Installation before changing production environment settings.
Create the relevant DNS records before enabling an environment:
staging.example.com
dev.example.com
The domains must also be covered by the active certificate arrangement. Wildcard certificates are normally the simplest option when staging or development subdomains are enabled.
The generated Nginx server blocks:
- redirect HTTP to HTTPS
- use separate environment web roots
- send an
X-Robots-Tagheader that blocks indexing and archiving - support shared guest HTTP authentication
- use the production
.well-knowndirectory for verification files
Noindex headers and password protection reduce accidental exposure, but they are not substitutes for removing real customer data, private messages, API credentials, or payment information from test environments.
Configure optional shared credentials with:
STAGING_SITE_PROTECT="true"
DEV_SITE_PROTECT="true"
GUEST_USER="example"
GUEST_PASSWORD="example-password"The same guest credentials are used for both protected subdomains.
Use unique credentials and do not reuse an administrator, SFTP, database, or Cloudflare password. Anyone with access to a protected environment may still see copied production content.
Staging is designed to be refreshed from production rather than maintained as a separate long-lived site.
Run a manual synchronization with:
sudo bash /var/www/ss-sync-stagingor:
ss sync stagingA synchronization occurs only when:
STAGING_SITE="true"SS_SYNC_STAGINGis any value other than"false"WP_MULTISITEis any value other than"true"
When those conditions are met, SlickStack:
- creates a fresh production database dump
- creates the staging database when missing
- imports production into the staging database
- copies selected production
wp-contentfiles into staging - fixes the staging
homeandsiteurlvalues - runs a production-to-staging WP-CLI search and replace
- replaces hardcoded production URLs found in staging theme files
- restores managed WordPress permissions
The staging sync copies production wp-content while excluding:
- uploads
- MU plugins
object-cache.phpblacklist.txt- files larger than 25 MB
Rsync does not broadly delete unmatched staging files, but matching files can be overwritten. The staging database is imported from production and therefore replaced.
Do not keep unique content, orders, settings, or other important state only in staging when synchronization is enabled.
Staging does not maintain a normal independent media library. Its Nginx server block maps:
/wp-content/uploads/
to the production directory:
/var/www/html/wp-content/uploads/
This reduces disk usage and makes staging synchronization faster, but it creates an important boundary:
Staging media requests use production files, and media operations performed through staging can affect the production uploads tree.
Do not use staging to test destructive media cleanup, filename migrations, bulk attachment deletion, or untrusted upload tools.
Automatic staging synchronization is controlled by:
SS_SYNC_STAGING="true"
INTERVAL_SS_SYNC_STAGING="half-daily"Supported scheduled values currently include:
hourly
quarter-daily
half-daily
daily
Set:
SS_SYNC_STAGING="false"when staging must remain unchanged.
The full ss-install workflow always invokes the staging sync script. If staging and synchronization are enabled and Multisite is not active, a normal production reinstall can overwrite the staging database and selected files.
See Cron Jobs for the fixed wrapper schedules.
Development is intended to be more independent than staging.
Enable it with:
DEV_SITE="true"Production-to-development synchronization is disabled by default:
SS_SYNC_DEVELOPMENT="false"To allow a deliberate manual refresh, set:
SS_SYNC_DEVELOPMENT="true"Then run:
sudo bash /var/www/ss-sync-developmentor:
ss sync developmentThe development sync runs only when all of these conditions are met:
DEV_SITE="true"SS_SYNC_DEVELOPMENT="true"WP_MULTISITEis not"true"SS_LOCKDOWNis not"true"
Unlike staging synchronization, development synchronization does not currently have a normal recurring interval option. It must be run manually.
A production-to-development sync:
- creates a fresh production database dump
- creates the development database when missing
- imports production into the development database
- copies selected production
wp-contentfiles, including uploads - fixes the development
homeandsiteurlvalues - runs a production-to-development WP-CLI search and replace
- replaces hardcoded production URLs found in development theme files
- restores managed WordPress permissions
The file copy excludes:
- MU plugins
object-cache.phpblacklist.txt- temporary and upgrade directories
- files larger than 25 MB
Development uses its own uploads directory. A sync copies eligible production uploads into that directory rather than mapping requests directly to production as staging does.
The development database and matching files are overwritten by a sync. Keep independent work under version control and back up any database-only changes before refreshing development.
SS_LOCKDOWN="true" currently blocks production-to-development synchronization. The option has limited functionality and should not be treated as a complete server freeze or deployment lock.
Normal staging and development sync workflows are not supported for WordPress Multisite. Both scripts skip their database-copy operations when WP_MULTISITE="true".
Do not attempt to bypass these checks without reviewing domain mapping, network tables, uploads, cookies, and certificate behavior.
The reverse command is:
sudo bash /var/www/ss-push-stagingor:
ss push stagingThis is a high-risk production overwrite operation. It requires typing yes within the current 30-second prompt.
When confirmed, the script:
- creates the normal SlickStack database dumps
- imports the staging database into the production database
- copies selected staging
wp-contentfiles into production - excludes uploads, MU plugins, temporary directories, upgrade directories, the blacklist, and files larger than 5 MB
- replaces staging URLs with the production URL across database tables
- resets WordPress permissions
- purges OPcache, transients, Memcached, and Nginx cache
The copy does not broadly delete unmatched production files, but the production database is replaced. Orders, users, posts, settings, form entries, and other production changes made after staging was copied can be lost.
The script's hardcoded theme-file URL replacement section is currently disabled and marked as needing work.
The development promotion command is:
sudo bash /var/www/ss-push-developmentor:
ss push developmentThe script labels this workflow experimental. It accepts y or yes at its confirmation prompt and then:
- creates the normal SlickStack database dumps
- imports the development database into production
- copies selected development
wp-contentfiles into production - includes uploads up to 512 MB
- excludes MU plugins, temporary directories, upgrade directories, and the blacklist
- replaces development URLs with the production URL across database tables
- resets permissions and purges all SlickStack origin caches
As with the staging push, the production database is overwritten and the hardcoded theme-file replacement section is currently disabled.
Do not treat either push command as transactional deployment, database merging, selective content promotion, or automatic rollback.
Before any sync or push:
- identify the source and destination clearly
- verify the current
ss-configvalues - create and inspect fresh database dumps
- verify an independent off-server backup
- preserve unique destination content
- confirm available disk space
- use a maintenance window for production pushes
- keep provider-console access available
Useful checks include:
grep -E '^(STAGING_SITE|DEV_SITE|SS_SYNC_STAGING|SS_SYNC_DEVELOPMENT|SS_LOCKDOWN|WP_MULTISITE)=' /var/www/ss-config
sudo ls -lh /var/www/backups/mysql/
df -h /After a production push, verify:
- the production URL and WordPress login
- recent orders, users, posts, and form entries
- uploads and static assets
- plugin and theme versions
- Nginx and PHP-FPM status
- cache behavior
- scheduled WordPress events
Check:
grep -E '^(STAGING_SITE|DEV_SITE|SS_SYNC_STAGING|SS_SYNC_DEVELOPMENT|SS_LOCKDOWN|WP_MULTISITE)=' /var/www/ss-configDevelopment synchronization prints the failed condition names. Staging synchronization currently skips quietly after its initial status message when its conditions are not satisfied.
Check the generated WordPress configuration and database values:
sudo -u www-data wp --path=/var/www/html/staging option get siteurl
sudo -u www-data wp --path=/var/www/html/dev option get siteurlThen inspect remaining URLs:
sudo -u www-data wp --path=/var/www/html/staging search-replace 'https://production.example.com' 'https://staging.example.com' --all-tables --dry-run
sudo -u www-data wp --path=/var/www/html/dev search-replace 'https://production.example.com' 'https://dev.example.com' --all-tables --dry-runReplace the example domains before running these commands.
This is expected under the shared uploads model. Restore the affected production uploads from backup and avoid destructive media testing in staging.
Stop making changes, preserve current files and database state, and restore the correct production database from a verified backup. The push scripts do not merge newer production records into the source environment.
See Backups, MySQL, and Logging for recovery guidance.
SlickStack owns the generated staging and development Nginx blocks, WordPress configuration files, environment databases, permissions, and sync scripts.
Persistent customization should use supported ss-config values, approved WordPress custom files, version control, and external deployment tooling where appropriate.
SlickStack's environment tools are designed for a simple single-server workflow. Database merging, selective table promotion, media offloading, content conflict resolution, zero-downtime deployment, and automated rollback remain outside their standard scope.