Skip to content

BB Migrate#

BB Migrate moves a WordPress site, or parts of one, between two installs that both run the plugin. It covers five jobs:

Feature What it is for
Database export, import, find and replace A .sql.gz dump of this site, an import that swaps tables in atomically, and a find and replace that keeps PHP-serialized data valid
Database push and pull The same export and import, streamed between two sites in chunks, with the URL and path replacements worked out from a handshake
File sync Copy media, a theme or a plugin to or from another site: a whole scope or only named paths, optionally deleting what the source no longer has
Page packages Move individual posts with their meta, terms, parent chain and every attachment they reference, as a zip or over the wire
Site actions The steps a deploy otherwise needs a person for on the remote: plugin activation, BB Cache settings and purge, snippet files, one meta value

Everything is available from Tools → BB Migrate in the admin and from wp bb-migrate on the command line.

The mental model#

There are always two sites and one of them drives.

  • The sender (also "the client", "this site", "local" in the command output) is the site where you click the button or run the WP-CLI command. It makes every request.
  • The receiver (also "the remote") only answers. It exposes REST routes under bb-migrate/v1 and does nothing on its own initiative.

"Push" and "pull" are named from the driving site's point of view: a push sends this site's data to the remote, a pull brings the remote's data here. Either way it is the driving site that runs the job, step by step, until it is done.

 sender (drives)                              receiver (answers)
 ┌──────────────────────┐   signed POST    ┌───────────────────────────┐
 │ admin screen / WP-CLI│ ───────────────▶ │ /wp-json/bb-migrate/v1/…  │
 │ job engine           │ ◀─────────────── │ checks signature, switches│
 └──────────────────────┘   JSON reply     └───────────────────────────┘
        holds the receiver's                  holds its own key and
        connection string                     its own three switches

A shared secret per receiving site#

Each site generates one secret key on activation. The key, together with the site's REST endpoint, is its connection string:

https://staging.example.com/wp-json/bb-migrate/v1 <key>

To drive a transfer against a site you paste that site's connection string into the driving site. The sender signs every request with the receiver's key; the receiver verifies the signature with the same key. There are no user accounts, cookies or application passwords involved, and the receiver never needs the sender's key.

Whoever holds a site's connection string can do whatever that site's switches currently allow. Treat it like a password.

Three switches on the receiver#

A valid signature is not enough. Each site has three switches, all off by default, that say what other sites may do to it:

  • Allow pull (allow_pull): its database and files may be read.
  • Accept push (allow_push): its database and files may be overwritten, packages imported, site actions run.
  • Allow code files (allow_code_files): the two above also apply to theme and plugin folders, and plugins may be activated or deactivated remotely.

The switches belong to the receiver and are checked on the receiver. The sender cannot change them, and a database push cannot overwrite them. See Concepts.

What the sender does#

The sender owns the work: it plans the job, cuts it into bounded steps, and repeats requests until the job is done. In the admin screen each step is one AJAX request of about twelve seconds; in WP-CLI the job runs to completion in one process. The receiver executes one small request at a time (a chunk of SQL, a batch of files), which keeps each request short enough for ordinary PHP and proxy limits. See Concepts.

What happens to the data#

  • A database arrives in temporary tables and replaces the live tables in one RENAME TABLE, after everything has been received. A transfer that fails halfway leaves the live tables as they were.
  • Before the swap the destination site backs up its current database to its storage folder (unless you skip it), and after the swap it restores a short list of its own options, such as its active plugins and its BB Migrate key and switches.
  • Find and replace runs on the imported tables after the swap. The default pairs rewrite the source site's home URL, uploads path and install path to the destination's.
  • Files are compared by size and modification time; only missing or changed files travel.
  • Imported pages arrive private unless you ask otherwise. Publishing stays a person's decision.

Where to go next#

  • Getting started: install, the settings screen, a first push and a first pull.
  • Concepts: the terms used on every other page.
  • Security: read this before turning on any switch on a production site.
  • Hosting notes: file ownership, proxies and other things that differ between servers.