Skip to content

Getting started#

This page takes two sites from nothing to a first push and a first pull. The examples call them https://example.com (the site you work on) and https://staging.example.com (the other one).

Requirements#

  • WordPress 6.0 or later and PHP 7.4 or later on both sites.
  • PHP extensions mysqli and zlib. ZipArchive is needed only for page packages as zip files.
  • The plugin in a folder named bb-migrate on both sites. The compatibility mu-plugin and the "never transfer myself" rules look for that folder name.
  • The same plugin version on both sites. A transfer between different versions still runs, with a warning in the log.

Install#

  1. Get the install zip: a release zip, or python3 bin/build-zip.py, which writes dist/bb-migrate-<version>.zip.
  2. On each site: Plugins → Add New → Upload Plugin, choose the zip, activate.

On activation the plugin:

  • generates the site's secret key,
  • copies compat/bb-migrate-compat.php to wp-content/mu-plugins/bb-migrate-compat.php (see Concepts),
  • creates the storage folder wp-content/uploads/bb-migrate/,
  • schedules the hourly bb_migrate_cleanup event.

Deactivating removes the mu-plugin. Deleting the plugin removes its settings and job records; the storage folder is left in place.

To update the plugin later, upload the new zip the same way (Replace current with uploaded). The plugin cannot be updated through its own file sync: plugin:bb-migrate is not a valid scope.

The settings screen#

Tools → BB Migrate has nine tabs: Pages, Export, Import, Find & Replace, Pull, Push, Files, Site and Settings. The line under the title shows this site's URL, whether the plugin considers it local, its table prefix and its table count.

The Settings tab holds everything that is stored:

Field Setting Default Meaning
Connection info key generated This site's connection string, read-only. A checkbox regenerates the key on save
Allow other sites to pull allow_pull off Other sites may read this site's database and files
Accept pushes allow_push off Other sites may overwrite this site's database and files
Allow theme and plugin files allow_code_files off The two switches above also cover theme and plugin folders (PHP code)
Verify SSL certificates verify_ssl on Used when this site calls another one
Max request size (bytes) max_request 1048576 Upper bound for one request body; see Files
Rows per step chunk_rows 500 Starting number of rows per export chunk (never below 25)
Keep exports/backups for (hours) keep_files_hours 24 Files in the storage folder older than this are deleted by the hourly cleanup
Saved connections connections none One per line: a label, a vertical bar, the connection info. Offered as suggestions in every connection field

A saved connection line looks like this:

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

All of it is one option, bb_migrate_settings. From WP-CLI, wp bb-migrate settings prints the switches and the transfer limits and can set the three switches; max_request, chunk_rows, keep_files_hours, verify_ssl and the saved connections are edited on the Settings tab.

Connection strings#

A connection string is the receiver's REST endpoint, a space, and the receiver's key:

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

Copy it from the Settings tab of the site you want to reach, or print it there:

wp bb-migrate key

Rules the parser applies:

  • It must be <url> <key> with one run of whitespace between them. On the command line, quote it so it is one argument.
  • A bare site URL is accepted: https://staging.example.com <key> becomes https://staging.example.com/wp-json/bb-migrate/v1.
  • Sites without pretty permalinks use the rest_route form: https://staging.example.com/?rest_route=/bb-migrate/v1 <key>.
  • http:// is accepted only for local-looking hosts (loopback, private IPv4 ranges, single-label names such as Docker service names, and .local, .test, .localhost, .internal, .lan). Any other http:// URL is rejected as a malformed connection.

wp bb-migrate key --regenerate (or the checkbox on the Settings tab) replaces the key. Every connection string that was handed out for this site stops working.

The three switches#

All three are off after activation. They are set on the site that will be called, not on the site that drives.

Switch Turn it on when this site should… Commands that need it on the remote
allow_pull be read by another site pull, files pull, pages pull, pages list, sync pull; also files push and sync push, because the file diff reads the remote listing
allow_push be written by another site push, files push, pages push, site …, meta push, sync push
allow_code_files exchange theme or plugin files, or have plugins activated remotely files with a theme or plugin scope, site activate, site deactivate, sync with its default file scopes
wp bb-migrate settings --allow-pull=1
wp bb-migrate settings --allow-push=1 --allow-code-files=1
wp bb-migrate settings                      # print the current values

Turn them off again when the work is done. On production, see Security.

Test the connection#

On the driving site, open the Pull, Push, Files or Site tab, paste the connection string and click Test connection. The plugin performs a handshake and shows the remote's home URL, WordPress version, table prefix, table count, its allow_pull and allow_push values and whether it is local. On the Pull and Push tabs the find and replace box shows the automatic pairs as its placeholder.

The handshake needs a valid key but no switch, so it works before you turn anything on.

First push#

A push sends this site's database to the remote and overwrites the remote's database.

On the remote (staging.example.com): turn on Accept pushes and copy the connection string.

From the admin screen#

  1. On example.com open Tools → BB Migrate → Push.
  2. Paste the connection string and click Test connection.
  3. Optionally narrow the tables, change the exclusions (transients and spam comments are excluded by default in the admin form) or type your own find and replace pairs. Leave the pairs empty for the automatic ones.
  4. Type the remote's host name (staging.example.com) in the confirmation field.
  5. Click Push and accept the browser prompt. The progress bar and log follow the job: remote backup, tables sent, remote finalize.

From WP-CLI#

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

The command asks This overwrites the database of <url>. Continue? and then logs each table. What the remote keeps of its own (active plugins, its key and switches, and a few more options) is described in Database.

First pull#

A pull brings the remote's database here and overwrites this site's database.

On the remote: turn on Allow other sites to pull and copy the connection string.

From the admin screen#

  1. On example.com open Tools → BB Migrate → Pull, paste the connection string, Test connection.
  2. If this site is not local, type its own host name in the confirmation field.
  3. Click Pull. The remote's tables are downloaded into a .sql.gz file in the storage folder, this site's database is backed up, and the file is imported.

From WP-CLI#

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

Confirmation prompts and --yes#

Destructive actions ask before they run.

Action Admin screen WP-CLI
import, pull on a local site Browser prompt Prompt; --yes skips it
import, pull on a site that is not local Type this site's host name Refused without --yes ("This site is not local. Re-run with --yes to overwrite …")
push Type the remote's host name Prompt; --yes skips it
files … --delete (not a dry run) Tick the delete box Prompt; --yes skips it
site activate, site deactivate Browser prompt for deactivate Prompt; --yes skips it
pages push --on-exists=update Type the remote's host name Prompt; --yes skips it
meta push Not available in the admin screen Prompt; --yes skips it

A site counts as local when its host is localhost, 127.0.0.1 or ::1, ends in .local, .test, .localhost, .internal or .lan, is a private IPv4 address, or when WP_ENVIRONMENT_TYPE is local or development. .dev is a public top-level domain and does not count. The bb_migrate_is_local filter can add other hosts:

add_filter( 'bb_migrate_is_local', function ( $is_local, $host ) {
    return $is_local || $host === 'sandbox.example.com';
}, 10, 2 );

Next steps#