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
backboatool 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:
- The backups themselves — already in your own bucket, at your own provider (Backblaze B2, Amazon S3, Wasabi, and so on).
- 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.
- 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:
- 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.
- Install Duplicity on the machine you trust — your Mac, your Windows PC (via WSL), or any Linux box.
- Download the
boa-restorehelper, fill in its one config file, and it drives Duplicity for you — the same feel asmybackupon the server, just local. - Run the fire drill now —
bash ~/boa-restore checkplus 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, yourplatforms/anddistro/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~/backupsfolder) are not in the off-site set — thedbackup/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.txtto~/static/control/remote_backups/credentials/.secret.txt, owned by my account's.ftpuser 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:
- Download it over SFTP — the same login and client you already use for your files (see Connecting to your account).
- 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.
- Delete the copy from your account once it's safely stored, and check it's gone:
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:
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:
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:
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):
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:
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):
curl -fsSL https://raw.githubusercontent.com/omega8cc/boa-restore/main/boa-restore -o ~/boa-restore
Create its config template:
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 ato123.fr8.eu.aegir.ccmeans accounto123, serverfr8.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>.txtfile — the helper reads the same variable names, so download that file over SFTP and copy itsexportlines 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:
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.
bash ~/boa-restore list
lists every file in the newest backup, and
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):
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:
read -rs BACKEND_PASSWORD && export BACKEND_PASSWORD
(paste your B2_APPLICATION_KEY at the blank prompt), then:
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:
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:
duplicity collection-status "<target-url>"
See the files in the most recent backup:
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:
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:
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):
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.phpfiles — 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-filesandrestore: none of them modify the backup chain. Never runduplicity backup,cleanup,remove-older-than,remove-all-but-n-fullorremove-all-inc-of-but-n-fullagainst 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:
- 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.
- From your own machine, run
bash ~/boa-restore check(or the manualduplicity 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. - Run
bash ~/boa-restore listand spot-check that your sites' folders and recentdbackupdumps are in the list. - 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_WITHINandFULL_BACKUP_FREQUENCYsettings, covered on the mybackup page); older sets are pruned on a weekly sweep.collection-statusshows you exactly what the chain still covers — a--timeoutside 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 afile:///path/to/mirrortarget URL — no cloud access needed at all.
Related
- Off-site backups & mybackup — setting up the off-site backups this page reads, and the on-server restore route.
- Exporting your site — turning restored pieces back into a running site elsewhere.
- Backing up and restoring in the UI — the everyday single-site safety net.
- Your files & storage — how the
files/links you'll see in the restored tree work on the server. - Connecting to your account — the SFTP/shell login you download the passphrase with.