Skip to content

Environment Sync and Rollback

Jon Imms edited this page Jun 25, 2026 · 1 revision

Environment Sync & Rollback

How to move content and FSE templates safely between WordPress environments — and recover when something goes wrong.

StrataWP includes built-in tooling (powered by the @stratawp/sync package) for three related jobs:

Task What it moves Direction Key commands
FSE template sync Site Editor templates stored in the database local ↔ remote sync:templates, sync:templates:list
Database sync MySQL tables (posts, options, etc.) pull or push sync:db:pull, sync:db:push
Rollback / snapshots Theme files + database dumps restore from history rollback:list, rollback:diff, rollback:mark-stable

Warning Database and template sync overwrite data in the destination environment. A pull replaces local data; a push replaces remote (often production) data. Always run with --dry-run first, and never push to production without a recent snapshot. See Deployment for the deploy flow that creates snapshots automatically.

Prerequisites

  • A StrataWP theme created with Installation & Quick Start.
  • The stratawp CLI available (provided by @stratawp/cli). Verify with stratawp --version.
  • A .stratawp-sync.json config file in your project root defining your environments (see Configuration below).
  • For most production databases (which only accept connections from 127.0.0.1), SSH access to the remote server with WP-CLI installed there.

Configuration

All sync commands read environments from .stratawp-sync.json in your project root. Create it once.

SSH configuration (recommended)

Most production databases only allow connections from localhost (127.0.0.1), so direct MySQL access fails. SSH-based sync runs the dump/restore on the remote server over an SSH tunnel.

{
  "environments": {
    "local": {
      "name": "local",
      "url": "http://local.test",
      "database": {
        "host": "localhost",
        "port": 3306,
        "user": "root",
        "password": "",
        "database": "wordpress"
      }
    },
    "production": {
      "name": "production",
      "url": "https://example.com",
      "ssh": {
        "host": "ssh.example.com",
        "port": 22,
        "user": "deploy",
        "key": "~/.ssh/id_rsa"
      },
      "wpPath": "/var/www/html",
      "database": {
        "host": "127.0.0.1",
        "user": "prod_user",
        "password": "prod_pass",
        "database": "wp_production"
      }
    }
  }
}

SSH options:

Option Description
ssh.host SSH server hostname
ssh.port SSH port (default: 22)
ssh.user SSH username
ssh.key Path to private key (supports ~ expansion)
ssh.passphrase Passphrase for encrypted keys (optional)
wpPath WordPress installation path on the remote server
wpCliPath Custom WP-CLI path (optional, defaults to wp)

Tip For encrypted SSH keys, prefer the STRATAWP_SSH_PASSPHRASE environment variable (ideal for CI/CD) over putting passphrase in the config file. If neither is set, you'll be prompted.

Direct MySQL configuration

For databases that allow public/remote connections (typically development or staging servers), you can skip SSH:

{
  "environments": {
    "staging": {
      "name": "staging",
      "url": "https://staging.example.com",
      "database": {
        "host": "db.staging.example.com",
        "user": "staging_user",
        "password": "staging_pass",
        "database": "wp_staging"
      }
    }
  }
}

FSE template sync

Full Site Editing templates edited in the Site Editor are stored in the database, not as theme files. This means a Git deploy of your theme does not carry over Site Editor changes. Use sync:templates to move those database-stored templates between environments via WP-CLI over SSH.

Step 1 — List local vs. remote templates

Before changing anything, see what exists on each side:

stratawp sync:templates:list production

This lists the FSE templates in your local database alongside those on production, so you can see what would change.

Step 2 — Preview the sync (dry run)

stratawp sync:templates production --all --dry-run

Tip --dry-run shows exactly what would be synced without writing anything. Make it a habit before every real sync.

Step 3 — Sync templates

Sync everything:

stratawp sync:templates production --all

Or sync a single template by slug:

stratawp sync:templates production --template=home

Custom WP-CLI / WordPress paths

If WP-CLI isn't at the default wp path, or your local WordPress root needs to be specified explicitly, override them per command:

stratawp sync:templates production --wp-cli=/path/wp    # Path to local WP-CLI binary
stratawp sync:templates production --wp-path=/wp/root   # Local WordPress root path

Both flags are also accepted by sync:templates:list.

If this fails: confirm WP-CLI is installed on the remote host (stratawp sync:templates:list production exercises the same SSH + WP-CLI path) and that wpPath in your config points at the WordPress install. Add --verbose to sync:templates for detailed output.


Database sync

Move full MySQL data (posts, options, metadata, and more) between environments. URLs are automatically rewritten so the destination site works at its own domain.

Warning A database sync replaces the destination database. sync:db:pull production overwrites your local data with production's. sync:db:push overwrites the remote database — for production this is destructive and irreversible without a snapshot. Always run --dry-run first, and ensure a snapshot exists before pushing (see Rollback & snapshots).

Pull remote data to local

This is the common, low-risk direction: bring production content down to your machine.

Step 1 — Preview:

stratawp sync:db:pull production --dry-run

Step 2 — Pull:

stratawp sync:db:pull production

Push local data to remote

Warning Pushing overwrites the target environment's database. Double-check the environment name. Only push to staging unless you fully intend to replace production content.

stratawp sync:db:push staging

Options

Option Effect Applies to
--tables=wp_posts,wp_postmeta Sync only the listed tables (comma-separated) pull, push
--no-url-replace Skip automatic URL replacement pull, push
--dry-run Preview without making changes pull, push
--force Skip the confirmation prompt push only

Examples:

stratawp sync:db:pull production --tables=wp_posts,wp_postmeta
stratawp sync:db:pull production --no-url-replace

How URL replacement stays safe

WordPress stores serialized PHP arrays in the database, where each string is prefixed with its byte length (e.g. s:24:"..."). A naive find-and-replace of a URL changes the string length and corrupts serialization. StrataWP's UrlReplacer recalculates those lengths automatically:

Before: s:24:"https://old-domain.com/path"
After:  s:27:"http://new-domain.test/path"

Use --no-url-replace only when you explicitly want the raw data preserved (for example, syncing into an identical domain).


Rollback & snapshots

A snapshot captures your theme files plus a database dump at a point in time. StrataWP creates one automatically before every deployment (unless you pass --no-backup), along with the current Git commit hash and branch. You can list, compare, and protect snapshots from the CLI.

Note Snapshots are stored in .stratawp-snapshots/ in your project root. Each snapshot directory contains a manifest.json, a compressed theme.tar.gz, and a compressed database.sql.gz. The snapshots.json file indexes them all.

List snapshots

stratawp rollback:list

Filter or expand the output:

stratawp rollback:list --environment=production   # Only production snapshots
stratawp rollback:list --limit=20                 # Show more entries (default: 10)

Compare two snapshots

See what changed between two points in time — added/deleted/modified files and SQL table differences:

stratawp rollback:diff 1 2                         # By index (from rollback:list)
stratawp rollback:diff snapshot-id-1 snapshot-id-2 # By snapshot ID

Protect a snapshot from auto-cleanup

Mark a known-good snapshot as stable so it isn't removed by automatic backup cleanup:

stratawp rollback:mark-stable 1

Tip After a successful, verified deployment, mark that snapshot stable. It becomes a reliable recovery point even after many later deploys.

Recommended recovery workflow

  1. Run stratawp rollback:list to find the snapshot you want to return to (note its index or ID).
  2. Run stratawp rollback:diff <good> <current> to confirm what changed.
  3. Mark your last-known-good snapshot stable with stratawp rollback:mark-stable <index> so it survives cleanup.
  4. Restore using your deploy workflow — see Deployment for redeploying a previous theme state, and use sync:db:pull/sync:db:push to restore database content as needed.

Note Snapshots integrate with stratawp deploy: a pre-deploy snapshot is created on every deployment unless you pass --no-backup. For the full deployment lifecycle, see Deployment.


Safe-sync checklist

Before any sync that touches a shared or production environment:

  • .stratawp-sync.json defines the correct environment and URL.
  • You ran the command once with --dry-run and reviewed the output.
  • A recent snapshot exists (run stratawp rollback:list to confirm).
  • You're pulling, not pushing — unless you genuinely intend to overwrite the remote.
  • URL replacement is enabled (omit --no-url-replace) when moving between different domains.

Related pages

For the canonical package docs, see packages/sync/README.md and the advanced deployment guide.

Clone this wiki locally