Restore from a backup
For the day the disk dies, the box is stolen, or you move to new hardware. From the envelope to a signed-in vault, about an hour plus the download.
On this page
Nothing here needs the old machine.
What you need#
From the envelope:
- The master key. Without it the documents in the backup are noise.
- The backup password.
- Where the repository is, and its credentials.
- The recovery codes, if your authenticator app is gone too.
The volume passphrase from the old box is not needed. A new box gets a new volume and a new passphrase, which then goes on a new envelope.
1. A box with an empty vault#
Follow Prerequisites and The data volume on the new machine, and install Tailscale if you use it. Then stop before the installer: a restore puts the old secrets back instead of generating new ones, so this part is done by hand, following the repository's deploy.md for the images and the configuration file. When it comes to secrets, put the old ones back exactly:
mkdir -p /data/secrets && chmod 700 /data/secrets
printf '%s\n' '<master key from the envelope>' > /data/secrets/kek
printf '%s\n' '<backup password from the envelope>' > /data/secrets/restic-password
chmod 600 /data/secrets/kek /data/secrets/restic-passwordSet the repository and its credentials in /data/harbor.env as they were. A key typed wrong fails loudly in the next step, not silently later.
Do not start the stack yet. Two shortcuts for what follows:
cd /opt/harbor
export $(grep -v '^#' /data/harbor.env | xargs)
alias dc='docker compose --env-file /data/harbor.env -f compose.yml -f compose.prod.yml'2. Bring the files back#
dc up -d postgres # the backup container needs it to start
dc run --rm backup restic snapshots # proves the password and the repository; lists what exists
dc run --rm backup restic restore latest --target /The last line puts everything back where it was: the documents under /data/blobs, the database dump at /data/dumps/harbor.dump. Both paths are mounts inside the container, so nothing else is written. To restore a particular night instead of the latest, use its id from the list.
3. Load the database#
dc run --rm backup pg_restore --no-owner --exit-on-error \
--dbname=postgres://harbor:harbor@postgres:5432/harbor /data/dumps/harbor.dumpThis is the same command the monthly test runs against a scratch database. The dump includes the migrations table, so the API starts without running migrations again.
4. Start and sign in#
dc up -d
dc logs -f api # wait for "API listening on :4000"Sign in at the new address with your password and authenticator. The authenticator secrets were sealed under the master key, which is why the envelope holds it. Sessions and invitations are in the dump too.
5. Prove it#
0 / 5 proven