Symelo Backups and Migration user guide

For Symelo Backups and Migration version 1.0.0.

This guide explains how to back up your site, keep copies in the cloud, restore a backup (even when the site no longer loads), and move a site to a new domain or server. It covers what every option does and how to fix problems yourself. The last section, "For developers", covers wp-config.php constants, hooks, WP-CLI commands, the REST API and the backup file formats.

Need help? Write to [email protected] or visit symelo.com.

What it does

Symelo Backups and Migration keeps copies of your whole site somewhere safe and brings them back when you need them.

  • Backs up your database, plugins, themes, media uploads, the rest of wp-content and, if you want, WordPress itself. You start backups yourself or let schedules make them, from every hour to once a month.
  • Makes incremental backups: after a full backup, later backups only store the files that changed. A new full backup starts automatically every few days.
  • Copies backups to destinations: Google Drive, Dropbox, OneDrive / Microsoft 365, Amazon S3 and S3-compatible storage (Wasabi, DigitalOcean Spaces, Scaleway, MinIO), Cloudflare R2, Backblaze B2, Microsoft Azure Blob Storage, SFTP, FTP/FTPS and email. One backup can go to several destinations.
  • Restores a backup from the dashboard, the whole site or only some parts.
  • Restores even when the site is broken, with a private recovery link that works without WordPress.
  • Backs up before updates: the database and the plugin or theme being updated (or WordPress itself) are saved right before every update, automatic updates included.
  • Moves and clones sites: a migration package can be installed on an empty server with the standalone installer, uploaded to another site, or pulled by another site with a migration link. Addresses are replaced automatically, also inside serialized data.
  • Encrypts the database or the whole backup with your password.
  • Removes old backups by rules you choose, without ever breaking an incremental chain.
  • Emails you when a backup fails, adds Site Health checks, and has WP-CLI commands and a REST API.

All work runs in the background in short steps. You can close the page while a backup runs. The only exception is the restore itself: keep the restore page open until it says it's done.

Backups are ordinary .tar.gz archives and a gzipped SQL file. An unencrypted backup can be opened with standard tools, without the plugin.

Key terms

TermMeaning
BackupA copy of your site at one moment: a folder with a description (manifest.json), the database file, one or more file archives and a file list.
ComponentA part of the site you can back up and restore on its own: Database, Plugins, Themes, Media uploads, Other content and WordPress core.
Full backupContains every selected file. It can be restored on its own.
Incremental backupContains only the files that are new or changed since the backup before it. The database is always saved in full. It needs the backups it builds on.
ChainA full backup and the incremental backups built on it. Restoring an incremental backup uses the whole chain automatically.
This serverThe private backup folder on your web server, wp-content/uploads/symelo-backups-… (the end of the name is random). Every backup is made here first.
DestinationAnother place that keeps copies of your backups, for example Google Drive or an S3 bucket. If the server fails or is hacked, the copies there are still safe.
JobA task that runs in the background: a backup, preparing a restore, downloading or deleting a backup. Jobs run one at a time; others wait in line.
Migration packageA full backup made for moving a site: every component plus wp-config.php. It comes with an installer and a migration link.
Installer keyA 24-character password shown once when you create a migration package. Nobody can run the package's installer without it.
Installerinstaller.php, a single standalone file that sets up a migration package on a server, even one without WordPress.
Migration linkA long code starting with symelo-migrate: that lets another site download a migration package directly, server to server. It works for 48 hours.
Recovery linkA secret address that opens the restore tool without WordPress, so you can restore a backup stored on this server when the site is broken.
RestorerThe standalone restore tool. Restores always run in it, outside WordPress, because they replace WordPress's own database and files.
EncryptionOptional protection of backups with your password, applied before they leave the server. Without the password, encrypted backups can't be restored by anyone.
RetentionThe rules for how many old backups are kept, on this server and at destinations.
From another siteA backup whose signature this site can't check: it was made by another site, or changed afterwards, or this site's security keys changed since. Restoring it needs your confirmation.

Requirements

  • WordPress 6.4 or newer.
  • PHP 7.4 or newer. On older PHP the plugin stays inactive and shows: "Symelo Backups and Migration needs PHP 7.4 or newer. This site runs PHP …, so the plugin is inactive."
  • PHP extensions:
    • zlib: needed for every backup and restore (compression).
    • mysqli: needed by the restore tool to import the database. Almost every host has it.
    • sodium: strongly recommended. Encrypted backups use Argon2id to turn your password into a key, and only the sodium extension has it. Without it, the plugin falls back to WordPress's built-in sodium_compat library and PBKDF2. A backup encrypted on a server with sodium can only be decrypted on a server with sodium.
    • SimpleXML: needed for Amazon S3 and compatible storage, Backblaze B2 and Azure.
    • ftp (built with OpenSSL for FTPS): needed for the FTP / FTPS destination.
    • SFTP works without extensions (the plugin brings its own SFTP library). On PHP 7 it needs the setting mbstring.func_overload to be off.
  • Write permission for the web server on wp-content/uploads (backups are stored there) and on wp-content (the restore tool and the recovery link are placed there).
  • Disk space: the plugin won't start a backup with less than 50 MB free. Plan for roughly the compressed size of your site per full backup on this server, plus room to restore. See Retention and disk space.
  • Background work: the site sends short requests to itself, with WP-Cron as a fallback. If your host blocks both, run a system cron job (see Run backups from a system cron job).

Only administrators can see and use the plugin (the manage_options capability). Developers can change this; see For developers.

Multisite: backups cover the whole network: the tables and files of every site. The plugin's screen is in the main site's dashboard and is only available to super admins. Activate the plugin network-wide or on the main site.


Quick start

This gets you from installation to an automatic, offsite backup with a recovery link.

1. Install and activate

  1. In wp-admin, go to Plugins → Add New Plugin and search for "Symelo Backups and Migration".
  2. Click Install Now, then Activate.

To install from a .zip file instead, click Upload Plugin on the same screen, choose the file, click Install Now, then Activate.

A new Backups menu appears in the admin sidebar. The plugin creates its private backup folder and schedules its daily maintenance. Nothing is backed up yet.

2. Make your first backup

  1. Go to Backups. The Backups tab opens and says "No backups yet. Make your first one below: it runs in the background and takes a few minutes."
  2. In the Back up now card, leave the defaults: everything except WordPress core, type Automatic (recommended).
  3. Click Back up now.

You see "Backup started. It runs in the background, so you can close this page." and a progress bar. When it's done, the page says "The backup is finished." and the backup appears in the Backups list, stored at This server.

3. Add a destination

A backup that only lives on your server is lost if the server fails.

  1. Click the Destinations tab. Because there's no destination yet, the Add a destination picker is open.
  2. Click a service, for example Amazon S3 and S3-compatible, and fill in its settings. See Setting up each destination for where to find each value.
  3. Click Save destination. The plugin tests it right away: "Destination saved and tested: backups can be stored there."

For Google Drive, Dropbox and OneDrive / Microsoft 365 you first create your own app with the provider. After saving, click Connect … and sign in.

4. Set up a schedule

  1. Click the Schedules tab. The New schedule form is open.
  2. The defaults make a good start: Every day at 03:00, Incremental (recommended) with a Full backup every 7 days, your usual components, this server only (tick your destinations), and Keep the newest 7 backups.
  3. Click Add schedule.
  1. Click the Recovery tab and Create recovery link.
  2. Copy the link into your password manager now. It is shown only once.

If a bad update ever leaves you with a white screen, open this link and restore the newest backup from before the problem.

  • Settings → Encryption: set a password and choose Encrypt everything, especially when backups go to a cloud provider. See Encryption.
  • Settings → Notifications: check the Send to address. Failure emails are on by default.

Where to find everything

Backups in the admin sidebar opens one screen with seven tabs. They switch instantly without reloading.

TabWhat it's for
BackupsStatus, Back up now, the list of backups (restore, download, delete), recent activity and logs.
SchedulesAutomatic backups: how often, what, where to, how many to keep.
DestinationsWhere copies of your backups go: add, test, turn off and remove destinations.
MigrationCreate a migration package; import a site from a package, an FTP upload or a migration link.
RecoveryThe recovery link for broken sites, and the installer for restoring without this site.
SettingsWhat to back up, encryption, retention, notifications, backups before updates, speed and uninstall behaviour.
GuideThis user guide, inside the plugin, with a contents list and a search box ("Find in this guide").
SupportHelp links, a system information report and contact details.

The Plugins screen has Backups and Settings links under the plugin.

When a job is running, its live progress is shown below the tab bar, whichever tab is open.


Backups tab

Status summary

The top card shows how your backups are doing:

  • "Your last backup was 3 hours ago (date)." Backups before updates and backups from another site don't count here.
  • "The last backup failed: …" with a View log link, when the newest backup job failed.
  • "No backups yet. Make your first one below: it runs in the background and takes a few minutes."

Below it:

  • "Next scheduled backup: … (in 5 hours)." or "No schedule yet, so backups only happen when you start them." with a Set up a schedule link.
  • "Backups are only kept on this server. If the server fails, they are lost with it." with an Add a destination link, when you have no destination.

The Back up now button jumps to the form. Four figures follow: Last backup, Next scheduled, Backups (with their total size) and Destinations.

Back up now

SettingWhat it doesDefault
What to back upThe components to include (table below).As set in Settings → What to back up
Where to keep itThis server is always included: "Always. Needed for quick restores and the recovery link; old copies are removed as set under Settings → Retention." Tick the destinations that should get a copy too. Destinations that are turned off or can't run on this server are greyed out.Every working destination ticked
TypeAutomatic (recommended) or Full (see below).Automatic
Encrypt this backupOnly shown when an encryption password is set. "Uses the password from Settings → Encryption." If encryption is Off in the settings, ticking it encrypts everything.Ticked when encryption is on in the settings
NoteOptional, for example "Before the redesign". Shown in the list.Empty
ComponentDescription in the pluginDefault
DatabasePosts, pages, comments, users, orders and settings.On
PluginsEverything in wp-content/plugins.On
ThemesEverything in wp-content/themes.On
Media uploadsImages and files in wp-content/uploads.On
Other contentThe rest of wp-content, like must-use plugins and translations.On
WordPress corewp-admin, wp-includes and the files in the main folder. Usually not needed: WordPress can be reinstalled any time.Off

Good to know:

  • Must-use plugins (wp-content/mu-plugins) belong to Other content: they are saved and restored with it, not with Plugins.
  • Folders in the WordPress folder other than wp-admin, wp-includes and wp-content are never backed up. Symbolic links aren't backed up either; the job log lists them.
  • wp-config.php is saved separately when Include wp-config.php is on in the settings, and is never copied over your live file by a restore.

Automatic or Full:

  • Automatic (recommended): "Makes an incremental backup when a recent full one exists: only files that changed since the last backup are saved, which is much faster and smaller. Otherwise everything is saved. The database is always saved in full."
  • Full: "Saves every file again. Takes longer, but doesn't depend on earlier backups."

With Automatic, the backup is incremental when all of this is true:

  • an earlier backup you started yourself (not a scheduled one) has exactly the same file components;
  • that backup's whole chain is complete at every destination you ticked (or on this server, when you ticked none);
  • the chain's full backup is less than 7 days old, and the chain has fewer than 50 backups;
  • if the earlier backup is encrypted with Encrypt everything, it was made with the current password.

Otherwise a full backup is made. A backup with only the database is always complete on its own; the list shows it as Database. A full backup without the database shows as Files.

Click Back up now. You see "Backup started. It runs in the background, so you can close this page." If another job is running: "Another job is running. This backup starts as soon as it is done."

A backup is refused right away when there's less than 50 MB of free disk space ("There is only … of free disk space on this server, which isn't enough to make a backup. Free up space or remove old backups first."), or when encryption is requested without a password ("Set a backup encryption password in Settings → Encryption first, or turn encryption off for this backup.").

Progress

While a job runs, a card below the tab bar shows its title (for example Backing up), a status badge, a progress bar and what it's doing right now, for example "Backing up wp_posts (1,200 of 5,000 rows)" or "Uploading … to Google Drive". The note says "This runs in the background, so you can close this page."

  • Cancel stops the job after asking "Cancel this job? Work done so far is discarded." An unfinished backup is removed; an upload that was in progress is stopped at the destination.
  • View log opens the job's log.

While this screen is open, it also does a little of the work itself, so jobs keep moving even on hosts that block background requests.

A backup goes through these steps:

  1. Preparing the backup: full or incremental is decided.
  2. For incremental backups: Getting the file list of the previous backup (downloaded from a destination if needed).
  3. Backing up the database, table by table, then Checking the database backup: the dump is read back and must end with its completion marker.
  4. Looking for files, and for incremental backups Comparing with the previous backup (by size and modification time).
  5. Archiving files into one or more .tar.gz parts.
  6. Writing the file index and Calculating checksums. The signed manifest.json is written last: its presence means the backup is complete.
  7. Uploading each file to each destination, the manifest last.
  8. Removing old backups as the retention rules say.

When the job is done, the page reloads and shows the result:

  • "The backup is finished." with View log.
  • "The backup is finished. There were 2 warnings." (yellow). Warnings don't stop a backup: a skipped unreadable file, a symbolic link, tight disk space, or "Uploading to … failed: … The backup is still kept on this server."
  • "The backup failed: …" with the reason.
  • "The backup was cancelled."

The list of backups

The Backups card lists every backup on this server and at your destinations, newest first (the newest 200).

ColumnMeaning
DateWhen it was made, and how long ago. A lock icon means Encrypted. Backups made by another site also show "From https://other-site.com".
TypeFull, Incremental, Database, Files, Pre-update or Migration. Incomplete (red) when files are missing. "Scheduled" under it when a schedule made it.
SizeThe size of this backup's own files (not the chain).
ContentsThe components in it.
Stored atThis server and the names of the destinations that have a complete copy.
NoteYour note, or for example "Before updating the plugin Akismet".

Actions:

ActionWhen shownWhat it does
RestoreThe backup is complete on this server or at a destination that can send it back (every type except Email)Opens the restore form. See Restore from the dashboard.
DownloadThe backup is on this serverOpens a menu with every file: Manifest, Database, Files (or Files, part 1, part 2…), File index, and for migration packages Installer. "To restore it elsewhere, download every file, including the manifest."
Copy to this serverThe backup is only at destinations that can send it back"Copies the backup from its destination to this server, so you can download it. Restoring doesn't need this." Its download links appear when the copy is done.
A note instead of RestoreThe backup is only stored by email"Stored by email only: download the attachments and upload them on the Migration tab to restore." See Email.
DeleteThe backup is stored somewhereOpens a menu: Delete it from: with a checkbox per place, and Delete backup. Asks "Delete this backup from the selected places? This can't be undone." When this server also holds an unfinished copy of a backup that is complete at a destination, the menu has the extra checkbox This server (unfinished copy).
LogThe job that made it is still known (jobs are kept for 30 days)Opens that job's log.

Deleting:

  • Runs in the background: "The backup is being deleted in the background."
  • A backup that newer incremental backups build on can't be deleted first: "1 newer incremental backup builds on this one and can't be restored without it. Delete it first."
  • A backup that a running job is using can't be deleted: "This backup is being used by a running job. Try again when it has finished."
  • Email destinations can't delete emails. The backup disappears from the list for that destination, and the log says "Email can't delete files, so … stays there. Delete it there yourself if you need the space."

Look for backups at destinations (shown when you have destinations) opens a small panel. Click Look for backups in it to list this site's folder at every destination that is on and can list files (all except Email), and add the backups found there: "Looking for backups at your destinations…". Use it after restoring an older database or reinstalling the plugin.

By default it looks in the folder of this site's current address. To look in another folder, for example the one of this site's old address, fill in the optional Site folder ("After moving to a new address, enter the old one's folder, e.g. old-domain.com"). Show the folders at my destinations looks at your destinations and shows the other site folders with backups in them as buttons that fill in the field ("Folders of other sites: click one to use it.", or "No folders of other sites were found."). On big destinations this can take a while. See After a domain change.

An incomplete backup on this server (one that stopped before its manifest was written) can't be restored. Click Delete next to it ("Delete this incomplete backup from this server? It can't be restored, and this can't be undone."), or leave it: unfinished backup folders are removed automatically after two days. A backup that a running job is still writing is never offered for deletion.

Recent activity

The Recent activity card lists the last 12 jobs with Started, Job (Backup, Restore, Import, Package download, Download, Delete, Cleanup, Destination check, Migration package), Status (Waiting to start, Running, Finished, Finished with warnings, Failed, Cancelled), Details (the error, the progress, or "Took 3 mins" and the number of warnings) and a View log link.

While a prepared restore or import is waiting for you, its row says "Ready to restore. The link works until …" and has a Continue to the restore button. Only the administrator who started it sees the button, and only until the link expires (an hour after the backup was checked).

Logs

View log opens the log in place, titled for example "Log: Backup, October 12, 2026 3:00 am". Each line has the time in UTC, a level and what happened. Passwords, keys and tokens are never written to logs. Logs and finished jobs are kept for 30 days; older ones say "This log isn't available any more. Logs are kept for 30 days."


Schedules tab

"Schedules make backups for you. Times are in the site's timezone (…). WordPress starts them when the site gets visits, so on very quiet sites a backup can start a few minutes late."

If WP-Cron is turned off on your site, a warning says: "WP-Cron is turned off on this site (DISABLE_WP_CRON). Make sure your server calls wp-cron.php every few minutes, otherwise schedules don't run."

Schedules list

ColumnMeaning
ScheduleThe name (click to edit), with Off when it's turned off.
WhenFor example "Every day at 3:00 am", and "Incremental, full every 7 days" or "Full backups".
Backs upThe components, "To: …" (the destinations, or "This server") and how many are kept, for example "Keeps the newest 7".
Next runDate and time, or — when off.
Last runDate and time with a status: Done, Done with warnings (an upload failed), Running, Skipped, Cancelled or Failed. Below it the reason, if there is one (for example "Skipped: the previous backup of this schedule was still running." or why a backup failed), and a View log link to that run's log. "Not yet" before the first run.

Actions: Edit, Run now (starts a backup with this schedule's settings now; the next regular run stays as it is; refused with "A backup for this schedule is already running." while one is queued or running), Turn off / Turn on, Delete ("Delete this schedule? Backups it made are kept.").

Adding or editing a schedule

Click Add schedule (the form is already open when you have no schedule).

SettingWhat it doesDefault
NameOptional, for example "Nightly". Without one, the schedule is called "Daily backup", "Weekly backup" and so on.Empty
How oftenEvery hour, Every 6 hours, Every 12 hours, Every day, Every week or Every month.Every day
Day of the weekOnly for Every week.Monday
Day of the monthOnly for Every month. "1 to 28, so the day exists in every month."1
Time"A quiet time of day is best. For hourly backups only the minutes count; every 6 or 12 hours counts from this time."03:00
TypeIncremental (recommended): "Saves only the files that changed since the last backup, which is fast and small, and makes a full backup now and then. The database is always saved in full." Full every time: "Every backup stands on its own. Uses more time and space."Incremental
Full backup every … daysOnly for incremental. A new full backup starts when the chain's full backup is this old. "Restoring an incremental backup needs the full backup it builds on, so those are kept too." 1 to 365.7
What to back upThe components. Each schedule keeps its own choice.As in Settings → What to back up
Where to keep itThis server (always) plus the destinations you tick. A turned-off destination shows "(turned off: skipped until you turn it on)".This server only: tick your destinations
How many to keepKeep the newest … backups and delete them after … days. "0 means no limit. Older backups from this schedule are removed after each new one."7 and 0
StatusOn.On

Click Add schedule or Save schedule.

How schedules work:

  • Each schedule has its own chain of incremental backups. Manual backups and other schedules never mix into it.
  • An incremental schedule also makes a full backup when the chain can't be continued: a destination was added, the components changed, a chain member is missing at a destination, or the chain reached 50 backups.
  • If a schedule is due while its previous backup is still queued or running, that run is skipped (Last run shows Skipped).
  • Different schedules that are due at the same time wait for each other: one job runs at a time.
  • When a scheduled backup can't even start (for example no disk space, or encryption without a password), Last run shows Failed, and you get the email "[Site] Scheduled backup couldn't start" when failure emails are on.
  • How many to keep applies to this schedule's backups at each of its destinations. When the schedule has no destination, it applies on this server too. The copies on this server always follow Settings → Retention. See Retention and disk space.

Destinations tab

"Every backup is made on this server first. Destinations keep copies somewhere else, so you can still restore your site if the server fails or is hacked. Two places are safer than one."

Destinations list

The first row is always This server: "Always on. Old copies are removed as set under Settings → Retention." It shows Ready and the free disk space, with a Retention link.

Each destination shows its name, type and folder, and a status:

StatusMeaning
ReadySettings complete. (Use Test to check the connection.)
Connected + accountGoogle Drive, Dropbox or OneDrive is signed in.
Not connectedGoogle Drive, Dropbox or OneDrive: open it and click Connect ….
Reconnect needed + reasonThe sign-in was revoked or expired, or it can't be read any more: "The saved sign-in can't be read anymore (the site's security keys changed). Connect again." Open the destination and click Reconnect.
Off"Schedules skip it." Manual backups can't choose it either.
Needs attention + problemsA required value is missing, or "A saved password or key can't be decrypted any more (the site's security keys changed). Enter it again."
Not available + reasonThis server can't use this type, for example "This server's PHP has no FTP support (the ftp extension). Ask your host to enable it, or use SFTP."
Unknown type"The add-on that provided it may be inactive."

Actions: Edit, Test, Turn off / Turn on, Remove ("Remove this destination? Backups already stored there stay there, but this site stops using it.").

Test uploads a small file, finds it in the listing, reads it back and deletes it: "It works: a test file was uploaded and deleted again." or "The test failed: …".

Adding a destination

  1. Click Add destination (the picker is already open when you have none).
  2. Under Add a destination, click a service tile: Google Drive, Dropbox, OneDrive / Microsoft 365, Amazon S3 and S3-compatible, Cloudflare R2, Backblaze B2, Microsoft Azure Blob Storage, SFTP, FTP / FTPS or Email. Tiles the server can't use are greyed out with the reason. Tiles also show what the provider gives away, for example 10 GB free (green: free every month) or Free trials (blue: for a limited time), and the settings card explains the offer with a link to the provider's current prices. See Free storage at a glance.
  3. Fill in the service's fields. Required fields have a red asterisk (*). Each field's help text says where to find the value; see Setting up each destination.
  4. Optionally enter a Name ("Only shown in this plugin. Defaults to the service's name."), for example "Google Drive (office account)".
  5. Click Save destination.

After saving:

  • Most destinations are tested right away: "Destination saved and tested: backups can be stored there." or "Saved, but the connection test failed: …" (the settings are kept, so you can fix them).
  • Google Drive, Dropbox, OneDrive: "Saved. Now click Connect to sign in to your account." You stay on the destination's page.
  • SFTP without a host key fingerprint: "The server sent its host key. Check it below and click "Trust this key" if it is the right one." See SFTP.

Every destination except Email has a Folder (default SymeloBackups): "Backups are stored in this folder, in a subfolder named after this site (for example SymeloBackups/example.com/), so several sites can share one destination. Use slashes for subfolders." The subfolder is named after the site's address (host, port and path).

Editing a destination

Click its name or Edit.

  • Passwords, keys and secrets are never shown again. The field says "Saved. Leave blank to keep it." Type a new value to replace it. Optional secrets (for example a Dropbox app secret or an SSH key passphrase) have a Remove the saved value checkbox.
  • The type of a destination can't be changed: add a new one instead.
  • Google Drive, Dropbox and OneDrive show an Account card: Connected with "Backups are stored in [email protected]." and Disconnect; or Reconnect needed with the reason, Reconnect and Disconnect; or "Not connected yet. Save the client ID and secret below, then sign in to allow this site to store backups in your account." with Connect …. While a required setting is still empty (for example the OneDrive Tenant), it says "Fill in the settings marked * below and save them. Then you can sign in to allow this site to store backups in your account." and the destination shows Needs attention with, for example, "Tenant is required."
  • The Test, turn off or remove card: "The test uploads a tiny file, reads the folder and deletes the file again. A destination that is turned off is skipped by schedules but keeps its settings." Buttons: Test connection, Turn off / Turn on, Remove destination.

Turning a destination off is useful during maintenance of the storage: schedules skip it and say so in their log ("The destination "…" is turned off and was skipped."), and nothing else changes.

You can have up to 50 destinations.


Migration tab

"A migration package is a complete copy of this site (files, database and settings) that another site can import. Use it to move to a new domain or host, or to copy a site into this one."

See Migrating and cloning for complete walkthroughs.

Export this site

"Creates a package with everything, including wp-config.php. When it is ready you get three ways to move it: download the files, use the installer on a new server, or send the migration link to another site."

When encryption is on: "Encryption is on, so the package is encrypted. You'll need your encryption password on the other site."

Click Create migration package. It runs in the background like a backup: "Creating the migration package. It runs in the background; the download links appear here when it is ready."

When it's done, the Your migration package is ready card shows:

  • Save the installer key now. "It is shown only this once. You need it to run installer.php on a new server; nobody can use the installer without it." The Installer key field has a Copy button. After a reload: "The installer key was shown when the package was created and isn't shown again. If you didn't save it, create a new package."
  • Download the package: "Download every file. For a new server, also download the installer." The files, plus Installer (installer.php).
  • Or send it straight to another site: the Migration link with a Copy button. "On the other site, install this plugin and paste the link under Migration → Pull from another site. The link works until …. Anyone who has it can download the package, so keep it to yourself."

Packages on this server lists up to five packages with their download links. "Packages are listed on the Backups tab too, where you can delete them."

Each package there also has a New migration link button: "For pulling this package to another site, server to server. Links you made before keep working until they expire." Use it when the first link expired or got lost. The page then shows "New migration link for the package from …": "Copy the link now. It is shown only this once. If you lose it, create another one." Like the first one, it works for 48 hours.

Migration packages are only kept on this server; they aren't uploaded to destinations. They count towards the local retention rule (see Retention and disk space).

Moving to a new server

The card repeats the steps for an empty server:

  1. "Create a migration package and save the installer key."
  2. "Download all package files and installer.php."
  3. "On the new server, create an empty database, then upload installer.php and the package files to the folder where the site should live."
  4. "Open installer.php in your browser (for example https://example.com/installer.php), enter the installer key and the new database details."
  5. "When it is done, log in as usual. Check that installer.php and the package files are gone from the server."

"If WordPress is already installed there, install this plugin and import the package (below)."

Import a site into this one

"Importing replaces everything on this site (content, users, plugins, themes and settings) with the other site. Afterwards you log in with the other site's usernames and passwords."

There are three ways to get a package here. They all end up under Packages ready to import.

Upload from your computer

"Choose all files of the package: manifest.json and the .gz files (.enc when the package is encrypted). Big files are sent in small pieces, so your host's upload limit doesn't matter, and an interrupted upload continues where it stopped."

  1. Choose the files (several at once is fine).
  2. Click Upload. Each file shows its progress ("12 MB of 480 MB"). Pause and Resume are available.
  3. When a package is complete: "Package … is complete." with an Import this package button. Otherwise "Still missing: …".

If the upload stops, choose the same files again: the upload continues where it stopped. Files that aren't package files are refused ("Not a backup package file. Choose manifest.json and the .gz or .enc files of a backup."). The upload needs this much free disk space: the file's size plus 50 MB.

Files uploaded by FTP

"With FTP or your host's file manager, create a folder named after the backup ID inside the folder below, and put all package files in it. The backup ID is the start of the file names, like 20261012-191500-migration-a1b2c3." The Import folder field shows the folder, for example wp-content/uploads/symelo-backups-…/import/. "Then click "Look for packages" below."

Upload in binary mode, so the files don't get changed on the way.

Pull from another site

"On the other site, create a migration package and copy its migration link. This site then downloads the package directly, server to server, which is the fastest way."

Paste the link and click Download package: "Downloading the package from the other site. It appears under "Packages ready to import" when it is done." Every file's checksum is checked. A migration link can't be used on the site that made it: "This migration link is from this site. Paste it into the site you are moving to."

Packages ready to import

Look for packages refreshes the list. Each package shows Package (date and ID), From (the old address), Size and Status: Complete, or Files missing with the missing file names. Click Import next to a complete package. Delete removes a package's files from the import folder: "Delete this package? Its files are removed from the import folder on this server. This can't be undone."

The Import this package form shows Made on, Size and Links (old address → this site's address), and two warnings:

  • "Everything on this site is replaced. Posts, pages, users, plugins, themes, media and settings all come from the package. Afterwards you log in with a username and password from the other site. Make a backup of this site first if you might need it."
  • "Your site will be in maintenance mode during the import. Keep this browser tab open until it says it's done."

"Packages from another site can't be verified here, so only import packages you made yourself or trust."

Enter the Encryption password ("Only needed when the package is encrypted: enter the encryption password of the site that made it."), tick "I understand that this site's content and users will be replaced." and click Import and replace this site. It asks once more: "Import this package and replace this site? This can't be undone without a backup."

The package is checked ("Getting the package ready. The import starts as soon as it has been checked."), then your browser continues to the restore page, as for a restore. See What happens during a restore.

An import is refused before anything changes when the package doesn't fit this site: a multisite package on a single site, a single-site package on a multisite network, or a network package from another domain or path. See Multisite.

Packages stay in the import folder after an import. Delete them under Packages ready to import when you no longer need them.


Recovery tab

"A secret address that restores this site from a backup on this server, even when WordPress itself is broken: a white screen after an update, a crashed plugin, or a hacked site. It works without logging in, so treat it like a password."

Click Create recovery link. The page shows: "Save this link in your password manager now. It is shown only this once. If you lose it, create a new one." with the Recovery link and a Copy button.

The link looks like https://example.com/wp-content/symelo-recovery/index.php?key=….

The status card then says "The recovery link is on. It was created on …" and how many backups it can restore: "3 backups on this server can be restored with it." Without local backups: "There are no backups on this server yet, so the link has nothing to restore. Keep at least one copy on this server."

ButtonWhat it does
Create a new linkReplaces the link; the old one stops working. Asks "Create a new recovery link? The current link stops working."
Turn offRemoves the recovery tool; the link stops working right away.

The recovery tool lives in wp-content/symelo-recovery/. If a redeploy removes it, or the database details, paths, plugin version or encryption password change, the plugin sets it up again with the same link the next time a wp-admin page is opened. If that isn't possible, the card says "The recovery files are missing or can't be written (a deploy may have removed them). Create a new link to set them up again."

When your site is broken

  1. "Open the recovery link from your password manager."
  2. "Choose the newest backup from before the problem started."
  3. "Follow the steps. The files and database are replaced just like a normal restore, then you can log in again."

"The link only uses backups stored on this server. If the server itself is gone, install WordPress and this plugin on a new server, add the same destination, click "Look for backups at destinations" on the Backups tab (enter the old site folder if the address changed) and restore from there. Or move a migration package with its installer." See When the site is broken: the recovery link and On a new server for the details.

Restore without this site

"A migration package comes with installer.php, a standalone restorer that works on any server, even an empty one. Keep a recent package somewhere safe to be ready for the worst case."

When you have a package on this server, the card shows "Newest package on this server: …" with its download links. "The installer asks for the installer key shown when the package was created." The button Create a migration package (or Create a newer package) opens the Migration tab.

The installer only works with migration packages, and packages stay on this server. To be ready for a total server loss, download a recent package (all files plus installer.php) and keep it somewhere else, together with its installer key.


Settings tab

The settings are grouped in cards: What to back up, Encryption, Retention, Notifications, Before updates and Advanced. The links at the top jump to each card. Each card has its own Save changes button: "Settings saved."

What to back up

"Used by "Back up now" and new schedules. Each schedule keeps its own choice."

SettingWhat it doesDefault
ComponentsDatabase, Plugins, Themes, Media uploads, Other content, WordPress core. See Back up now. At least one is needed.All except WordPress core
Include wp-config.php"It holds your database login and security keys. It is stored in the backup but never copied over your live file automatically, so a restore can't lock you out." The installer uses it to set up the new site. Only saved when the backup includes files.On

Leave out

SettingWhat it doesDefault
Folders and files"One per line, relative to the WordPress folder. * matches anything, so */node_modules leaves out every node_modules folder. The defaults skip caches and other backup plugins' archives." Leaving out a folder leaves out everything in it. Up to 200 lines. Use the defaults fills in the default list again.See below
File typesExtensions without the dot, separated by commas.log, tmp
Files larger than … MB"A size of 0 means no limit."0

The default exclusions:

wp-content/cache
wp-content/upgrade
wp-content/upgrade-temp-backup
wp-content/updraft
wp-content/ai1wm-backups
wp-content/backups-dup-lite
wp-content/backups-dup-pro
wp-content/wpvividbackups
wp-content/uploads/backwpup-*
*/node_modules
*/.git

Patterns match the whole path. For example wp-content/uploads/2019 leaves out that year's uploads, and *.zip leaves out every .zip file. Patterns may contain letters, digits, spaces and . _ * / @ + -, but not ..; others are refused: '"…" isn't a valid path to exclude and was left out.'

Always left out, whatever you set: the plugin's own backup folder, the restore and recovery tools, .maintenance, and wp-config.php (saved separately, see above).

Database tables

OptionDescription in the plugin
This site's tables (starting with wp_) (default)"Recommended. Tables from other software in the same database are left out." On multisite this includes the tables of every site.
All tables in the database"Includes tables that don't belong to WordPress."
Only the tables I choose"For special setups. Leaving out WordPress tables can make a restore incomplete." A list of every table with its size appears; tick the ones to back up.

Encryption settings

"Encrypted backups can only be opened with your password, so a leaked or stolen backup reveals nothing. They are encrypted before they leave this server."

OptionDescription in the plugin
Off (default)"Backups can be opened with ordinary tools."
Encrypt the database"Protects user accounts, orders and settings. Files stay readable."
Encrypt everything"The database and all files. The safest choice when backups are stored with a cloud provider."

Under Password, enter a New password (at least 8 characters; "a long passphrase is best") and Repeat it. A red callout reminds you: "If you lose this password, your encrypted backups can't be restored by anyone, including us. Save it in your password manager. You also need it to restore a backup on another site or server."

Choosing a mode without a password doesn't turn encryption on: "Set a password to turn on encryption." Once a password is set, the card shows A password is set ("Leave the fields blank to keep it.") and a Remove the password card. See Encryption.

Retention

"How many backups stay on this server. Copies at destinations follow each schedule's own setting."

SettingDefault
Keep the newest … backups (0 to 1000)5
and delete them after … days (0 to 3650)0

"0 means no limit. Backups take disk space, so keep only what you need; the full backups that newer incremental ones build on are kept automatically." The card also shows the free disk space. See Retention and disk space.

Notifications

SettingWhat it doesDefault
Email me when a backup failsAlso when a backup finished but couldn't be copied to a destination, when a scheduled backup couldn't start, and when downloading a migration package fails.On
Also email me when a backup succeedsNot for backups before updates.Off
Send to"Separate several addresses with commas. Emails are sent with wp_mail(), so an SMTP plugin like Symelo SMTP improves delivery." Up to 10 addresses.The site's admin email

See Notices, emails and Site Health for what the emails contain.

Before updates

SettingWhat it doesDefault
Back up before updates"Before WordPress updates a plugin, a theme or itself (also automatic updates), a quick backup of the database and of what is being updated is made, so a bad update can be undone. It adds a few seconds to each update."On
Keep the newest … of these backups (1 to 50)Older backups before updates are removed.3

Below the settings, the card shows how the last backup before an update went: "Last backup before an update: … (… ago)" with Done, Skipped or Failed, and what happened, for example "Backed up before updating the plugin Akismet." or "No backup was made before updating the plugin Akismet because another backup was running. The update went ahead." Skipped and failed results are highlighted. Before the first update: "No backup has been made before an update yet."

See Backups before updates.

Advanced

Speed: "Backups run in short steps in the background. This sets how hard they may use the server."

SpeedDescription in the pluginLength of a stepPause between stepsWaits when the load per CPU core is at least
Fast"Long steps, one after another. For dedicated servers, or quiet times."25 sNoneNever
Normal (recommended) (default)"Steady work that pauses when the server is overloaded."15 sNone2.0
Gentle, for small servers"Short steps with pauses in between, and waits whenever the server is busy. Backups take longer, but visitors won't notice."6 s20 s0.7
  • A step never runs longer than PHP's time limit allows (the time limit minus 10 seconds, at least 5 seconds).
  • The load check needs a server that reports its load. Where it can't (for example on Windows), work never waits.
  • While the Backups screen is open, it also runs short steps of 3 to 8 seconds.
  • WP-CLI, the REST API's run route and backups before updates don't pause and don't wait for a busy server.
  • If the speed is set in wp-config.php: "Set by SYMELO_BACKUPS_SPEED in wp-config.php."

Archives

SettingWhat it doesDefault
Split archives into parts of … MB (10 to 4096)"Smaller parts upload more reliably to some destinations and fit email size limits. A single large file can still make a part bigger."500
Compression (1 to 9)"1 is fastest, 9 makes the smallest files. 6 is a good balance. Images and videos hardly shrink at any level."6

When the plugin is deleted

SettingWhat it doesDefault
Also delete its data"Removes the settings, schedules, destinations and sign-ins when you delete the plugin. Backups are never deleted: the ones on this server and at your destinations stay where they are, so you can still restore them."Off

Whatever you choose, deleting the plugin always removes the recovery link and leftover restore tools. See Deactivating and uninstalling.


Support tab

  • Get help: "Most problems come down to disk space, a destination's login details, or background requests being blocked by the host. The log of a failed job usually says exactly what went wrong." Links to Recent activity and logs, Test your destinations and Check Site Health, and an Email support button ([email protected]).
  • System information: a plain-text report with the plugin version, the storage folder (its random part masked) and whether it's writable, free disk space, backups, schedules, the current and recent jobs, your settings, destinations (names and types only), WordPress and server details, PHP extensions (including whether Argon2id is available) and disabled functions. "It never includes passwords, keys, tokens or links." Click Copy system information and paste it into your support email.
  • About Symelo LTD: who makes the plugin, with a link to symelo.com.

Notices, emails and Site Health

Admin notices

On the Dashboard and the Plugins screen, when the newest backup job failed:

"Symelo Backups: the last backup (date) failed: …" with a See what happened link to its log. The notice disappears after the next successful backup.

On the plugin's own screen, when the key that signs your backups had to be replaced:

"The key that signs your backups had to be replaced (the site's security keys changed). Backups made before … will show as "from another site", and restoring them needs one extra confirmation." Click Dismiss once you've read it. See Backups marked as from another site.

Emails

Emails go to the Send to addresses in Settings → Notifications, as plain text through wp_mail().

SubjectWhen
"[Site] Backup failed"A backup failed. "No new backup was saved; your earlier backups are not affected."
"[Site] Backup finished, but an upload failed"The backup is complete on this server, but couldn't be copied to every destination.
"[Site] Backup complete"Only with Also email me when a backup succeeds.
"[Site] Scheduled backup couldn't start"A schedule was due but its backup couldn't start, with the reason.
"[Site] Migration package download failed" / "[Site] Migration package downloaded"A pull with a migration link failed or finished.

Backup emails list the backup ID, who started it (an administrator, a schedule, an update or a migration export), the components, the start time, duration and size, each destination ("uploaded" or "failed (…)"), up to 10 warnings, and a link to the Backups screen.

Site Health

Tools → Site Health includes six checks:

CheckGood resultProblem and fix
Your site has a recent backup"The last successful backup was … ago.""Your site has no backup yet" (make one and set up a schedule). "Scheduled backups aren't running": the last backup is more than twice your most frequent schedule's interval old. Check the Backups screen for failed jobs and make sure WP-Cron runs.
Backups can't be downloaded from the web"The web server refuses requests for files in the backups folder.""The backups folder can be opened from the web": the server ignores the protection files (Nginx, for example). See Privacy and security. "The protection of the backups folder couldn't be checked": the site couldn't request a test file from itself.
Backup destinations work"No destination reported an error recently.""A backup destination has problems", with each destination's error from the last backup or listing.
There is enough disk space for backups"… of disk space is free; the last backup needed …""Disk space for backups is running low" (less than twice the last backup) or "There isn't enough disk space for the next backup" (less than the last backup).
Backups run in the background"No backup job is stuck.""A backup job is stuck": a job hasn't made progress for 30 minutes. See Jobs don't start or get stuck.
This site can recognize its own backups"The key that marks backups as made by this site is intact, so restores can check that a backup wasn't changed.""Older backups show as made by another site": the signing key couldn't be read any more (the security keys in wp-config.php or SYMELO_BACKUPS_KEY changed, or another site's database was imported), so a new one was made on the date shown. Older backups still restore, after a confirmation. Dismissing the notice on the plugin's screen also clears this result. See Backups marked as from another site.

The protection check is remembered for 12 hours.

Site Health → Info → Symelo Backups and Migration lists the version, the backups folder, free disk space, the number of backups (all, and how many of them are on this server), the last successful backup, schedules, destinations, encryption, speed, whether backups before updates and the recovery link are on, when the background runner last ran (and any error sending its request), and whether the scheduler event exists.


Setting up each destination

General tips:

  • Create a separate account, key or app just for backups, with access to the backup location only.
  • Keep buckets, containers and folders private.
  • After saving, check that the test passes. A destination's problems also show in the Backups list (missing copies) and in Site Health.
  • Provider dashboards change often. If a menu name below doesn't match exactly, look for the closest equivalent.

Free storage at a glance

Several providers store backups for free, which is enough for many small and medium sites, especially with incremental backups and retention rules. The offers below were checked on October 12, 2026. Providers change them, so check the provider's pricing page (linked on each destination's settings card) before you rely on one.

DestinationFree storageHow long
Google Drive15 GB per Google account, shared with Gmail and Google PhotosAlways
Cloudflare R210 GB (Standard storage class), 1 million write and 10 million read requests a month. Downloads are never charged, so restores are free.Always, every month
Backblaze B2The first 10 GB. Downloads are free up to three times what you store each month.Always
OneDrive / Microsoft 3655 GB per Microsoft account, shared with Outlook.com attachmentsAlways
Dropbox2 GB (Dropbox Basic)Always
Microsoft Azure Blob Storage5 GB of hot blob storage (locally redundant), plus $200 of credit for the first 30 days, with a new Azure free account12 months
Amazon S3No free storage. New AWS accounts get $100 of credit (up to $200) on the free plan.Up to 6 months
Wasabi (S3-compatible)A trial with up to 1 TB, no credit card30 days
Scaleway (S3-compatible)750 GB for new Object Storage users90 days
DigitalOcean Spaces (S3-compatible)None ($5 a month for 250 GiB)–
SFTP, FTP / FTPSYour own server or hosting account–
EmailLimited by your mailbox and the attachment size limit–

To estimate what fits: backups are compressed, but images and videos barely shrink, so a full backup is usually between half and the whole size of your site's files plus the database. Each incremental backup only stores what changed. The Backups tab shows the size of every backup.

Google Drive

"Store backups in Google Drive (personal or Google Workspace). You sign in with Google; no password is stored."

You create your own Google app once. Steps (from the field help):

  1. In the Google Cloud Console, create a project (or choose one) and enable the Google Drive API.
  2. Open Google Auth platform and set the audience:
    • Google Workspace: Internal.
    • Personal Google account: External, then Publish app. "In Testing mode Google ends the access after 7 days."
  3. Go to Clients → Create client, choose Web application, and add the Redirect URI shown on the destination form as an authorized redirect URI. It must match exactly.
  4. Copy the Client ID and the Client secret ("Shown when you create the client (Clients → your client → Client secrets).").
  5. In WordPress, add a Google Drive destination, paste both, set the Folder and click Save destination.
  6. Click Connect Google Drive, choose the account and allow access. You return with "Connected to Google Drive as [email protected]."
FieldWhat to enterDefault
Redirect URIRead-only, with Copy. Add it to your Google client.–
Client ID (required)Ends in .apps.googleusercontent.com.Empty
Client secret (required)Stored encrypted.Empty
Folder"Folder in your Google Drive for the backups, e.g. SymeloBackups. Use / for subfolders. The plugin creates it: it can only see folders and files it created itself, not ones you made by hand."SymeloBackups

Things to know:

  • "The plugin only asks for access to the files it creates, so Google doesn't require an app review." It can't see the rest of your Drive.
  • Because of that, files you upload or move into the folder by hand are invisible to the plugin. If you set up the destination on a new site and want to see older backups, use the same Google app (the same client ID).
  • If you change the client ID after connecting: "The client ID changed after Google Drive was connected. Reconnect Google Drive on the Destinations tab."
  • Disconnect also revokes the access at Google.
  • The plugin refreshes sign-ins that haven't been used for 7 days, so they don't expire while unused.

Dropbox

"Store backups in Dropbox, in an app folder or anywhere in your Dropbox. You sign in with Dropbox; no password is stored."

Steps (from the field help):

  1. At dropbox.com/developers/apps, click Create app, choose Scoped access, then App folder (backups go to Apps/<app name>) or Full Dropbox.
  2. On the Permissions tab, turn on files.metadata.read, files.content.write and files.content.read, and click Submit.
  3. On the Settings tab, add the Redirect URI from the destination form, then copy the App key.
  4. In WordPress, add a Dropbox destination, paste the App key, and click Save destination.
  5. Click Connect Dropbox and allow access.
FieldWhat to enterDefault
App key (required)From the app's Settings tab.Empty
App secret"Optional: sign-in uses PKCE, which doesn't need the app secret. If you enter it, it's stored encrypted."Empty
Folder"Folder in your Dropbox for the backups, e.g. SymeloBackups. Use / for subfolders. With an "App folder" app it's inside Apps/<app name>/."SymeloBackups

If a permission is missing when you connect: "Dropbox didn't grant every permission backups need (missing: …). Check the app's permissions, click "Connect" again and allow access to files." Permissions changed after connecting only take effect after connecting again. Disconnect also revokes the access at Dropbox.

OneDrive / Microsoft 365

"Store backups in OneDrive or OneDrive for Business (Microsoft 365). You sign in with Microsoft; no password is stored."

Steps (from the field help):

  1. In the Microsoft Entra admin center (entra.microsoft.com), go to App registrations → New registration. Choose who may sign in ("for a personal OneDrive, include personal Microsoft accounts").
  2. Add the Redirect URI from the destination form with the platform Web.
  3. Under API permissions → Add a permission → Microsoft Graph → Delegated permissions, add Files.ReadWrite, offline_access and User.Read.
  4. Under Certificates & secrets → New client secret, create a secret and copy its Value (not the Secret ID).
  5. In WordPress, add a OneDrive / Microsoft 365 destination, fill in the fields below and click Save destination.
  6. Click Connect OneDrive, choose the account and accept.
FieldWhat to enterDefault
Application (client) ID (required)From the app's Overview page.Empty
Client secret (required)The secret's Value. "Secrets expire (after 24 months at most): add a new one before then."Empty
Tenant (required)"Depends on the app's "Supported account types" (on its Authentication page). Single tenant, the default for new apps: the Directory (tenant) ID from the app's Overview page. Multiple Entra ID tenants (multitenant): organizations. Multitenant and personal Microsoft accounts: common. Personal Microsoft accounts only: consumers."Empty (placeholder "Directory (tenant) ID")
Folder"Folder in your OneDrive for the backups, e.g. SymeloBackups. Use / for subfolders. It is created when needed."SymeloBackups

The Tenant must match the "Supported account types" you chose for the app. New apps are single-tenant: they need your Directory (tenant) ID from the app's Overview page; common fails with AADSTS50194. For a personal OneDrive, the app must allow personal Microsoft accounts. Other values are refused when you save. When the client secret expires, backups to OneDrive fail with a sign-in error: create a new secret, enter it in the destination, save, and connect again. Microsoft has no simple way to revoke a sign-in from outside, so Disconnect deletes the stored sign-in from your site.

Sign-in problems (Google Drive, Dropbox, OneDrive)

MessageFix
"The sign-in link expired or was already used. Click "Connect" again."Finish signing in within 10 minutes, in the same browser and admin account.
"Signing in to … didn't finish: …"The provider's reason follows. Often the redirect URI doesn't match: copy the Redirect URI again and paste it into the app exactly.
"… Microsoft needs this app's own tenant. Copy the Directory (tenant) ID from the app's Overview page in Microsoft Entra into the destination's Tenant field, save, and click "Connect" again."Microsoft answered AADSTS50194 (a single-tenant app used with common) or AADSTS90002 (unknown tenant). As the message says.
"The saved sign-in can't be read anymore (the site's security keys changed). Connect again."The security keys in wp-config.php or SYMELO_BACKUPS_KEY changed, or the database came from another site. Click Connect again.
"… didn't send a refresh token, so backups would stop working within hours. Remove this app's access in your account's security settings, then click "Connect" again."As the message says.
"… didn't accept the client ID or client secret. Check both on the destination (client secrets can expire), save, and connect again."As the message says.
"Access to … was revoked or has expired. Reconnect … on the Destinations tab."Open the destination and click Reconnect.
"This site uses plain permalinks, so the redirect URI contains "?", which sign-in services may reject."Choose another structure under Settings → Permalinks first, then copy the new redirect URI.

If your site's address changes (a new domain, or http to https), the redirect URI changes too. Update it in your app and connect again.

Amazon S3 and S3-compatible storage

"Amazon S3, Wasabi, DigitalOcean Spaces, Scaleway, MinIO and other S3-compatible storage. Cloudflare R2 has its own destination."

FieldWhat to enterDefault
ProviderAmazon S3, Wasabi, DigitalOcean Spaces, Scaleway Object Storage, or MinIO or another S3-compatible service (custom endpoint).Amazon S3
Access key ID (required)"Create a key that may only list, read, write and delete objects in this bucket (for AWS: s3:ListBucket, s3:GetObject, s3:PutObject, s3:DeleteObject and s3:AbortMultipartUpload)."Empty
Secret access key (required)Stored encrypted.Empty
Bucket (required)"The bucket must exist already. Keep it private."Empty
Region"Where the bucket is. Amazon S3 and Wasabi: for example us-east-1 or eu-central-1. DigitalOcean Spaces: for example nyc3, ams3 or fra1. Scaleway: fr-par, nl-ams, pl-waw or it-mil. Other services: as they document it, usually us-east-1." Required for Wasabi, DigitalOcean Spaces and Scaleway.Empty
Endpoint URLOnly for a custom endpoint (required there). "The service's S3 API address, starting with https://, with the port if it isn't the default (for MinIO often https://your-server:9000). Plain http:// only works for a server in your own network (localhost, a private IP address or a name without dots), because backups would travel unencrypted." Other http:// addresses are refused when you save.Empty
Path-style URLs"Puts the bucket name in the path (https://endpoint/bucket/…) instead of the host name. Always used for custom endpoints and bucket names with dots."Off
Storage classOnly for Amazon S3: Standard, Standard-Infrequent Access, One Zone-Infrequent Access, Intelligent-Tiering, Glacier Instant Retrieval, Glacier Flexible Retrieval, Glacier Deep Archive.Standard
Server-side encryptionOnly for Amazon S3: "Ask Amazon S3 to encrypt the files at rest with SSE-S3 (AES-256). New buckets do this by default; turn it on when a bucket policy requires the header."Off
FolderSee Adding a destination.SymeloBackups

Things to know:

  • About storage classes: "Glacier Flexible Retrieval and Deep Archive are the cheapest, but their files must be restored in the AWS console (hours) before this plugin can download them, and early deletion is charged. Infrequent Access and Glacier classes charge minimum storage periods." Retention deletes old backups, so minimum storage periods may cost extra. For quick restores, use Standard, Intelligent-Tiering or Glacier Instant Retrieval.
  • Files over 8 MB are uploaded in parts and resume where they stopped. A cancelled upload is aborted. An unfinished multipart upload can also be cleaned up by a bucket lifecycle rule.
  • Avoid lifecycle rules that delete or move backup files. The plugin's retention already removes old backups, and rules that delete files can break incremental chains.
  • Every request is signed (AWS Signature Version 4) and carries a checksum, so the storage rejects anything damaged on the way.
  • Server-side encryption protects the files at the provider. For end-to-end protection, also turn on the plugin's encryption.

Cloudflare R2

"Object storage from Cloudflare with no download fees, through its S3-compatible API." R2 includes 10 GB of storage free every month (see Free storage at a glance).

Set it up in the Cloudflare dashboard:

  1. Open R2 (you may need to turn R2 on for your account once). Create a bucket, for example site-backups. Leave public access off. Keep the default storage class Standard: the free tier doesn't cover Infrequent Access.
  2. Copy your Account ID from the R2 overview page (Account details).
  3. Open Manage API tokens and create an R2 API token with the Object Read & Write permission, limited to this bucket. Copy the Access Key ID and Secret Access Key: Cloudflare shows the secret only once.
FieldWhat to enterDefault
Account ID (required)"Shown in the Cloudflare dashboard on the R2 overview page (Account details), 32 letters and digits."Empty
Access key ID (required)"In the Cloudflare dashboard, open R2, then Manage API tokens, and create an R2 API token with the "Object Read & Write" permission, limited to this bucket. Copy the Access Key ID and Secret Access Key it shows (only once)."Empty
Secret access key (required)Stored encrypted.Empty
Bucket (required)"A bucket you created in R2. Leave public access off."Empty
JurisdictionDefault (automatic location) or European Union (EU). "Choose EU only for buckets created with the EU jurisdiction, which keeps the data inside the European Union."Default
FolderSee Adding a destination.SymeloBackups

Things to know:

  • A wrong account ID gives: "Enter your Cloudflare account ID (32 letters and digits)."
  • R2 always encrypts stored files, so there is no server-side encryption option. For end-to-end protection, turn on the plugin's encryption.
  • Downloads from R2 are free, so restoring or copying a backup back to the server costs nothing.
  • Uploads over 8 MB go in parts and resume where they stopped, like Amazon S3.

Backblaze B2

"Low-cost cloud storage from Backblaze, through its S3-compatible API."

FieldWhat to enterDefault
Application key ID (required)"Create an application key in Backblaze under Application Keys, limited to this bucket with read and write access. The master application key doesn't work with this connection."Empty
Application key (required)Shown once when you create the key. Stored encrypted.Empty
Bucket (required)"A private bucket that already exists."Empty
Endpoint region (required)"The part between "s3." and ".backblazeb2.com" in the bucket's endpoint, shown on the Buckets page (for example us-west-004 or eu-central-003)."Empty
Server-side encryption"Ask Backblaze to encrypt the files at rest (SSE-B2). Buckets can also do this by default."Off
FolderSee Adding a destination.SymeloBackups

A wrong region gives: "Enter the endpoint region as shown on the Backblaze Buckets page, for example us-west-004."

Microsoft Azure Blob Storage

"Store backups in a container of an Azure storage account."

FieldWhat to enterDefault
Storage account name (required)"The name of the storage account (3 to 24 lowercase letters and digits)."Empty
Sign in withAccess key or Shared access signature (SAS token). "A SAS token limited to one container is safer than the account's access key."Access key
Access key"In the Azure portal: storage account → Security + networking → Access keys." Copy the Key value, not the connection string.Empty
SAS token"Create it for this container (or for the Blob service with container and object access) with the Read, Write, Delete and List permissions, HTTPS only, and a far-away expiry date. Paste the part after the "?"."Empty
Container (required)"A private container that already exists." 3 to 63 lowercase letters, digits and single hyphens.Empty
Azure cloudAzure (global), Azure operated by 21Vianet (China) or Azure Government (US).Azure (global)
Access tierAccount default, Hot, Cool (30-day minimum) or Cold (90-day minimum). "The Archive tier isn't offered: archived backups can't be restored without rehydrating them first."Account default
FolderSee Adding a destination.SymeloBackups

When a SAS token expires, uploads fail. Create a new token and enter it in the destination.

SFTP

"Any server you can reach over SSH: a storage box, a VPS or a NAS. Encrypted, with the server's identity checked."

FieldWhat to enterDefault
Server (required)For example backup.example.com or an IP address, without sftp://.Empty
Port1 to 65535.22
Username (required)The SSH user.Empty
Sign in withPassword or Private key. "A private key that is used only for backups is the safest choice."Password
PasswordFor password sign-in. Stored encrypted.Empty
Private key"Paste the whole private key (OpenSSH, PEM or PuTTY format). Add its public key to ~/.ssh/authorized_keys on the server." Stored encrypted.Empty
Key passphrase"Only if the private key is protected with a passphrase."Empty
Host key fingerprintThe server's SHA-256 fingerprint, like SHA256:…. See below.Empty
Folder"Folder for the backups, relative to the folder you land in after logging in (usually your home folder). Start with / for an absolute path. Each site gets a subfolder."SymeloBackups

Trusting the server's host key. The plugin only sends your password or key to a server whose identity it has checked. It never transfers backups without a saved fingerprint.

  1. Save the destination with Host key fingerprint empty. The plugin connects without logging in and reports: "The server sent its host key. Check it below and click "Trust this key" if it is the right one."
  2. The Check the server's host key card shows: "The server answered with a ssh-ed25519 key with this fingerprint: SHA256:…"
  3. Compare it with the fingerprint your host gives you. On a computer you trust, you can also run:
    ssh-keyscan backup.example.com | ssh-keygen -lf -
    
  4. Only if they match, click Trust this key within 15 minutes. The plugin saves it, logs in for real and tests: "The host key is saved and the connection works. The plugin now refuses to connect if the server shows a different key."

You can also paste the fingerprint into the field yourself before saving.

If the server's key changes later (a reinstall, a move, or an attack), backups to it stop: "The server's host key doesn't match the saved fingerprint (saved: …, server: …), so the plugin didn't log in. If the server was reinstalled or moved, check the new fingerprint with your host and save it. Otherwise someone may be intercepting the connection."

Connections time out after 30 seconds.

FTP / FTPS

"A web host or NAS that offers FTP with TLS encryption (FTPS). Prefer SFTP when the server has it."

FieldWhat to enterDefault
Server (required)For example ftp.example.com, without ftp:// or a folder.Empty
Port1 to 65535.21
Username (required)Empty
Password (required)Stored encrypted.Empty
EncryptionRequire TLS (explicit FTPS) or None: plain FTP (not recommended). "With plain FTP, your password and the backups travel unencrypted and can be read on the way. Only choose it for a server in your own network."Require TLS
Passive mode"Leave this on unless your host tells you otherwise; it works through most firewalls."On
Folder"Folder for the backups, relative to the folder you land in after logging in. Start with / for an absolute path. Each site gets a subfolder. Keep it outside the public web folder."SymeloBackups

Things to know:

  • Only explicit FTPS (AUTH TLS, usually port 21) works. Implicit FTPS on port 990 isn't supported by PHP.
  • If the server refuses TLS, the login fails; the plugin never falls back to plain FTP by itself.
  • PHP doesn't check the FTPS server's certificate, so FTPS protects against eavesdropping but not against an impostor server. SFTP with a trusted host key is stronger.
  • FTPS needs PHP's FTP extension built with OpenSSL: "This server's PHP can't use FTPS (its FTP extension was built without OpenSSL). Use SFTP instead."
  • Uploads resume where they stopped when the server supports it.

Email

"Emails each backup file as an attachment. Only for small sites: mail servers limit the size of attachments."

FieldWhat to enterDefault
Send to (required)"One or more addresses, separated by commas. Backups contain your whole site, including user data: send them only to mailboxes you trust." Up to 10.Empty
Largest file (MB)1 to 100. "Files above this size aren't emailed. Attachments grow by about a third when sent, and most mail services accept 20 to 25 MB per email in total. Lower the archive split size in the plugin settings so that the parts fit."20

Things to know:

  • Each file of a backup is sent in its own email, the manifest last. Subjects look like "Backup of My Site: 20261012-030000-full-a1b2c3 (files, part 2)".
  • Emails go through wp_mail(), so the site's email setup must work (Symelo SMTP helps).
  • A file over the limit isn't sent: "… is …, more than the email limit of …, so it wasn't emailed. Send this site's backups to cloud storage or SFTP instead, or lower the archive split size in the plugin settings." Set Settings → Advanced → Split archives into parts of below the limit, for example 12 MB for a 20 MB limit.
  • The plugin can't list, download or delete emails. A backup that is only stored by email has no Restore or Copy to this server action; the list says "Stored by email only: download the attachments and upload them on the Migration tab to restore."
  • To restore from emails: save every attachment of the backup into one folder, upload them under Migration → Upload from your computer, then Import. An import replaces the whole site except WordPress core files and wp-config.php.
  • Test sends "Test email from Symelo Backups on …" with a small attachment, symelo-test.txt.

Restoring

There are three ways to restore:

SituationUse
The site works and you can log inRestore from the dashboard
WordPress is broken (white screen, fatal error, hacked) but the server and its backups are thereThe recovery link
The server is gone, or you're setting up a site on an empty serverinstaller.php, or a fresh WordPress with this plugin

Make a backup of the current state first when you can: if the restore isn't what you wanted, you can go back.

Restore from the dashboard

  1. On the Backups tab, click Restore next to the backup.
  2. The Restore the backup from … form opens:
    • A yellow box: "Your site will be in maintenance mode during the restore. Visitors see a short "back in a moment" message. Most restores take a few minutes; large sites take longer. Keep this browser tab open until it says it's done."
    • For a backup from another site, a red box: "This backup was made by another site (…). Backups are signed by the site that made them, and this signature can't be checked here, so there is no way to tell whether the backup was changed. Only restore it if you trust where it came from."
  3. Under What to restore, untick the parts you want to keep as they are. Each part says what it replaces (table below).
  4. Optional settings:
    • Remove plugins and themes that aren't in the backup (when the backup contains plugins or themes): "Leave this off to keep plugins and themes installed after the backup was made." It isn't offered for backups before updates, which hold a single plugin or theme.
    • "Links are changed from https://old.example.com to https://example.com." when the backup was made at another address.
    • "This incremental backup builds on 3 earlier backups, which are used automatically."
    • Restore from: when the backup is in several places it can be restored from, choose which copy to use. This server is fastest. (Email copies can't be restored from.)
    • Encryption password, for encrypted backups: "Leave this blank to use the password saved in Settings. Enter a password only if this backup was made with an older one." It's required when no password is saved on this site any more, or the backup comes from another site.
    • For a backup from another site, tick "I trust this backup and want to replace this site with it."
  5. Click Restore now and confirm "Restore this backup now? The parts you selected are replaced."
PartWhat restoring it does
Database"Replaces all posts, pages, comments, users, orders and settings with their state on …. Anything added or changed since then is lost, and you may have to log in again."
Plugins"Replaces the plugins in wp-content/plugins with the versions in the backup."
Themes"Replaces the themes in wp-content/themes with the versions in the backup."
Media uploads"Puts back the media files from the backup. Files uploaded since then are kept."
Other content"Replaces the other files in wp-content, like must-use plugins and translations."
WordPress core"Replaces wp-admin, wp-includes and the files in the main folder. wp-config.php is never overwritten."

Preparing. First a job gets the backup ready while your site stays online: "Getting the backup ready. The restore starts as soon as it has been checked." It reads the backup's description and those of the backups it builds on, downloads the needed files from the destination if you restore from one (this needs disk space for the whole chain), checks every file's SHA-256 checksum, the signature and the encryption password. Errors stop it here, before anything changes, for example "The encryption password is wrong. Enter the password this backup was made with." or "An earlier backup that this incremental backup builds on is missing, so it can't be restored." A backup whose database doesn't fit this site is refused too: a multisite backup on a single site, a single-site backup on a network, or a network backup from another domain or path (see Multisite).

The restore page. When everything is ready, your browser opens the restore page by itself. If it doesn't (for example because you closed the tab), the job's row under Recent activity says "Ready to restore. The link works until …" and has a Continue to the restore button; the page you started from shows "The backup is ready to restore." with the same button: "The link works for one hour. Your site is in maintenance mode while the restore runs." Only the administrator who started the restore sees the button. After the hour, start the restore again.

The restore page (title Restore) shows:

  • Backup: Backup from, Site, Contains, Size, Type (for example "incremental, 4 backups in a row"), Note, Encrypted.
  • Server check: PHP, PHP extensions, Backup files, Encryption, Database (a test table is created and dropped), Folders (write permission), Disk space, Backup signature (only for unverified backups, with a confirmation) and Time limit. Problems block the start; warnings need your confirmation.
  • "Nothing has been changed yet. The restore replaces the parts listed above with the backup."
  • Buttons: Start the restore, Check again, and Cancel and go back to WordPress (removes the restore tool; nothing was changed).

Click Start the restore. The page shows Restoring with a progress bar and the steps (see What happens during a restore). "Keep this page open until it has finished. If the connection drops, open the same link again: the work continues where it stopped."

When it's done: "Your site has been restored. The backup has been restored and maintenance mode is off." with notes such as "If WordPress asks you to log in, use your login from the time of the backup." and a Go to your dashboard button. The restore tool deletes itself.

A restore link must be started within an hour. Once started, the same link can continue a stopped restore for two days.

You need a recovery link created beforehand (Recovery tab) and at least one complete backup on this server.

  1. Open the recovery link. The page Site recovery lists the backups on this server, newest first (up to 200): date, type and note, what they contain and their size. Badges: Verified (signed by this site) or Not verified, Encrypted, From … (made at another address), Files missing.
  2. Click Restore… next to the backup you want.
  3. Under What to restore, choose the parts. WordPress core files is unticked by default. Optionally tick Also remove plugin and theme files that aren't in the backup. If the backup is encrypted and the link doesn't know the password, enter the Encryption password. Click Continue (or Back to the list).
  4. The Server check runs, as for a dashboard restore. Click Start the restore (or Choose another backup).
  5. The restore first checks every backup file's checksum (Checking the backup files), then restores.
  6. When it's done: "Your site has been restored." and "Your recovery link keeps working, so keep it somewhere safe."

Things to know:

  • The link only sees backups in this server's backup folder. Packages in the import folder aren't listed.
  • The link knows the encryption password that was set when it was last updated, so you usually don't need to type it.
  • A backup made at another address gets this site's address.
  • If you enter a wrong link too often, the page is locked for 15 minutes. See The restore or installer page is locked.

On a new server: installer.php

installer.php sets up a migration package on any server, even one without WordPress. You need the package files, installer.php and the installer key. See Move to a new host for the complete steps.

If you only have regular backups at a destination (no migration package), install WordPress and this plugin on the new server at the same address as before, add the destination with the same settings, click Look for backups at destinations on the Backups tab, and restore. The new installation can't verify the old signatures, so the backups show as from another site and you confirm that you trust them. If the address is different, open Look for backups at destinations and enter the old address's folder (see After a domain change), or download the backup's files from the destination and import them under Migration → Upload from your computer.

What happens during a restore

The restore tool works through these steps, in short slices, so PHP's time limit doesn't matter:

StepWhat happens
Checking the backup filesRecovery link and installer only (the dashboard already checked them): every file's SHA-256 checksum is compared with the manifest.
Turning on maintenance modeA .maintenance file is written. "Visitors see a short "briefly unavailable" message." It's refreshed while the restore runs.
Restoring files (installer: Unpacking the files)The archives of every backup in the chain are extracted in order, full backup first. After each backup, files it recorded as deleted are removed. Only the chosen parts are written.
Removing files that aren't in the backupOnly with the "remove plugins and themes" option: files and folders in wp-content/plugins and wp-content/themes that the backup doesn't list are deleted.
Restoring the database (installer: Importing the database)The newest backup's database dump is imported table by table. With a different table prefix, the tables are renamed, and the user roles and user settings are renamed too.
Updating addresses in the databaseOnly when the address or folder changed: old addresses and folder paths are replaced (see Address replacement).
Finishing upThe installer writes wp-config.php. When the database was restored, the stored permalink rules are deleted (WordPress rebuilds them on the first visit). Maintenance mode is turned off. The restore tool removes itself (dashboard), resets itself (recovery link), or deletes the installer and package files (installer, when chosen).

The restore never extracts files outside the WordPress folder: absolute paths, .. and symbolic links in an archive are refused.

If a step fails, the page shows "This step stopped: …" with the reason and a hint, and two buttons: Try again continues where it stopped; Start this step over begins the step from scratch. Click Copy the log under Log when you contact support. The site stays in maintenance mode while the restore is paused. WordPress itself ignores a maintenance file that is more than 10 minutes old, so visitors see the site again after a while, possibly half-restored: finish or repeat the restore.

What a restore doesn't change

  • wp-config.php is never overwritten, so a restore can't lock you out of your database. The copy in the backup is only used by the installer.
  • Files created after the backup stay in place: media uploaded since, and plugins and themes added since (unless you tick the "remove plugins and themes" option).
  • Database tables that aren't in the backup (for example from a plugin installed later) stay.
  • The plugin's own backup folder, the restore and recovery tools and .maintenance are never touched.
  • Folders in the WordPress folder other than wp-admin, wp-includes and wp-content aren't in backups, so they aren't changed.
  • Restoring the database also restores this plugin's own settings, schedules and destinations as they were then. Your list of backups isn't affected, because backups are files, not database rows.

Migrating and cloning

A migration package reaches the new site in one of three ways:

WayWhen to use it
installer.phpThe new server is empty (no WordPress yet).
Pull from another site (migration link)WordPress and this plugin are installed on the new site, and the new site can reach the old one over the internet. Fastest: server to server.
Upload from your computer or Files uploaded by FTPWordPress and this plugin are installed on the new site, but it can't reach the old one (or you have the files already).

Creating the package

On the old site: Migration → Create migration package. Save the installer key right away. See Export this site.

A package contains every component, WordPress core included, and wp-config.php. It is encrypted when encryption is on in the old site's settings; then you need that password on the new site.

Importing into an existing WordPress site

  1. On the new site, install WordPress (if needed) and this plugin.
  2. Get the package there: paste the migration link under Pull from another site and click Download package, or upload the files.
  3. Under Packages ready to import, click Import, enter the encryption password if needed, tick the confirmation and click Import and replace this site.
  4. Follow the restore page to the end.
  5. Log in with a username and password from the old site.

An import replaces the database, plugins, themes, media and other content. It never touches WordPress core files or wp-config.php: the new site keeps its own database login and security keys. Use the same or a newer WordPress version on the new site as on the old one. When the package was made with a newer WordPress, the import form shows a warning before you start ("This package was made with WordPress …, and this site runs …. An import never replaces WordPress itself, so update WordPress here first, then import."), and preparing the import adds this warning to the job's log: "This package was made with WordPress …, but this site runs WordPress …. An import doesn't change WordPress itself, so plugins, themes and the database from the newer version may not work here. Update WordPress on this site first (Dashboard → Updates), then import." The import isn't stopped, so check the version before you import.

Using the installer

  1. Create an empty database on the new server, and a database user with all privileges on it.
  2. Upload installer.php and all package files to the folder where the site should live (usually the web root). The package files can also be in a subfolder named after the backup ID.
  3. Open https://your-new-site/installer.php. The page Site installer asks: Enter your installer key ("You saw this key when you created the migration package on the old site."). Wrong keys: "That key isn't right. 9 tries left before a 15-minute pause."
  4. Fill in The new site: Database host ("Often localhost."), Database name, Database user, Database password, Table prefix (filled in with the old site's prefix), Site address ("Where the new site will be. We filled in the address of this page."), and the Encryption password when the package is encrypted. Keep Delete the installer and the backup files when the site is ready (recommended) ticked. Click Check and continue.
  5. The Server check adds two checks: WordPress (the core files are in the package or already in the folder) and Existing site. If the folder already has a wp-config.php, or the database has tables with this prefix: "There is already a site here: …. Installing replaces it. Back it up first if you still need it." Tick "Yes, replace the existing site" to continue.
  6. Click Install the site. The installer checks every file, unpacks the files, imports the database, replaces the addresses and writes wp-config.php: the old site's file with the new database details (or a new one with fresh security keys when the old one isn't in the package).
  7. "Your site is ready. The files are in place, the database is imported and wp-config.php is written." Click Log in to your site and log in with a username and password of the old site.

The installer keeps its working files in a folder symelo-installer-data next to it. Once it has finished, it refuses to run again: "This installer has finished. The site has been set up. For your security the installer won't run again." Check that installer.php, the package files and that folder are gone; delete them by hand if a note says they couldn't be removed.

The installer needs PHP 7.4+, zlib, mysqli, and sodium or openssl. An encrypted package that was made where PHP has the sodium extension can only be opened where PHP has it too.

Address replacement

When the backup or package was made at another address, the old address is replaced with the new one throughout the database:

  • http:// and https:// forms, addresses without a scheme (//old.example.com), JSON-escaped (https:\/\/old.example.com) and URL-encoded forms;
  • inside serialized data (as many plugins store their options), with the string lengths corrected;
  • without changing longer addresses that merely start the same way (old.example.com.au stays as it is);
  • the WordPress address (siteurl) too when it differs from the site address, and the server folder path when the site moves to another folder.

Post GUIDs are left alone.

On a dashboard restore of your own backup, addresses are only replaced when the backup's address differs from this site's address.

After a migration

  • You log in with the old site's usernames and passwords.
  • This plugin's settings, schedules and destinations come with the database. With an import, the new site keeps its own wp-config.php security keys, so saved passwords, keys and sign-ins of the old site can't be decrypted: destinations show Needs attention or Reconnect needed ("The saved sign-in can't be read anymore (the site's security keys changed). Connect again."). Enter the values again and connect again, or remove the destinations you don't want here. Set the encryption password again. (With the installer, the old site's wp-config.php comes along, so they keep working. If both sites define the same SYMELO_BACKUPS_KEY, they keep working too.)
  • Check the Schedules tab: a clone runs the same schedules as the original, to the same destinations.
  • Backups made on this server before the import may now show as from another site. See Backups marked as from another site.
  • Create a new recovery link on the new site.

Multisite

  • A backup of a multisite network contains every site's tables and the whole uploads folder.
  • To move a network to a new domain or path, use the installer. It updates the network's main domain and path in the database and in wp-config.php: "This is a multisite network moving to a new address. The installer updates the main domain and path of the network. Sites with their own domains keep them; check them in Network Admin afterwards."
  • An import on the Migration tab, and a dashboard restore of a network backup's database, only work for a network at the same domain and path. Otherwise they're refused before anything changes, for example: "This network package was made at …, but this network is at …. An import can't move a network to another domain or path. Use the package's installer instead: it moves the network to its new address and writes a matching wp-config.php."
  • A multisite package or backup can't go into a single site, and a single-site one can't go into a network. For example: "This package comes from a multisite network, but this site is a single site. Importing it here would break the site. To move the network, use the package's installer on a new server or in an empty folder."
  • These checks only concern the database: restoring only files (plugins, themes, media, other content) is always possible.
  • The plugin has no option to move a single site into a network, or one site out of a network: backups and packages always cover the whole network.

Backups before updates

With Settings → Before updates → Back up before updates on (the default), the plugin makes a quick backup right before WordPress downloads an update:

UpdateWhat is backed up
A pluginThe database and that plugin's folder.
A themeThe database and that theme's folder.
WordPressThe database and WordPress core (wp-admin, wp-includes and the files in the main folder).

Details:

  • It works for updates you start and for automatic updates. New installs and translation updates are skipped.
  • When several plugins are updated at once, the database is backed up once, with the first one.
  • It runs in the same request as the update, within about 60 seconds in total. If it can't finish in time, or another backup is running, it's skipped and the update goes ahead. An update is never blocked. Settings → Before updates shows how the last one went.
  • These backups stay on this server; they aren't copied to destinations. They follow the encryption setting.
  • They appear in the list with the type Pre-update and a note like "Before updating the plugin Akismet". The newest 3 are kept (Keep the newest … of these backups); they don't count towards the other local backups.
  • No success email is sent for them; failures are emailed like other backups.

Undo a bad update: on the Backups tab, click Restore next to the Pre-update backup. To put back only the old plugin version, tick Plugins and untick Database. Tick Database too if the update changed the database and the new version left it in a state the old one can't use.


Encryption

What is encrypted

SettingEncryptedNot encrypted
Encrypt the databaseThe database file (….database.sql.gz.enc).File archives, file index, manifest.
Encrypt everythingThe database file, every file archive part and the file index (.enc).The manifest.

The manifest (manifest.json) is never encrypted, so the plugin can list and check backups without the password. It contains the site's name and address, the WordPress folder path, the table names with their row counts, the number and total size of files, the backup's checksums, and for incremental backups the paths of deleted files.

Files are encrypted on this server before they're uploaded, with XChaCha20-Poly1305. The key is made from your password with Argon2id when PHP has the sodium extension, or otherwise with PBKDF2-SHA256 and 600,000 rounds. Argon2id uses 64 MB of memory, or 256 MB when PHP's memory limit on the server that makes the backup is unlimited or at least 512 MB; the server that restores it needs as much. A wrong password is detected before anything is decrypted, and any change to an encrypted file is detected.

The password

  • The password is saved in the database, encrypted (see Privacy and security), so scheduled backups can encrypt without asking.
  • If you lose the password, encrypted backups can't be restored by anyone. Keep it in a password manager.
  • You need it to restore a backup on another site or server, to import an encrypted migration package, and in the installer.
  • A dashboard restore uses the saved password automatically. A restore of the database brings back the password that was saved at that time.
  • The recovery link remembers the password too.

Changing or removing the password

  • Enter a New password and Repeat it under Settings → Encryption → Change the password, then Save changes: "Encryption password saved. Keep it somewhere safe: without it, encrypted backups can't be restored."
  • "Changing it applies to new backups only: older ones still need the password they were made with." Keep the old password as long as you keep backups made with it. To restore one, enter its password in the Encryption password field of the restore form.
  • With Encrypt everything, the next incremental backup after a password change becomes a full one.
  • Remove password (in the Remove the password card) turns encryption off: "New backups are no longer encrypted. Existing encrypted backups keep needing the password, so don't forget it."
  • Don't change the password while a backup runs: "The encryption password changed while the backup was running. Please start the backup again."

Retention and disk space

Where the rules apply

RuleSet inApplies to
LocalSettings → Retention: keep the newest 5, no age limit (defaults)Every backup on this server except backups before updates: manual backups, scheduled backups, migration packages and copies made with Copy to this server.
Before updatesSettings → Before updates: keep the newest 3Pre-update backups on this server.
Per scheduleHow many to keep of each schedule: keep the newest 7 (default)That schedule's backups at each of its destinations; on this server too when the schedule has no destination. Backups found in another site's folder (see After a domain change) are never removed by it.

Rules run after each backup (the local rule, or for backups before updates their own rule, plus the schedule's rule for scheduled backups) and once a day for everything.

How the rules decide:

  • A backup is removed when it's beyond Keep the newest or older than delete them after … days. 0 means no limit for that part.
  • The newest backup a rule covers is always kept, so an age limit can't remove everything when backups stop for a while.
  • Chains are kept complete: a backup that a remaining incremental backup at the same place builds on is never removed. With incremental schedules you may therefore see more backups than the number you set, until a new full backup starts a new chain.
  • The backup that was just made is never removed by its own run.
  • Backups you start yourself and copy to destinations aren't removed at destinations by any rule. Delete them on the Backups tab when you no longer need them.
  • Migration packages count towards the local rule. Creating a package can push out an older local backup.
  • Packages in the import folder aren't covered by any rule: delete them under Migration → Packages ready to import.
  • Backups found in another site's folder at a destination (an older address, see After a domain change) are never removed automatically.

Disk space

  • Every backup is made on this server first. Expect roughly the compressed size of your site for a full backup, much less for incremental ones. Images and videos hardly compress.
  • A backup doesn't start with less than 50 MB free. Before the database and file steps it estimates the space needed; it stops when there clearly isn't enough ("There isn't enough free disk space for the file archives: at least … is needed and only … is free. Free up space or remove old backups, then try again.") and warns when it's tight ("Disk space is tight: … may need up to … and … is free. The backup continues, but it may fail if the disk fills up.").
  • Restoring from a destination downloads the needed files to this server first.
  • Uploading or pulling a package needs its size plus 50 MB free.
  • The free space is shown on the Destinations tab (This server), in Settings → Retention and in Site Health.

To free space: lower Keep the newest in Settings → Retention, delete old backups on the Backups tab, delete imported packages on the Migration tab, or exclude large folders you don't need (caches, old archives).


How-to recipes

Daily database, weekly full, to Google Drive and S3

  1. Add a Google Drive and an Amazon S3 destination and make sure both tests pass.
  2. On Schedules, add a schedule:
    • Name: "Daily database", How often: Every day, Time: 02:00.
    • What to back up: only Database. (A database-only backup is always complete on its own.)
    • Where to keep it: both destinations.
    • Keep the newest 30 backups.
  3. Add a second schedule:
    • Name: "Weekly full", How often: Every week, Day of the week: Sunday, Time: 03:30.
    • Type: Full every time.
    • What to back up: everything you need.
    • Where to keep it: both destinations. Keep the newest 8 backups.
  4. In Settings → Retention, set how many stay on this server, for example 7.

Both schedules also leave their backups on this server, where the local rule applies.

Move to a new host

The new server is empty:

  1. On the old site: Migration → Create migration package. Save the installer key.
  2. Download every package file and Installer (installer.php).
  3. On the new host: create an empty database and user, then upload installer.php and the package files to the web root.
  4. Open installer.php at the new site's address and follow Using the installer. If you keep the same domain, enter it under Site address.
  5. Point the domain to the new server if you haven't yet, log in and check the site.
  6. On the new site: check destinations and schedules, and create a new recovery link.

WordPress is already installed on the new host:

  1. Install this plugin there.
  2. On the old site: Create migration package and copy the Migration link.
  3. On the new site: Migration → Pull from another site, paste the link, Download package, then Import.

Clone production to staging

  1. On the staging site (WordPress and this plugin installed), protect it from sending email to customers. With Symelo SMTP, add define( 'SYMELO_SMTP_DELIVERY', 'log_only' ); to its wp-config.php before the import.
  2. On production: Migration → Create migration package, copy the migration link.
  3. On staging: Migration → Pull from another site, paste the link, Download package, Import.
  4. After the import, log in with your production account. On staging, open Schedules and turn off or delete the schedules you don't want there, and review Destinations. (They come from production; see After a migration.)

If staging can't reach production over the internet (for example both run on the same private network), upload the package files instead, or ask a developer about the symelo_backups_pull_allow_private_urls filter.

Restore one plugin

  • After a bad update: restore the Pre-update backup with only Plugins ticked. It contains just that plugin. See Backups before updates.
  • From a regular backup: restoring Plugins puts back every plugin as it was then, which also undoes newer updates of other plugins. To get just one plugin from an unencrypted full backup, download its Files parts, extract wp-content/plugins/plugin-name/ with an archive tool, and upload that folder by FTP.

Back up a small server gently

  1. Settings → Advanced → Speed: Gentle, for small servers.
  2. Lower Compression to 3 or 4: less CPU, slightly bigger files.
  3. Leave out what you don't need: caches, old archives, node_modules.
  4. Use an Incremental schedule at a quiet time, so most runs only save changed files.
  5. If backups still stop with "The job stopped three times in a row because PHP ran out of memory/time…", see Time and memory limits.

Keep backups mostly offsite

Every backup is made on this server first, and the plugin always keeps at least the newest one there (needed for quick restores and the recovery link).

  1. Add at least one destination and tick it in your schedules.
  2. In Settings → Retention, set Keep the newest to 1. (0 means no limit, not "none".)
  3. Use Full every time schedules if you want only one backup on this server. With incremental schedules, the current chain stays on this server until a new full backup starts.

Run backups from a system cron job

When your host blocks the site's requests to itself, or WP-Cron is turned off (DISABLE_WP_CRON), let the server's cron run the work. wp symelo-backups run starts the scheduled backups that are due, then works on the queued jobs until none are left.

For example, every 5 minutes:

*/5 * * * * cd /path/to/wordpress && wp symelo-backups run --max-seconds=270

The daily maintenance (retention, cleanup, keeping cloud sign-ins alive) still runs through WP-Cron. With WP-Cron off, add wp cron event run --due-now --quiet to the same cron job.

--max-seconds ends the run before the next cron job starts; the rest continues in the next run. wp symelo-backups run doesn't pause between steps and doesn't wait for a busy server.

Without WP-CLI, an external cron service can call POST /wp-json/symelo-backups/v1/run with an administrator's application password (see REST API). Each call starts the due schedules and works for up to 60 seconds.


Troubleshooting

Start here

  1. On the Backups tab, look at Recent activity and open View log of the failed job. The last lines usually say exactly what went wrong.
  2. Check Tools → Site Health.
  3. On the Destinations tab, click Test for each destination.

Jobs don't start or get stuck

The job stays at "Waiting to start…", or Site Health says "A backup job is stuck".

  • Only one job runs at a time. "Waiting for the job before it to finish…" means another job is still running.
  • Keep the Backups screen open for a minute: it runs steps itself. If the job moves now, the background start is blocked.
  • Common causes: a firewall or security plugin blocking requests from the site to itself, HTTP authentication on a staging site, or WP-Cron turned off. Site Health → Info → Symelo Backups and Migration → Background runner shows when the runner last ran and any error sending its request.
  • Fix: allow the site's requests to wp-admin/admin-ajax.php, or run the work from a system cron job (see Run backups from a system cron job).
  • A job you don't want any more: click Cancel on its progress card.
  • Schedules don't run at all: check that WP-Cron runs. Scheduler event under Site Health → Info → Symelo Backups and Migration should say Scheduled. Without WP-Cron, wp symelo-backups run from a system cron job starts due schedules too.
  • Run now says "A backup for this schedule is already running.": wait for that backup, or cancel it.

Time and memory limits

The plugin works in short steps and saves its place after each one. When PHP is killed during a step, the next step continues from the last saved point with shorter steps. After three interruptions in a row, the job fails with one of these messages:

MessageWhat to do
"The job stopped three times in a row because PHP ran out of memory. Ask your host to raise the PHP memory limit, or exclude very large files or folders in Settings, then try again."As it says. Very large single files are the usual cause.
"The job stopped three times in a row because PHP ran out of time. Choose the speed "Gentle, for small servers" in Settings → Advanced (it works in shorter steps), or ask your host to raise max_execution_time, then try again."As it says.
"The job stopped three times in a row before a step could finish (the server ended the request). Try the speed "Gentle, for small servers" in Settings → Advanced and check the PHP error log. Last error: …"As it says; the last error helps your host.

Not enough disk space

MessageWhat to do
"There is only … of free disk space on this server, which isn't enough to make a backup. Free up space or remove old backups first."See Disk space.
"There isn't enough free disk space for the database backup / the file archives: …"Same.
"The archive part … wasn't written completely. The disk may be full."Same.

Destination errors

MessageCause and fix
"Uploading to … failed: … The backup is still kept on this server."The backup is fine; only the copy failed. The reason follows the colon. Fix the destination and test it; the next backup copies again. Temporary problems (rate limits, server errors, network trouble) are retried automatically first.
"… isn't connected yet. Open the destination on the Destinations tab and click "Connect …"."Connect the account.
"Access to … was revoked or has expired. Reconnect … on the Destinations tab."Click Reconnect. For OneDrive, also check that the client secret hasn't expired.
"The server's host key fingerprint isn't saved yet…" / "The server's host key doesn't match the saved fingerprint…"SFTP. See SFTP.
"The server didn't accept the username and password." / "The server didn't accept the private key…"SFTP login. Check the username and the key in ~/.ssh/authorized_keys.
"Couldn't connect to … on port …. Check the server name and port, and that the server allows connections from this site's IP address."The server isn't reachable from your host. Ask both sides about firewalls.
"Enter the endpoint region as shown on the Backblaze Buckets page, for example us-west-004."B2 region.
"Request signing doesn't work on this server…"S3: contact support.
"Endpoint URL: use https://. Plain http:// is only accepted for a server in your own network…"S3-compatible storage with a custom endpoint: use the https:// address of the service.
"Tenant: enter the Directory (tenant) ID from the app's Overview page…"OneDrive: see OneDrive / Microsoft 365.
"… is …, more than the email limit of …, so it wasn't emailed…"Email. See Email.
"The email couldn't be sent: … Check this site's email setup (for example with Symelo SMTP), and that the mail server accepts attachments of this size."Email. Check the site's email setup.
"The destination "…" is turned off and was skipped."Turn it on again, or untick it in the schedule.
"A saved password or key can't be decrypted any more (the site's security keys changed). Enter it again."See The saved value can't be decrypted any more.

Backups at a destination don't show up

  • Click Look for backups at destinations on the Backups tab.
  • By default the plugin only looks in this site's folder, which is named after the site's current address (for example SymeloBackups/example.com/). After a change of address, the older backups are in the old folder: see After a domain change.
  • Google Drive only shows files the plugin itself created, with the same Google app.
  • Email can't be listed.
  • Open the log of the Destination check job under Recent activity: "The backups on … could not be listed: …" names the problem.

After a domain change

Backups at destinations are stored in a folder named after the site's address. After a move to a new domain (or a new path), new backups go to a new folder, and the older ones stay in the old one. To see them again:

  1. On the Backups tab, open Look for backups at destinations.
  2. Enter the old folder under Site folder, for example old-domain.com, or click Show the folders at my destinations and pick it.
  3. Click Look for backups.

The backups found there are added to the list. They show as from another site, so restoring them asks you to confirm, and their old address is replaced with the current one. They're downloaded from the old folder, new incremental backups never build on them, and schedule retention never deletes them: delete them yourself when you don't need them any more.

A multisite network's database can't be restored at another address this way; use a migration package's installer (see Multisite).

Backups marked as from another site

The list shows "From https://…" and restoring asks you to confirm that you trust the backup. That happens when:

  • the backup was made by another site (an import, or a destination folder shared by mistake);
  • the backup was found in the destination folder of another address, for example this site's old domain (see After a domain change);
  • the backup's manifest was changed after it was made;
  • this site's security keys changed since the backup was made: new WordPress salts in wp-config.php, adding or changing SYMELO_BACKUPS_KEY, or an import of another site's database. The plugin then can't read its signing key any more and creates a new one, so all older backups look foreign, even with this site's own address. The plugin tells you when this happens, and Tools → Site Health shows "Older backups show as made by another site".

If you know the backup is yours, tick the confirmation and restore it.

Restore problems

Message or situationWhat to do
"This backup is encrypted. Enter the password it was made with." / "The encryption password is wrong…"Enter the password that was set when the backup was made.
"An earlier backup that this incremental backup builds on is missing, so it can't be restored."A chain member was deleted. Restore the full backup of the chain, or another chain.
"This file was encrypted with Argon2id, which needs the PHP sodium extension…"Ask your host to enable the sodium extension.
"The restore tool could not be set up. Check that wp-content is writable."The restore tool is copied to wp-content. Fix the folder permissions.
"The restorer could not be started: the server answers with an error (500). The PHP error log of your hosting account shows why."The server refuses to run PHP in a new folder in wp-content. Ask your host.
A page This restore link doesn't work: "The link is wrong or incomplete, it has expired, or it was already used. A restore link has to be opened within an hour, and works for one restore only."Restore links expire after an hour if not started, and after two days once started. Go back to the Backups tab and start the restore again; if WordPress doesn't load any more, use the recovery link. A plain "Not Found" page means the restore tool has already finished and removed itself.
A page This recovery link doesn't work: "The link is wrong or incomplete, or it was replaced by a newer link or turned off."Copy the whole link again (it ends with a long code after ?key=). If WordPress still works, create a new link under Backups → Recovery; otherwise use a migration package's installer, or ask your hosting provider.
"This link can't be used. It has expired, was already used, or isn't complete…"Shown when the restore page was already open and the link stopped working. As for the pages above. On the recovery page the text says the recovery link was replaced or turned off: use the newest one from Backups → Recovery.
"This backup comes from a multisite network, but this site is a single site…" / "This backup comes from a single site, but this site is a multisite network…" / "This network backup was made at …, but this network is at …"The database doesn't fit this site. See Multisite. Restoring only files is still possible.
"A statement in the database backup is larger than this database server accepts (max_allowed_packet is … MB)."Ask your host to raise max_allowed_packet for MySQL/MariaDB.
"The database user can't create and delete tables: …"Give the database user all privileges on the database.
"The web server can't write to …"Fix the folder permissions, then click Check again.
The site still says "Briefly unavailable for scheduled maintenance"The restore stopped. Open the restore link again and click Try again, or delete the .maintenance file in the WordPress folder.

The restore or installer page is locked

After 10 wrong keys or links from the same IP address within 15 minutes (or 100 from all addresses), the page refuses further tries for 15 minutes:

  • The installer says "Too many wrong keys. For your security, try again in … minutes."
  • Restore and recovery links open a page Please wait a moment: "This page was opened with a wrong link too often, so it is locked for a while to keep your site safe." It says how long to wait, and to copy the whole link.

Wait as long as the page says and use the correct link or key. Behind a proxy or CDN, all visitors may count as one address; a wrong guess by someone else can then lock you out too. If the restore tool can't keep its count of wrong tries (for example because its folder isn't writable), it never locks anyone out.

Migration problems

MessageWhat to do
"This isn't a valid migration link. Copy the whole link from the Migration tab of the old site (it starts with "symelo-migrate:")."Copy the complete link again.
"This migration link has expired (links work for 48 hours). Click "New migration link" next to the package on the old site's Migration tab."On the old site, open the package under Migration → Packages on this server and click New migration link.
"This migration link is from this site. Paste it into the site you are moving to."Use the link on the new site.
"The other site refused the download…"The link expired or was copied incompletely. Make a New migration link on the old site.
"The package isn't on the other site anymore…"The package was deleted on the old site. Create a new package there.
"This package comes from a multisite network…" / "This package comes from a single site…" / "This network package was made at …"The package doesn't fit this site. See Multisite.
"The package could not be downloaded from the other site: …"Network problems; the pull retries several times first. Check that the new site can reach the old one, or upload the files instead.
"The server refused the upload because it is too large. Ask your host to raise upload_max_filesize and post_max_size, or upload the files by FTP."As it says.
"Your login session expired. Reload the page and choose the files again: the upload continues where it stopped."As it says.
"This package isn't complete yet. Missing: …"Upload the missing files.
"This package builds on the backup …, which isn't on this server. Upload it too."An incremental backup needs its whole chain: upload the files of every backup it builds on.
  • "The recovery files are missing or can't be written…": open any wp-admin page (the plugin sets them up again), or click Create a new link.
  • "The recovery link could not be set up: …": usually wp-content isn't writable.
  • After a change of security keys (salts or SYMELO_BACKUPS_KEY), the plugin can't update the link any more. The old link still works, but create a new one so it uses the current settings.

The saved value can't be decrypted any more

You see "The saved value can't be decrypted any more (the site's security keys changed). Enter it again." on a destination, destinations show Needs attention, or a Google Drive, Dropbox or OneDrive destination shows Reconnect needed with "The saved sign-in can't be read anymore (the site's security keys changed). Connect again."

Passwords, keys and sign-ins are encrypted with SYMELO_BACKUPS_KEY or, without it, with your site's security salts. If the key or the salts changed (some security plugins rotate salts; an import keeps the new site's salts), the old values can't be read. Enter them again, connect OAuth destinations again, and set the encryption password again. Defining a SYMELO_BACKUPS_KEY (and keeping it when you move the site) prevents this in future.

Still stuck?

Go to the Support tab, click Copy system information, and email it with a description of the problem (and the job log) to [email protected].


Privacy and security

What is stored, and where

DataWhere
Backupswp-content/uploads/symelo-backups-{random}/backups/{backup ID}/ (on multisite, in the main site's uploads folder).
Job files, logs, temporary files…/jobs/, …/logs/, …/tmp/ in the same folder. Logs and jobs are deleted after 30 days, temporary files after a day.
Uploaded and pulled packages…/import/{backup ID}/.
Recovery link configuration…/recovery/ and the recovery tool in wp-content/symelo-recovery/.
Restore toolswp-content/symelo-restore-{random}/, while a restore is prepared or running. Removed when done, or after a day without use.
Settings, schedules, destinations, OAuth sign-ins, the list of backups at destinationsOptions in the WordPress database. Passwords, keys, tokens, the encryption password and the signing key are encrypted.

The storage folder's name has a random part, and the plugin puts .htaccess, web.config and index.php files in it that block web access on Apache, LiteSpeed and IIS. Nginx ignores these files. On Nginx, block the folder in the server configuration (your host can help):

location ~ /symelo-backups- { deny all; }

Site Health checks that backups can't be downloaded from the web, whatever server you use. Downloads in the admin go through WordPress after a permission check; the storage folder is never linked.

The recovery and restore tools need the database login and the encryption password. They keep them encrypted with a key derived from the link's secret, which is never stored in a file. Access rules for Apache, LiteSpeed and IIS block everything in these folders except index.php; on Nginx the encryption protects them.

What is sent where

  • Backups go only to the destinations you set up, with the account details you entered: Google Drive (oauth2.googleapis.com, accounts.google.com, www.googleapis.com), Dropbox (www.dropbox.com, api.dropboxapi.com, content.dropboxapi.com), OneDrive (login.microsoftonline.com, graph.microsoft.com), Amazon S3 (s3.{region}.amazonaws.com), Wasabi, DigitalOcean Spaces, Scaleway, Cloudflare R2 ({account}.r2.cloudflarestorage.com), Backblaze B2 (s3.{region}.backblazeb2.com), Azure Blob Storage ({account}.blob.core.windows.net), your MinIO or other custom S3 endpoint, your SFTP or FTP server, or email through wp_mail(). Nothing is sent until you add a destination. Backups, file names and your site address (the name of the site's folder) are sent only as needed to store and list backups. Requests to S3-compatible storage, Cloudflare R2, B2 and Azure identify themselves with a SymeloBackups/<version> user agent that includes your site's address.
  • Background work: the site sends short requests to itself (wp-admin/admin-ajax.php, authenticated with a random per-site token) and uses WP-Cron. Site Health requests a test file from the backup folder.
  • Migration links: the new site downloads the package from the old site, with signed requests that expire with the link.
  • Notifications go to your notification addresses.
  • Nothing is sent to Symelo LTD.

Personal data

Backups contain your whole database: user accounts, orders, comments and everything else. Keep that in mind for data protection:

  • Store backups only where you are allowed to keep personal data, and limit how long you keep them with retention rules.
  • Deleting a user or erasing personal data in WordPress doesn't change existing backups. They disappear when retention removes them.
  • Encryption (Encrypt everything) makes stolen or leaked backups useless without the password.

Security notes

  • Every admin action checks permissions and WordPress's nonce protection. REST routes need the plugin's capability.
  • Every backup's manifest has SHA-256 checksums of its files and is signed with a key only this site knows (HMAC-SHA256). Restores check both; a backup that can't be verified needs your explicit confirmation.
  • Archives are only extracted inside the WordPress folder: absolute paths, .. and symbolic links are refused, and wp-config.php is never overwritten.
  • The database import only runs the statement types a dump needs.
  • Passwords, keys and tokens are stored encrypted, never shown again in the admin, never returned by the REST API, and removed from logs and the system information report.
  • SFTP servers are pinned by their host key fingerprint. OAuth sign-ins use your own app with PKCE.
  • The restore tool, recovery link and installer use long random keys checked in constant time, lock out repeated wrong keys, and the restore tool and installer delete themselves when done. Restore links expire after an hour if not used.
  • Migration links are signed, expire after 48 hours and only serve the files of that migration package.
  • Treat the recovery link, migration links and installer keys like passwords.

Deactivating and uninstalling

Deactivating the plugin:

  • stops schedules, backups before updates and all background work (a running job continues when you activate the plugin again);
  • leaves backups, settings, destinations and the recovery link in place. The recovery link keeps working while the plugin is inactive, because it doesn't need WordPress. That's on purpose: when a site is broken, plugins are often deactivated while you troubleshoot. Turn the link off on the Recovery tab first if you don't want that.

Deleting the plugin (Plugins → Delete):

  • Always: removes the scheduled tasks, lock files, the recovery link (its tool in wp-content and its settings) and leftover restore tools. They open a restore without a login, and nothing would look after them once the plugin is gone. After a reinstall, create a new recovery link.
  • With Settings → Advanced → Also delete its data on: also removes the settings, schedules, destinations, OAuth sign-ins, the list of backups at destinations, and the job files, logs and temporary files. On multisite, the main site's setting decides about the files.
  • Never: backups are not deleted, not on this server (the backups/ and import/ folders stay) and not at your destinations. They may be the only copy of your site.
  • With Also delete its data off (the default), everything else stays, so a reinstall picks up where you left off.

To remove everything:

  1. Delete the backups you don't need on the Backups tab, choosing every place they're stored, and the packages under Migration → Packages ready to import.
  2. Disconnect Google Drive, Dropbox and OneDrive destinations, and delete the apps you created with these providers if you don't need them.
  3. Tick Settings → Advanced → Also delete its data and click Save changes.
  4. Deactivate and delete the plugin. (The recovery link and restore tools are removed with it.)
  5. Delete the wp-content/uploads/symelo-backups-… folder by FTP.

For developers

wp-config.php constants

ConstantValuesEffect
SYMELO_BACKUPS_KEYAt least 32 random charactersKey that encrypts the stored secrets (destination passwords and keys, OAuth tokens, the encryption password, the manifest signing key) instead of a key derived from the site's security salts (wp_salt( 'secure_auth' )). Then a copy of the database alone can't reveal them. Shorter values are ignored.
SYMELO_BACKUPS_SPEEDfast, normal or gentleLocks Settings → Advanced → Speed. Invalid values mean normal.

Set SYMELO_BACKUPS_KEY when you install the plugin, and keep it when you move the site:

define( 'SYMELO_BACKUPS_KEY', '…64 random characters…' );

Adding or changing it later makes everything encrypted with the old key unreadable: re-enter destination secrets, connect OAuth destinations again, set the encryption password again and create a new recovery link. A new signing key is created too, so existing backups show as from another site.

Filters

FilterDefaultPurpose
symelo_backups_capability'manage_options' ('manage_network_options' on multisite)Capability for the screen, every admin action and the REST API.
symelo_backups_paceSee Advanced( array $profile, string $speed ). Keys: budget (seconds per step), pause (seconds between steps), max_load (load per core at which work waits; 0 = never).
symelo_backups_dispatch_argsNon-blocking POST with the runner tokenwp_remote_post() arguments of the request the site sends to itself.
symelo_backups_http_timeout60( int $seconds, string $method, string $host ). Timeout of requests to S3-compatible storage, B2 and Azure (minimum 5).
symelo_backups_ftp_timeout30FTP connection timeout in seconds (minimum 5).
symelo_backups_sftp_timeout30SFTP connection timeout in seconds (minimum 5).
symelo_backups_azure_version'2026-04-06'Azure Blob Storage REST API version.
symelo_backups_pull_request_args–( array $args, string $url ). Arguments of the requests that pull a package from another site.
symelo_backups_pull_allow_private_urlsfalse( bool $allow, string $url ). Allow pulls from private and local addresses (for example two sites on one internal network).
symelo_backups_notification–( array $mail ) with to (array), subject, body. Change or cancel (empty to) a notification email.
symelo_backups_more_from_symelo[]Products listed under "More from Symelo LTD" on the Support tab: [ [ 'title' => …, 'description' => …, 'url' => … ] ]. The card only appears when the list isn't empty.

Actions

ActionArgumentsWhen
symelo_backups_loadedPlugin $pluginThe plugin has loaded.
symelo_backups_register_destinationsRegistry $registryRegister a custom destination with $registry->add( new My_Destination() ). Destinations implement Symelo\Backups\Destinations\DestinationInterface.
symelo_backups_job_finishedarray $jobA job is done, failed or cancelled. Keys include id, type, status, options, result, error, warnings.
symelo_backups_destination_savedstring $id, string $type, bool $newA destination was added or changed.
symelo_backups_destination_deletedstring $idA destination was removed.
symelo_backups_destination_testedstring $id, true|WP_Error $resultA destination was tested.
symelo_backups_cleanupJobManager $jobsAfter the daily cleanup.

WP-CLI

CommandWhat it does
wp symelo-backups backup [--components=<list>] [--destinations=<list>] [--type=<full|incremental|auto>] [--note=<note>] [--no-wait]Makes a backup and waits until it's finished, printing the progress. Components default to the settings, destinations to this server only, type to full. --no-wait only queues it.
wp symelo-backups list [--format=<table|csv|json|yaml|ids>]Lists backups with ID, date, type, size, components, completeness, encryption, where they're stored and the note.
wp symelo-backups restore <id> [--components=<list>] [--source=<id>] [--ask-password] [--confirm-foreign] [--no-replace-urls]Prepares a restore and prints the restore page's address. Nothing changes until you open it in a browser (within an hour) and start the restore there.
wp symelo-backups run [--max-seconds=<seconds>]Starts the scheduled backups that are due, then works on queued jobs until none are left (or the time is up, minimum 10 seconds), without pauses.
wp symelo-backups schedules [--format=<format>]Lists the schedules.
wp symelo-backups destinations listLists destinations with ID, name, type, whether they're on and available.
wp symelo-backups destinations test <id>Tests a destination.
wp symelo-backups self-testChecks archives, encryption, damage detection, a database dump and import of temporary tables, search-replace and S3 request signing on this server (10 to 30 seconds).

Examples:

wp symelo-backups backup --components=database --note="Before the launch"
wp symelo-backups backup --destinations=s3-a1b2c3 --type=auto
wp symelo-backups restore 20261012-191500-full-a1b2c3 --components=plugins,themes

REST API

All routes are under /wp-json/symelo-backups/v1/ and need the plugin's capability: an administrator logged in (with a REST nonce) or using an application password. Responses never contain secrets: destination secrets only say whether they're set, and jobs leave out installer keys and migration links.

Method and routeParametersWhat it does
GET /status–Version, free space, current job, number of active jobs, last successful backup, counts, recovery status, runner times.
GET /backups–All backups, newest first.
POST /backupscomponents, destinations, type (full default, incremental, auto), note, encrypt, include_wp_configStarts a backup. Answers 202 with the job.
GET /backups/{id}–The manifest (without signature) plus locations and foreign.
DELETE /backups/{id}locations (default: everywhere)Deletes a backup in the background.
GET /backups/{id}/files/{file}–Streams a file of a backup on this server (manifest.json or a file the manifest lists). Supports HTTP Range.
GET /jobs/current–The running or next job.
GET /jobs/{id}log (bool)A job, optionally with the end of its log.
POST /jobs/{id}/cancel–Cancels a job.
POST /runseconds (5–60, default 20)Starts the scheduled backups that are due (started: schedule ID => job ID), then runs background work in this request, without pauses: an alternative to WP-CLI for external cron.
POST /restorebackup_id (required), components, source, password, replace_urls (bool or null), delete_extra, confirm_foreignPrepares a restore (a job). When it's done, result.restorer_url (for the same user) is the restore page to open within an hour.
GET /settings–All settings, without secrets (has_encryption_password instead).
POST /settingsAny setting keys; encryption_password (write-only, "" removes it)Changes only the keys you send, validated like the settings screen. A new password needs at least 8 characters, and encryption can't be turned on without a password: both answer 400 and change nothing. Removing the password turns encryption off. Returns the settings, errors (values that were left out) and messages.
GET /destinations–Destinations with their values; secrets only as set or not, plus problems.
POST /destinationsid (leave out to add), type, label, valuesAdds or changes a destination. Blank secrets keep the stored value.
DELETE /destinations/{id}–Removes a destination (backups stored there stay there).
POST /destinations/{id}/test–Tests a destination: {ok, message}.
GET /schedules–All schedules.
POST /schedulesid (leave out to add), label, enabled, frequency, time, weekday, monthday, type, full_every, components, destinations, keep, keep_daysAdds or changes a schedule. A new schedule takes what you leave out from the defaults: daily at 03:00, incremental with a full backup every 7 days, the components from the settings, this server, keep 7.
DELETE /schedules/{id}–Deletes a schedule (its backups stay).
GET /recovery–Recovery link status: enabled, created, folder_ok.
POST /recovery–Creates (or replaces) the recovery link. The response is the only place the link is shown.
DELETE /recovery–Turns the recovery link off.
POST /migration/exportencrypt, noteStarts a migration package. The response (202) is the only place with result.installer_key.
POST /migration/{id}/link–A new migration link for a package on this server: {link, expires}.
GET /migration/{id}/installer–Streams installer.php for a package.
GET /migration/imports–Packages in the import folder, with completeness and missing files.
DELETE /migration/imports/{id}–Deletes a package from the import folder.
POST /migration/pulllinkPulls a package with a migration link (a job).
POST /migration/importbackup_id, password, confirm_foreignPrepares an import (a job, like /restore).
POST /self-test–The self-test (as in WP-CLI).
GET /oauth–Public: the OAuth redirect target. It only forwards the provider's answer into wp-admin, where the administrator and the sign-in request are checked.

The migration links' download endpoint is wp-admin/admin-ajax.php?action=symelo_backups_pull. It needs no login; every request carries a signature derived from the link, and only the files of that migration package are served until the link expires.

IDs: backups {Ymd}-{His}-{type}-{random} in UTC (for example 20261012-191500-full-a1b2c3), jobs job-{Ymd}-{His}-{microseconds}-{random}, destinations {type}-{random} (for example s3-a1b2c3), schedules {frequency}-{n} (for example daily-1).

File formats

A backup is a folder backups/{id}/ on this server, and {folder}/{site}/{id}/ at destinations (the site part is the site's host, port and path, for example example.com):

FileContent
manifest.jsonThe description: site details, components, files with sizes and SHA-256 checksums, the chain, deleted paths, encryption mode and signature. Written (and uploaded) last.
{id}.database.sql.gzThe database dump (.enc when encrypted).
{id}.files.{n}.tar.gzFile archive parts, n = 1, 2, … (.enc when encrypted).
{id}.index.gzThe file index: one JSON line per file of the complete file set, with size, modification time and the backup that holds its current version (.enc when encrypted).
installer.jsonMigration packages only: the bcrypt hash of the installer key.

Details:

  • Archives are POSIX ustar .tar.gz files. Paths are relative to the WordPress folder (wp-content/uploads/2026/10/photo.jpg, wp-admin/index.php). wp-config.php is stored as symelo-meta/wp-config.php in part 1. Each part is a standalone archive.
  • The database dump is plain SQL, UTF-8, one statement per line: DROP TABLE IF EXISTS, CREATE TABLE, then INSERT statements, with the original table prefix. Binary values are written as hex. Views have no DEFINER. The last line is -- symelo:complete; a dump without it is incomplete.
  • Files are written as a series of gzip members, which standard tools read as one .gz file.
  • Encrypted files (.enc) start with the header SYMBKENC and can only be opened by the plugin, its restore tool or the installer.
  • docs/architecture.md in the plugin folder describes every format in detail.

Opening an unencrypted backup by hand:

# Files: extract every part. For an incremental backup, extract the full
# backup first, then each incremental backup in order (see "chain" in
# manifest.json), and delete the paths listed under files.deleted.
mkdir site && cd site
tar -xzf ../20261012-191500-full-a1b2c3.files.1.tar.gz

# The old wp-config.php
cat symelo-meta/wp-config.php

# Database: import the dump of the newest backup in the chain
gunzip -c ../20261012-191500-full-a1b2c3.database.sql.gz > database.sql
mysql -u dbuser -p dbname < database.sql

# File index
gunzip -c ../20261012-191500-full-a1b2c3.index.gz | head

When the site moves to another address this way, replace the addresses afterwards, for example with wp search-replace.

Scheduled tasks

HookSchedulePurpose
symelo_backups_dailyDailyApplies all retention rules; deletes finished jobs and logs older than 30 days, temporary files older than a day, unfinished backup folders older than two days, abandoned package uploads older than a week, and unused restore tools; refreshes OAuth sign-ins unused for 7 days.
symelo_backups_schedulesEvery 5 minutesStarts the schedules that are due.
symelo_backups_runnerEvery minute, only while jobs are queued or runningFallback that keeps background jobs moving.
symelo_backups_runner_nextOne-offContinues a job after a pause (Gentle speed, a busy server, or a destination that asked to retry later).

All of them are removed on deactivation.

user-guide.md