BackupWallby PortWall
RestoreUpdated 2026-11-16

How do I read my backups without BackupWall?

Use bw-extract, a single Python file that reads a destination directly, read-only, and writes plain files, database dumps and mail. It needs no BackupWall database, services or panel, only Python 3.9 or newer, and the master key if the job was encrypted.

What bw-extract is

Your backups do not depend on BackupWall being installed or working. If the server is gone, the console will not start, or you want your data somewhere else, bw-extract reads a destination directly:

  • No BackupWall database, no queue, no services, no panel.
  • One Python file, Python 3.9 or newer. It ships in the release as backend/scripts/bw-extract.py; an installed server has it as bw-extract (/usr/local/bin/bw-extract).
  • Read-only: it never writes, renames or deletes anything on the destination.
  • The format it reads is documented, so a backup stays readable without the tool.
  • Memory stays small whatever the size of the backup: everything is streamed.

On a BackupWall server run bw-extract --help. Anywhere else, copy the one file and run python3 bw-extract.py.

What else it needs

Case Needs
zstd-compressed objects (almost every backup) the zstandard module, or the zstd command (dnf install zstd or apt install zstd)
The job had Encrypt backup data on the cryptography module (dnf install python3-cryptography or apt install python3-cryptography)
S3, Wasabi, B2, GCS (HMAC) nothing (a built-in client); boto3 is used when installed
SFTP the paramiko module (pip install paramiko), or mount the server with sshfs and use --local

Google Drive, OneDrive and native Google Cloud Storage destinations: copy the BackupWall folder or bucket prefix to a local disk with rclone, then use --local.

Point it at the destination

Destination Options
Local directory --local /var/lib/backupwall/backups (the destination's root path)
S3 / Wasabi / B2 / MinIO --s3 BUCKET --prefix 'PREFIX' --endpoint URL --region REGION --s3-credentials keys.json
GCS through an HMAC key --s3 BUCKET --prefix 'PREFIX' --endpoint https://storage.googleapis.com --s3-credentials hmac.json
SFTP --sftp user@host[:port] --sftp-path /remote/path --ssh-key ~/.ssh/id_ed25519

Use --prefix exactly as it is set on the destination; on S3 the prefix is used verbatim. --s3-credentials takes a JSON file (access_key_id and secret_access_key), AWS_ACCESS_KEY_ID= lines, or two lines (key id, then secret); or set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. SFTP checks the host key against known_hosts; a password goes in --sftp-password-file or BW_SFTP_PASSWORD.

Encrypted backups: give it the master key

If the job had Encrypt backup data on, you need the master key of the server that made the backup. Either:

  • --key-file /etc/backupwall/backupwall.env (the old server's file, or any file holding MASTER_ENCRYPTION_KEY_B64=..., or just the key), or
  • --dr-bundle backupwall-dr-....bwdr (from the destination under dr/<server>/) and its passphrase: --passphrase-file FILE, BW_DR_PASSPHRASE, or it asks.

Without the key an encrypted backup cannot be read by anyone, PortWall included.

Find, look and extract

D="--local /var/lib/backupwall/backups"        # or the S3 / SFTP options

bw-extract $D list-points                      # every point: id, date, accounts, files, size
bw-extract $D list-accounts latest -l          # accounts of the newest point
bw-extract $D ls 8505c302 alice public_html    # a directory of alice's backup
bw-extract $D extract 8505c302 alice --to /root/restore/alice
bw-extract $D extract 8505c302 alice public_html/wp-content --to /root/out
bw-extract $D extract-db 8505c302 alice alice_wp --to /root/alice_wp.sql.gz
bw-extract $D extras 8505c302 alice --to /root/alice-extras
bw-extract $D verify 8505c302 --deep
  • A point is its id, a unique start of it, or latest.
  • extract restores files with their mode, mtime, symlinks and directories, and as root their owner (by name, when the user exists on the machine). It writes into an empty directory unless you pass --overwrite, never through a symlink and never into the destination itself. Every object is checked against its hash. A damaged file is reported and not written (--force writes it anyway for salvage).
  • extract-db writes the dump as stored: .sql.gz from mysqldump | gzip, or a MongoDB mongodump --archive --gzip file. Load one with gunzip -c alice_wp.sql.gz | mysql alice_wp.
  • extras writes DNS zone files, SSL certificates and keys, the crontab, FTP and database-user records, each mailbox as a Maildir tar, and the cPanel account archive (cpmove-<user>.tar.gz, for /scripts/restorepkg). It holds private keys and password hashes: keep it private.
  • verify checks every object is there; --deep reads everything back (it downloads the whole point).
  • Exit codes: 0 all good, 1 something failed or is damaged, 2 wrong usage or a missing key, 3 the destination cannot be read.

What it does not do

It does not import databases, recreate panel accounts or send mail. It gives you the files. To restore into a panel, install BackupWall (or use bw-dr-restore with a DR bundle) and restore from the console. Which job made a point, and whether it was completed or partial, lives in BackupWall's database, not on the destination.

Still stuck? Open a ticket at portwall.net/billing or write to [email protected], and attach a support bundle. See Report a problem and make a support bundle.