Skip to content

Powered by Grav

Disaster-proof access to your off-site backups

Disaster-proof access to your off-site backups

Availability: hosted accounts and PRO-licensed servers. This page is about the extended off-site backup subsystem — the one included with every hosted BOA account and unlocked on self-hosted servers by a BOA PRO licence (see Off-site backups & mybackup). If you self-host without PRO and use the legacy backboa tool instead, the same Duplicity principles apply but the paths and names differ — that tool is covered in the operator documentation, and you're expected to be comfortable adapting what follows yourself.

The mybackup restore tool is the easy way to pull your off-site backups back — but it runs on the server. That's fine for the everyday "I deleted a folder" case. It's not enough for the case off-site backups really exist for: the day the server itself is gone, or unreachable, or you simply want your data back without depending on anyone's infrastructure.

The good news is that BOA's off-site backups are built for exactly that day. They are ordinary Duplicity archives — an open, widely packaged backup format — sitting in your own cloud storage bucket, encrypted with a passphrase. Nothing about reading them requires BOA, Ægir, or the server they came from, and you don't need to have ever used Duplicity before: this page assumes no prior knowledge and works from a MacBook, a Windows PC, or any Linux machine, one copy-paste block at a time.

To open the backups you need exactly three things:

  1. The backups themselves — already in your own bucket, at your own provider (Backblaze B2, Amazon S3, Wasabi, and so on).
  2. Your storage credentials — the same keys you put into your credentials file when you set up off-site backups. You had them once; part of this page is making sure you still have them off the server.
  3. The encryption passphrase — the one piece you don't have yet, because BOA generates and guards it on the server. Getting it is one support request, covered below.

This page walks through all three, ending with the fire drill — a ten-minute test from your own computer that proves, today, that you could recover everything tomorrow.

The short version

If you stop reading after this list, you have the whole plan:

  1. Ask your host for your backup passphrase — one support request. They place a copy in your account, you download it and store it in your password manager together with your storage keys and bucket name.
  2. Install Duplicity on the machine you trust — your Mac, your Windows PC (via WSL), or any Linux box.
  3. Download the boa-restore helper, fill in its one config file, and it drives Duplicity for you — the same feel as mybackup on the server, just local.
  4. Run the fire drill nowbash ~/boa-restore check plus one small test restore — so the first time you do this isn't during a disaster.

What you're actually holding

It helps to know what's in the bucket, because it explains why this works so cleanly:

  • The backups are standard Duplicity archives: chains of encrypted volumes (about 300 MB each), starting with a full copy every 28 days by default and topped up with an incremental on every backup cycle — which runs every six hours by default, so expect several incrementals per day when you look at the chain.
  • Encryption is Duplicity's default GnuPG symmetric encryption: one passphrase both locks and unlocks everything. There is no key file, no certificate, no BOA-specific wrapping — the passphrase alone is the key.
  • Your account has one passphrase per server, generated once (a single line of 44 random characters) and never rotated while your account stays on that server. The same passphrase covers every provider you back up to. If your account is ever migrated to a different server, the new server mints a new passphrase and, because the bucket name embeds the server's hostname, backups start landing in a new bucket — so after a migration, repeat Step 1 and keep the old entry in your password manager until the old bucket's history has aged out.
  • What's inside is your static/ tree, your platforms/ and distro/ codebases, and your FTP home — minus scratch folders — exactly as described under what goes off-site by default. That includes your nightly database dumps (static/files/dbackup/ rides along), so the bucket carries both the files and the databases of your sites. Note the asymmetry: files go off-site every few hours, database dumps are made nightly and kept for around 14 days locally — so the newest dump can be up to a day older than the files beside it, and a restore from further back than two weeks will find files but no matching dump. The backup archives made by Ægir's own Backup task (your ~/backups folder) are not in the off-site set — the dbackup/ dumps are your database half.

What the bucket is not: a browsable copy of your folders. If you look at it in your provider's console you'll see opaque duplicity-full.* and duplicity-inc.* volume files. That's expected — Duplicity is the tool that turns them back into your files.

Step 1 — get your passphrase from your host

The passphrase lives on the server at /data/disk/<your-account>/remote_backups/.secret.txt, owned by root — your login has no routine way to read it, and nothing you do day to day needs it, because both the scheduled backups and mybackup read it server-side. For independent access, though, you need a copy in your hands.

That's a one-line support request to your host — worded so it can be done in one round trip:

Please copy (don't move) my off-site backup passphrase file remote_backups/.secret.txt to ~/static/control/remote_backups/credentials/.secret.txt, owned by my account's .ftp user with mode 600, so I can download it for disaster-recovery purposes.

The credentials/ folder is the right landing spot because it's the same locked-down folder that already holds your cloud storage keys — the copy is protected exactly as well as the keys next to it while it waits for you.

Once it appears (it's a single line of 44 characters), from your own computer:

  1. Download it over SFTP — the same login and client you already use for your files (see Connecting to your account).
  2. Store it in your password manager, as the "off-site backup passphrase" entry for this account — and put your storage access key and secret and your bucket name (next section) in the same entry. On the disaster day the server holds the only other copy of all three, which is exactly why they need a home elsewhere. When pasting the passphrase, take the 44 characters only — the file ends with a line-break that is not part of the passphrase. A printed copy in a safe place is a reasonable extra for something this important.
  3. Delete the copy from your account once it's safely stored, and check it's gone:
SH
rm -f ~/static/control/remote_backups/credentials/.secret.txt
ls -la ~/static/control/remote_backups/credentials/

Do the download-and-delete the same day the host places the file: while the copy sits in your account it's readable by anyone holding your account login. (A scheduled backup cycle may capture the copy into the archive before you delete it — that particular copy is harmless, since the archive is locked with the very passphrase inside it.)

Treat the passphrase like the master key it is: anyone holding it plus your storage credentials can read all your backups, and there is no reset — a lost passphrase means the off-site copies can't be opened by anyone, including your host.

Step 2 — a machine with Duplicity

Any machine you trust will do: your own computer, or a small VM at a different provider than your hosting (that's the fully disaster-proof arrangement — no shared failure with the server or with the storage).

One rule before the per-system steps: the commands on this page need Duplicity 2.0 or newer — 3.x ideally, which is what the server writes with. After installing, always run:

SH
duplicity --version

If it prints 0.8 or older, don't use that build — install via pipx instead (last option below).

  • macOS. Open the Terminal app (Applications → Utilities). If you don't have Homebrew yet, install it first with the one-line command on that page, then:
SH
brew install duplicity

That currently gives you Duplicity 3.x with everything it needs, including GnuPG and the Backblaze/S3 libraries.

  • Windows. There is no native Windows build of Duplicity — but Windows can run the Linux one in a couple of clicks via WSL (Windows Subsystem for Linux, Microsoft's built-in Linux layer). Open PowerShell as Administrator and run:
POWERSHELL
wsl --install

Reboot when asked, let Ubuntu finish setting up (it asks you to pick a username and password), and you have a Linux terminal — everything on the rest of this page happens inside it, starting with the Linux install command below. One handy path to know: inside WSL, your Windows C: drive is /mnt/c, so restoring into /mnt/c/Users/Public/restored puts the files where Windows Explorer can see them.

  • Linux (including inside WSL). On Debian-family systems (Debian/Devuan/Ubuntu):
SH
sudo apt update && sudo apt install duplicity python3-b2sdk python3-boto3

then check the version as above — current releases ship Duplicity 2.x/3.x, but older ones (Debian 12, Ubuntu 22.04 and their derivatives) still package 0.8.x, which is too old for these commands.

  • Any system, newest version (and the fallback whenever the version check fails): install pipx from your package manager (sudo apt install pipx / brew install pipx), then:
SH
pipx install duplicity

Duplicity's own package pulls in every backend library with it, so there's nothing else to add.

Two named tools, so there's no confusion:

  • Duplicati — despite the near-identical name, a completely different program with an incompatible format. It cannot read these backups.
  • Déjà Dup — a GNOME desktop front-end that genuinely wraps Duplicity, but current releases no longer talk to S3/B2 storage directly. The command line below works everywhere, so it's what this page documents.

Step 3 — the boa-restore helper

You don't have to learn Duplicity's command line: the boa-restore helper wraps it for you — the same feel as running mybackup on the server, just on your own machine, and just as strictly read-only: its only verbs look at backups and restore from them; it physically cannot create, prune or damage anything in your bucket.

Download it (one file, no installation):

SH
curl -fsSL https://raw.githubusercontent.com/omega8cc/boa-restore/main/boa-restore -o ~/boa-restore

Create its config template:

SH
bash ~/boa-restore setup

That writes ~/.boa-restore/config.txt with the instructions inside. Filling it in is deliberately copy-paste work:

  • three values you already know — your service (b2, wasabi, aws, ...), your account name and your server hostname (both read straight off your control-panel address: signing in at o123.fr8.eu.aegir.cc means account o123, server fr8.eu.aegir.cc) — the helper derives the bucket name from them for you;
  • your provider credential lines, pasted exactly as they appear in your server-side ~/static/control/remote_backups/credentials/<service>.txt file — the helper reads the same variable names, so download that file over SFTP and copy its export lines over unchanged;
  • your passphrase (Step 1), saved as the single line of ~/.boa-restore/.secret.txt.

Then everything on this page is one short command each:

SH
bash ~/boa-restore check

proves the whole chain — Duplicity version, credentials, bucket name and passphrase — and tells you in plain words what to fix if something's off.

SH
bash ~/boa-restore list

lists every file in the newest backup, and

SH
bash ~/boa-restore restore
bash ~/boa-restore restore data/disk/<your-account>/static/projects
bash ~/boa-restore restore data/disk/<your-account>/static/projects 7D

restores everything, one folder, or one folder as it was a week ago — always into a fresh timestamped folder under ~/boa-restored/, never over anything you already have. The helper bakes in the details the rest of this page explains (the ownership flag, the private metadata cache, percent-encoding, the Amazon tier bucket suffixes, the S3-compatible endpoints for Google Cloud Storage and IBM COS), and it covers every supported provider — so if you're happy to treat it as a black box, you can skip straight to the fire drill now.

Doing it by hand — Duplicity directly

Prefer to see the machinery, or need something the helper doesn't cover? Everything it does amounts to a few environment variables and a target URL. Three pieces of information, all now in your password manager:

The passphrase — Duplicity reads it from the PASSPHRASE environment variable. Set it without it appearing on screen or in your command history (this works in bash and zsh, the default shells everywhere Step 2 lands you):

SH
read -rs PASSPHRASE && export PASSPHRASE

The prompt stays completely blank while you paste — that's intentional. Paste the passphrase, press Enter, and it's set for this terminal session. (If you skip this, Duplicity simply asks for the passphrase interactively — that works too.)

Your storage credentials — the same values you put in ~/static/control/remote_backups/credentials/<service>.txt on the server. How they're handed to Duplicity differs per provider — worked examples below.

The bucket name — BOA derives it as back-to-USER-HOSTNAME-PROVIDER, where the hostname's dots and the provider key's underscores each become hyphens. The bucket name section of the mybackup page shows how to read yours off your control-panel address — or simply look in your provider's console: the bucket is sitting right there, and copying the name from the console is the safest way to get it exactly right.

Worked example: Backblaze B2

The B2 target URL carries your B2_ACCOUNT_ID (from your b2.txt credentials file); the application key is supplied separately, the same way as the passphrase, so it never lands in your command history:

SH
read -rs BACKEND_PASSWORD && export BACKEND_PASSWORD

(paste your B2_APPLICATION_KEY at the blank prompt), then:

SH
duplicity collection-status "b2://<B2_ACCOUNT_ID>@back-to-o123-fr8-eu-aegir-cc-b2"

with your own account id and bucket name. (The key can also be embedded in the URL after a colon — b2://<id>:<key>@<bucket> is the form BOA itself uses server-side — but then it shows up in your shell history, so prefer the prompt.)

Worked example: Amazon S3

The S3 backend takes the keys from the standard AWS environment variables instead of the URL:

SH
export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."
duplicity collection-status \
  --s3-endpoint-url https://s3.dualstack.eu-central-1.amazonaws.com \
  --s3-region-name eu-central-1 \
  "boto3+s3://back-to-o123-fr8-eu-aegir-cc-aws"

with your own region in both flags. If your credentials file is aws_one_zone.txt or aws_standard_ia.txt rather than aws.txt, your bucket ends in -aws-one-zone or -aws-standard-ia accordingly — the service key with underscores turned into hyphens.

Every other provider

The exact target URL form BOA itself uses for every supported provider is tabulated in Backup regions, bucket names & target URLs. For most of them — Wasabi, DigitalOcean Spaces, Cloudflare R2, Linode — the key and secret go inside the target URL rather than into environment variables: substitute your own values into the URL shape from that table (the variable names in your BOA credentials file are BOA's own bookkeeping — Duplicity never reads them). If a key contains characters other than letters and digits, percent-encode them in the URL (a / becomes %2F, a + becomes %2B; BOA percent-encodes these values server-side for the same reason). Azure additionally wants AZURE_STORAGE_KEY exported alongside the account name in the URL. Google Cloud Storage and IBM COS work exactly like the Amazon S3 example above — export the HMAC key pair from your credentials file as AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY, keep the boto3+s3://<bucket> target, and set the endpoint flag to --s3-endpoint-url https://storage.googleapis.com for GCS (no region flag needed) or --s3-endpoint-url https://s3.<region>.cloud-object-storage.appdomain.cloud for IBM COS.

Listing and restoring

The first command you run against the bucket makes Duplicity download the archive metadata into a local cache (~/.cache/duplicity/) — on a large backup set that first contact can take a few minutes; it's much quicker after that. Worth knowing: the cache holds a decrypted index of your file names and sizes (not their contents), so on a machine that isn't yours to keep, point it somewhere disposable with --archive-dir /some/path and delete it when you're done.

See the chain — how many full and incremental backups exist, and from when:

SH
duplicity collection-status "<target-url>"

See the files in the most recent backup:

SH
duplicity list-current-files "<target-url>"

One thing will look unfamiliar: the paths. Backups are taken relative to the server's filesystem root, so everything appears as data/disk/<your-account>/... (your static files, platforms and distro folders) and home/<your-account>.ftp/... (your FTP home) — no leading slash. Those are the paths you feed to --path-to-restore.

Restore everything into a new, empty folder on your machine:

SH
duplicity restore --no-restore-ownership "<target-url>" ~/restored-account

The --no-restore-ownership flag matters on every restore here: the archive records the server's file owners, which your own machine neither knows nor lets you set — this flag tells Duplicity to make the files yours instead of trying (it's the same flag mybackup uses server-side).

Restore one folder — say, your static/projects:

SH
duplicity restore --no-restore-ownership \
  --path-to-restore data/disk/<your-account>/static/projects \
  "<target-url>" ~/restored-projects

Restore from a point in time--time takes an interval (7D, 2W, 1M) or a date (2026-08-01):

SH
duplicity restore --no-restore-ownership --time 7D \
  --path-to-restore data/disk/<your-account>/static/projects \
  "<target-url>" ~/restored-projects

Duplicity won't overwrite existing files, so always restore into a fresh directory and move things where you want them afterwards.

Two things to keep in mind about what comes back:

  • A full restore includes your static/control/remote_backups/ credentials files and your sites' settings.php files — your cloud keys and database credentials, in plain text. Restore onto a machine you control, and wipe the directory when a test is done.
  • What you're holding afterwards is the pieces of your sites — the files, the codebases, and the recent database dumps under static/files/dbackup/. Turning those pieces back into a running site on another host is exactly the territory of Exporting your site — its three-pieces model applies unchanged; you've just sourced the pieces from the bucket instead of the live server.

Read, don't write. On the day you actually need this, the bucket is the only copy left — treat it as untouchable. From your own machine, stick to collection-status, list-current-files and restore: none of them modify the backup chain. Never run duplicity backup, cleanup, remove-older-than, remove-all-but-n-full or remove-all-inc-of-but-n-full against your bucket — those delete or reshape backup sets permanently, with no undo, and the server (if it's still alive) maintains the chain and will be confused by a second writer. One caveat even on the read side: with several providers (B2 among them) a mistyped bucket name is silently created as a new empty bucket, and the command then reports no backups found instead of an error — so if you ever see "no backup chains found", suspect a typo in the bucket name first, and prefer copy-pasting the name from your provider's console.

The fire drill

A backup you've never test-restored is a hope, not a plan. Everything above works while the server is perfectly healthy — which is exactly when you should prove it:

  1. Get the passphrase, your storage key and secret, and your bucket name into your password manager (Step 1) now, not after the disaster. The passphrase is the piece that can never be recovered or reset once the server is gone; the storage keys you could re-mint in your provider's console, and the bucket name you could look up there — but having all three in one place is what makes the drill (and the real thing) a ten-minute job.
  2. From your own machine, run bash ~/boa-restore check (or the manual duplicity collection-status). Success proves your credentials work, the bucket name is right, the passphrase decrypts (the metadata is encrypted too), and the backups are arriving on schedule.
  3. Run bash ~/boa-restore list and spot-check that your sites' folders and recent dbackup dumps are in the list.
  4. Restore one small folder and open a file. That's the only step that proves an actual data volume decrypts and restores — which is why it's not optional. Now it's a plan.

Repeat the drill whenever something in the chain changes — you rotated a storage key or switched provider — and once in a while regardless; each run costs a minute and a few megabytes of download. If your account is migrated to a different server, treat that as a full reset: new passphrase to request, new bucket name to record, and the old entry kept until the old bucket's history has aged past its retention window.

If something doesn't work

(boa-restore check diagnoses most of these for you and says so in its own output — this list is the same knowledge for the manual route.)

  • "GPG error" / "bad session key" / decryption failure — almost always a mangled passphrase: a stray space or line-break pasted along with it, or a truncated copy. Re-copy all 44 characters, nothing more.
  • "No backup chains found" — almost always a mistyped bucket name (see the warning above — the typo may even have created an empty bucket). Copy the exact name from your provider's console. On Amazon, also check you used the right tier suffix (-aws, -aws-one-zone, -aws-standard-ia).
  • A flood of permission or ownership errors during restore — you forgot --no-restore-ownership.
  • "No such option" on a documented flag — your Duplicity is older than 2.0 (the version check in Step 2). Install via pipx instead.
  • Authentication errors — re-check which mechanism your provider uses (in-URL vs environment variables, above), and that the keys are the same ones in your server-side credentials file.

Good to know

  • Who can read what. The volumes in your bucket are opaque to your storage provider and to anyone who gets hold of them without the passphrase, and no other account on the server can read yours. Your host necessarily holds both the passphrase and your storage keys — it's the machine that writes the backups. What this page changes is your side of that: you stop being dependent on the server to read your own data.
  • Retention shapes what you can reach. By default the chain keeps about three months of history with a fresh full copy every 28 days (your KEEP_WITHIN and FULL_BACKUP_FREQUENCY settings, covered on the mybackup page); older sets are pruned on a weekly sweep. collection-status shows you exactly what the chain still covers — a --time outside that range has nothing left to point at.
  • Egress is on you. Restoring a large account downloads volumes from your provider, and most providers charge for download traffic. A single-folder restore only fetches the volumes that folder's data lives in.
  • A second copy is cheap insurance. Tools like rclone can mirror the whole bucket to a local disk (rclone sync), giving you an offline copy of the encrypted volumes; Duplicity can restore from that local mirror with a file:///path/to/mirror target URL — no cloud access needed at all.

© 2026 BOA Documentation. All rights reserved.