Nimble Backup

Description

Nimble Backup protects the WordPress database and wp-content with on-demand or scheduled local backups. It also includes a migration workflow for moving a WordPress site between servers without FTP.

Backup and recovery

  • Create a backup on demand.
  • Schedule daily or weekly backups.
  • Keep a configurable number of recent recovery points.
  • Build large backups in resumable chunks to reduce request-timeout and disk-I/O pressure.
  • Verify new archives before they are marked successful.
  • Download, restore or delete backups from WordPress admin.
  • Create a verified pre-restore safety point before a destructive restore. Restore stops if that safety point cannot be created.
  • Keep backup archives when the plugin is uninstalled, so removing the plugin never silently removes recovery data.

Secure local storage

New working data is stored below wp-content/uploads/nimble-backup/. Backup and migration directories receive Apache and IIS deny rules plus non-index files. Newly-created archive filenames also include a random suffix.

Nimble Backup automatically moves compatible backup archives from the legacy nimble-migration-backups directory into the new protected backup directory. Existing 1.40.x settings are migrated into the new nimble_backup_* namespace, schedules are re-armed under the new package, and public Security/Operations contracts remain compatible.

Local backups protect against application-level failures, bad updates and accidental changes. They are stored on the same server and therefore are not a substitute for an independent off-site copy if the entire server or disk is lost.

Migration

The Migration tabs create one package containing the WordPress database and wp-content, then transfer it directly from a source WordPress site to a destination WordPress site using a random, expiring token.

The destination validates the archive before extraction, rejects unsafe paths and symbolic links, and creates a verified local pre-import recovery point before overwriting existing data. The transfer token can be manually revoked as soon as the migration is complete.

Migration also supports different WordPress database table prefixes and performs serialization-safe source-to-destination URL replacement after import.

Nimble Security integration

Nimble Backup implements the public nimble_security_recovery_point_providers contract. When Nimble Security requires a recovery point before a destructive response action, Backup creates and verifies the recovery point synchronously. If it cannot do so safely, Security receives an error and can stop the destructive action.

No incident content, credentials or archive contents are exchanged through this contract. Only the recovery-point reference is returned.

Nimble Operations integration

Nimble Backup exposes its native Operations health provider through nimble_backup_operations_health contract 1.1. The provider reports aggregate backup, schedule, storage, integrity, restore and migration state without exposing archive contents, filesystem paths, credentials, destination details or transfer tokens.

Privacy

Backup archives remain on the WordPress installation. Nimble Backup does not upload backup contents to NimblePlugins.

The optional migration feature only communicates with the source site URL explicitly entered by an administrator. A short-lived token authenticates that site-to-site package transfer. No third-party NimblePlugins cloud service is required for backup, restore or migration.

Where the plugin writes

Nimble Backup keeps everything it creates in one protected folder inside the uploads directory, resolved at runtime with wp_upload_dir(): backup archives, migration packages, database dumps and working files all live under uploads/nimble-backup/. That folder is created with an .htaccess file, a web.config file and an index.php silence file, so the archives are not reachable over the web.

Restoring a backup, and completing a migration, writes files back into wp-content. That is the purpose of the plugin: a backup that cannot be restored is not a backup. The WordPress plugin guidelines allow this for backup and migration plugins, and Nimble Backup keeps that write as narrow as it can:

  • Only wp-content is ever written. The plugin does not back up or restore WordPress core, and it never writes to wp-admin, wp-includes or the site root.
  • A restore or migration only ever runs from an explicit action by a logged-in administrator, behind a capability check and a nonce. Nothing is restored automatically, on a schedule, or in the background.
  • A backup package contains exactly two things: a database dump and a copy of wp-content.
  • The plugin never writes to its own plugin folder, to other plugins’ folders or to any theme folder outside a restore.
  • The two working files a backup needs – the database dump it builds before zipping, and the directory a package is unpacked into before a restore – are both created inside uploads/nimble-backup/ and deleted when the job finishes. A database dump is data, not something the server executes; it is only ever read back statement by statement through $wpdb during a restore the administrator started.
  • When off-site storage is configured, the finished archive is also sent to the bucket you named. Nothing is read back from it automatically.

External services

Nimble Backup does not contact NimblePlugins. It sends nothing anywhere that you have not configured yourself.

Off-site storage is the one feature that contacts a service outside your own servers, and only after you enter its address and credentials:

  • What it is: any S3-compatible object storage you choose. There is no default and no suggested provider; the endpoint, bucket, region and keys are all yours to enter. Tested against Amazon S3, Backblaze B2, Wasabi, Cloudflare R2, DigitalOcean Spaces, Hetzner and MinIO.
  • What it is used for: sending a copy of each finished backup archive somewhere the server itself cannot take with it when it fails.
  • What is sent, and when: the backup archive, which contains a dump of your database and a copy of wp-content – including any personal data those hold. It is sent over HTTPS after a backup completes, whether that backup was started by hand or by the schedule. Nothing is sent when the feature is switched off, which is the default.
  • What is never sent: nothing else. No telemetry, no site identity, no usage statistics, and nothing at all to NimblePlugins.
  • Whose terms apply: the provider you chose. Their terms of service and privacy policy are the ones that govern the copy, because it is your account with them.

There are two further outbound requests, and neither involves a third party:

  • Server-to-server migration. The destination site fetches the package directly from the source site over HTTPS, using the URL and token shown on the source site’s Export tab. You type that address in yourself, so the only host contacted is the one you chose. No copy passes through NimblePlugins.
  • A loopback request to your own site. Long backups are started in the background by having the site call its own home URL, so a slow job cannot be cut short by a reverse-proxy timeout. Nothing leaves the server.

Privacy

Backup archives contain whatever your site contains, including personal data in the database. They stay on your server unless you configure off-site storage, in which case a copy also goes to the bucket you named, under your own account with that provider. The plugin sends no telemetry, no usage statistics and no file contents to NimblePlugins, ever.

The secret key for off-site storage is stored encrypted, with a key derived from this installation’s own salts. Define AUTH_KEY and AUTH_SALT in wp-config.php if they are not already: wp-config.php is never part of a backup, so the stored key then cannot be opened using the contents of an archive. Without them WordPress keeps the salts in the database, which is inside every archive. The settings screen says which of the two applies to your site.

A migration token is valid for 24 hours from the moment it is generated, after which the download endpoint refuses it. You can revoke a token at any time from the Export tab. Migration packages are not deleted automatically once transferred, so remove the package from the source site when the migration is done.

Screenshots

Installation

  1. Upload the plugin ZIP through Plugins > Add Plugin > Upload Plugin, or install it from the WordPress plugin directory when available.
  2. Activate Nimble Backup.
  3. Open the top-level Nimble Backup menu.
  4. Choose a backup schedule and retention policy, or create the first backup immediately.

If upgrading from the legacy nimble-migration-tool package: deactivate the legacy plugin first but do not delete it yet; install and activate the new nimble-backup package; open Nimble Backup once and confirm the schedule/backups are present; then delete the legacy package. Durable settings are migrated to nimble_backup_*, so the legacy uninstaller cannot reset the new plugin.

FAQ

What does a backup contain?

The WordPress database and the site’s wp-content tree, excluding Nimble Backup’s own temporary/archive storage and common cache/backup working directories.

Does it support WordPress Multisite?

Not in 1.41.0. Backup, restore and migration are deliberately disabled on Multisite until network-wide database and shared wp-content restore semantics can be guaranteed safely.

Does it back up wp-config.php or server configuration?

No. wp-config.php, web-server configuration, PHP configuration and files outside wp-content are not included. Keep infrastructure secrets and server configuration in your normal hosting or infrastructure backup process.

Are backups stored off-site?

Only if you set it up. By default everything stays on this server. Under Backup / Restore there is an “Off-site storage” section where you can enter an S3-compatible bucket of your own — Amazon S3, Backblaze B2, Wasabi, Cloudflare R2, DigitalOcean Spaces, Hetzner, or your own MinIO — and each finished archive is then uploaded there as well. The credentials are yours and the bucket is yours; nothing passes through NimblePlugins.

A copy on the same server protects you from a mistake. Only a copy somewhere else protects you from the server going away, which is the failure a backup exists for.

Can I migrate between sites with different database table prefixes?

Yes. Current-format packages include the source prefix, and the importer rewrites dump table identifiers to the destination prefix and repairs WordPress prefix-dependent option/usermeta keys.

Does migration overwrite the destination?

Yes. Migration is intentionally destructive. Nimble Backup first creates a verified pre-import recovery point and stops if that safety point cannot be created.

What happens when I uninstall the plugin?

Plugin settings and scheduled hooks are removed, but backup archives are intentionally retained. Recovery data should never disappear merely because the plugin is removed.

Reviews

There are no reviews for this plugin.

Contributors & Developers

“Nimble Backup” is open source software. The following people have contributed to this plugin.

Contributors

Translate “Nimble Backup” into your language.

Interested in development?

Browse the code, check out the SVN repository, or subscribe to the development log by RSS.

Changelog

1.44.1

  • PHP execution limits are no longer set to unlimited. A backup, restore, export or import now raises the limit to a bounded 900 seconds, and only when the host allows it and the current limit is lower; memory is raised with wp_raise_memory_limit() instead of ini_set().
  • A restore or a migration import no longer unpacks the archive to a folder first. The database dump is streamed out on its own, and everything under wp-content is streamed from the archive straight to its final path, so no plugin or theme source is ever written to the uploads folder in between. Every path in the archive is checked before a single byte is written, and a short write is now detected instead of being counted as a success.

1.44.0

  • Off-site storage. Each finished backup can be uploaded to an S3-compatible bucket of your own – Amazon S3, Backblaze B2, Wasabi, Cloudflare R2, DigitalOcean Spaces, Hetzner, or your own MinIO. Switched off until you enter a bucket and credentials. A backup on the same server shares that server’s bad days; this is the copy that does not.
  • The upload is part of the same paced batch process the archive is built with, so a multi-gigabyte archive is sent a piece at a time instead of in one request that a host would cut short. An interrupted upload resumes from the piece it reached rather than starting over, and an upload that cannot be finished is cancelled at the provider – an abandoned multipart upload keeps billing for the pieces already sent, and does not show up in a listing.
  • A failing upload gives up after five attempts instead of retrying for ever. A rotated key or a deleted bucket would otherwise have left the backup permanently “running”, and a run in progress blocks the next one – every later scheduled backup would have been skipped in silence.
  • A failed upload never invalidates the backup. The archive is on disk and verified, so it is recorded as the success it is, with the off-site failure reported separately.
  • Remote copies follow the same retention count as local ones, and only ever delete archives this plugin wrote. Object storage is billed by the gigabyte-month, and a nightly backup that is never pruned becomes a bill nobody is watching.
  • The secret key is stored encrypted, never rendered back into the page, and can be removed by clearing the field. The settings screen says whether this installation keeps its salts in wp-config.php, where a backup cannot reach them.
  • “Test the connection” proves the credentials before a backup depends on them, rather than finding out at three in the morning after the archive is built.

1.43.0

  • Every declaration, hook and stored name now carries the full nimble_backup / Nimble_Backup_ / NIMBLE_BACKUP_ prefix. The short NMT_, NB_ and nmt_ names are gone. Settings saved by earlier versions are migrated automatically, and cron events scheduled under the old hook names are still picked up.
  • Uploaded migration packages go through wp_handle_upload() instead of move_uploaded_file(), with the upload directed at the plugin’s own protected folder and restricted to zip files.
  • Restoring a database dump now runs through $wpdb->query() rather than the raw mysqli handle. Checked against WordPress core: wpdb::query() neither adds nor removes placeholder escapes, so the “%” corruption the raw handle was meant to avoid was never caused by it. The repair tool stays for sites damaged by versions before 1.41.
  • A restore no longer activates or deactivates anything. It only rewrites the plugin’s own entry in the active list when the restored database still names the 1.40.x folder, so an administrator’s existing choice survives the rename.
  • A restore now stops at the first statement the database refuses, and names the table, instead of running the rest of the dump into a database that is already half replaced.
  • The options cache is flushed the moment a database import finishes. Without it every option read for the rest of that request still answered with the values from before the restore.
  • Other plugins can no longer touch a restore or a package upload in flight: the query filter is lifted for the duration of the import, and the upload filters that media-offload plugins use are lifted while the package is stored, so a database archive is never copied to third-party storage.
  • An uploaded package keeps a high-entropy filename, and is deleted on every failure path, not just some of them.
  • While the legacy 1.40.x package is active this one stands down and says so, whichever of the two WordPress loads first.

1.42.4

  • Screenshot captions in the readme now describe the three screens the plugin actually has. No code changes.

1.42.3

  • Documents where the plugin writes: everything it creates stays in a protected folder inside the uploads directory, and the only write outside it is restoring wp-content, which is what a backup plugin is for.
  • No functional changes.

1.42.2

  • Moves the admin stylesheet and script into real files loaded through wp_enqueue_style() and wp_enqueue_script() instead of being printed inline on the page.
  • No backup, restore or migration behaviour changes.

1.42.1

  • Documents why the server-to-server download endpoint has no nonce: the caller is another site rather than a browser session, and authentication is a random expiring token compared with hash_equals(). The existing annotation sat one line below the line that needed it.
  • Documents the usermeta prefix rewrite during migration, where meta_key is the column being written rather than a query argument.
  • No behaviour change.

1.42.0

  • Removes the cross-promotion sidebar. It accounted for 94 percent of the plugin’s download size: 3.98 MB of images against 216 KB of code. The package is now 240 KB.
  • Internationalises the interface. 89 previously untranslated strings now use the standard WordPress translation functions, and the plugin ships a .pot file for the first time.
  • Documents the two outbound requests the plugin makes, neither of which involves a third party, and adds External services and Privacy sections to the readme.
  • Corrects the Contributors username.

1.41.2

  • The admin header mark was an inline SVG drawn in PHP with no class names; it now uses the
    shipped brand file like every other surface.
  • The three cross-product promo images carried the old mark baked in. Each now shows the
    promoted product’s own colour.
  • Replaces the placeholder mark with the real Nimble logo across the plugin, in the
    product’s own colour so the WordPress admin menu stays readable when several
    Nimble plugins are installed side by side.
  • No behaviour change.

1.41.0

  • Renamed the install package and plugin root to nimble-backup/nimble-backup.php.
  • Migrates durable 1.40.x settings into the nimble_backup_* namespace so deleting the legacy package cannot reset the new plugin.
  • Moves primary cron workers to nimble_backup_* hooks while retaining legacy action aliases for compatibility.
  • Preserves legacy nmt_* admin/action aliases and the public Security/Operations contracts while moving persistent runtime state to the new namespace.
  • Moves new private working data below uploads/nimble-backup/ and adds Apache/IIS deny files plus randomized archive filenames.
  • Migrates compatible legacy backup archives into the new protected backup directory.
  • Validates migration and restore ZIP files before extraction, rejecting unsafe paths, unexpected top-level entries and symbolic links.
  • Adds verified archive metadata and only marks new backups successful after ZIP/manifest/database validation.
  • Creates a verified safety recovery point before restore and migration import and stops destructive work if that point cannot be created.
  • Fixes destination URL capture so migration URL replacement uses the real destination URL even after the source database has been imported.
  • Adds migration support for differing WordPress database table prefixes.
  • Sends the migration token in a request header on new transfers while retaining legacy query-token compatibility on the source endpoint.
  • Adds a one-click transfer-token/package revoke action.
  • Fixes top-level admin navigation so Backup, Export and Import use the real admin.php?page=nimble-backup route.
  • Records migration success/failure telemetry for the existing Operations 1.1 health provider.
  • Keeps the Nimble Security recovery-point provider contract intact and fail-closed.
  • Fails closed on WordPress Multisite instead of exposing unsafe network-wide restore/migration behavior.

1.40.2

  • Keeps the Nimble Security recovery-point provider registered while Backup is temporarily running, continuing or locked.
  • Separates durable provider capability from per-request readiness so Operations no longer reports a false missing-provider issue during normal backup activity.
  • Preserves the fail-closed response gate while Backup is busy.

1.40.1

  • Registers Nimble Backup through the public Nimble Security recovery-point provider contract.
  • Creates and verifies a complete local recovery point before Security may continue destructive automatic quarantine.
  • Refuses the recovery request when storage, ZipArchive or backup concurrency is unsafe.

1.40.0

  • Moves Nimble Backup to its own top-level admin menu.

1.39.0

  • Adds the Operations native health provider contract 1.1 and privacy-bounded backup/restore outcome telemetry.