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
mysqliandzlib.ZipArchiveis needed only for page packages as zip files. - The plugin in a folder named
bb-migrateon 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#
- Get the install zip: a release zip, or
python3 bin/build-zip.py, which writesdist/bb-migrate-<version>.zip. - 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.phptowp-content/mu-plugins/bb-migrate-compat.php(see Concepts), - creates the storage folder
wp-content/uploads/bb-migrate/, - schedules the hourly
bb_migrate_cleanupevent.
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>becomeshttps://staging.example.com/wp-json/bb-migrate/v1. - Sites without pretty permalinks use the
rest_routeform: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 otherhttp://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#
- On
example.comopen Tools → BB Migrate → Push. - Paste the connection string and click Test connection.
- 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.
- Type the remote's host name (
staging.example.com) in the confirmation field. - 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#
- On
example.comopen Tools → BB Migrate → Pull, paste the connection string, Test connection. - If this site is not local, type its own host name in the confirmation field.
- Click Pull. The remote's tables are downloaded into a
.sql.gzfile 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#
- Move a single page instead of the whole database: Page packages.
- Deploy a theme: Files and Site actions.
- Whole-site copy in one command:
wp bb-migrate sync.