A plain-text copy of this page is uploaded every night as RECOVERY.txt in the Google Drive folder
diskstation-offsite, so it can be read even when this wiki is down. Its source is
offsite/RECOVERY.txt in the diskstation/kopia project; keep the two identical.
Last updated: 2026-10-31. Last restore drill: not yet done.
This guide is for when the Synology NAS "diskstation" is gone: dead hardware, failed drives,
fire or theft. It gets back, in this order:
This file contains no secrets. You can read all of it before you start.
From the household safe:
You also need:
The decrypted bundle holds every bootstrap secret in plain form. Work in one folder,
~/recovery, preferably on an encrypted disk, and delete it when you are done (step 7).
Install age: "sudo apt install age" (Debian/Ubuntu), "brew install age" (macOS), or download
it from https://github.com/FiloSottile/age/releases.
Type the private key from the safe into a file, exactly as printed, then lock it down:
cd ~/recovery
nano age.key # one line: AGE-SECRET-KEY-1...
chmod 600 age.key
Decrypt and unpack:
age -d -i age.key -o bundle.tar diskstation-offsite-YYYYMMDD.tar.age
mkdir bundle && tar -C bundle -xf bundle.tar
"no identity matched" means the key was mistyped. Compare it with the paper copy character by
character.
Check the files are intact. Every line should say OK:
cd ~/recovery/bundle
sha256sum -c SHA256SUMS # on macOS: shasum -a 256 -c SHA256SUMS
Read MANIFEST.txt. It lists the exact Kopia, Vault and container image versions the NAS was
running. Use those versions below, not "latest".
What the bundle contains:
MANIFEST.txt, SHA256SUMS
kopia/ repository.config, repository.config.kopia-password (the repository
password), nightly-backup-root.sh, ssh/ (Storage Box SSH key and known_hosts)
vaultwarden/ db.sqlite3, attachments/, sends/, config.json, rsa_key*
vault/ raft.snap (Vault snapshot), hcl-vault-files.tar (Vault's folder from the NAS:
config, certificates, scripts and unseal_keys.txt)
Copy the data into place and start the container. Replace VERSION with the vaultwarden image
tag from MANIFEST.txt:
mkdir -p ~/recovery/vw-data
cp -a ~/recovery/bundle/vaultwarden/. ~/recovery/vw-data/
Edit ~/recovery/vw-data/config.json. Settings there override everything else, so if it has a
"domain" line, change its value to "http://localhost:8080". Then:
docker run -d --name vaultwarden -v ~/recovery/vw-data:/data \
-p 127.0.0.1:8080:80 vaultwarden/server:VERSION
Open http://localhost:8080 in a browser on the same computer and log in as mark@rachelski.net
with the master password.
Make a backup straight away: Tools > Export vault > format ".json (Encrypted)", protected by a
password you will remember. Keep that file off the recovery computer too.
You now have every household password, including "DiskStation Admin", the Vault admin login and
the Hetzner account.
How Vault was set up: it ran in Docker from the folder hcl-vault. On every start, its script
config/init-vault.sh unseals Vault using vault/data/unseal_keys.txt. If the data folder is empty,
the script sets up a brand-new Vault instead. The restore below uses that: start a new, empty
Vault, load the snapshot into it, then switch back to the original unseal keys.
Unpack Vault's folder and set the original keys aside:
cd ~/recovery
tar -xf bundle/vault/hcl-vault-files.tar # creates ~/recovery/hcl-vault
cd hcl-vault
mv vault/data/unseal_keys.txt ~/recovery/original_unseal_keys.txt
rm -f vault/data/status.txt
Edit docker-compose.yaml:
change "image: hashicorp/vault:latest" to the Vault version in MANIFEST.txt
(for example hashicorp/vault:1.20.4)
add these lines to the vault service, so the old hostname points at this computer:
extra_hosts:
- "hcl-vault.rachelski.internal:127.0.0.1"
Start it and wait about 30 seconds. The script sets up a new Vault and writes
vault/data/init.txt containing a temporary root token:
docker compose up -d
sleep 30 && docker exec vault vault status # Initialized true, Sealed false
Load the snapshot:
TOKEN=$(grep 'Initial Root Token' vault/data/init.txt | awk '{print $4}')
docker cp ~/recovery/bundle/vault/raft.snap vault:/tmp/raft.snap
docker exec -e VAULT_TOKEN="$TOKEN" vault vault operator raft snapshot restore -force /tmp/raft.snap
Put the original unseal keys back, remove the temporary setup's file, and restart:
cp ~/recovery/original_unseal_keys.txt vault/data/unseal_keys.txt
rm vault/data/init.txt
docker compose restart
sleep 30 && docker exec vault vault status # Sealed false
Open http://localhost:8200 and log in with the Vault admin login from Bitwarden. Check that
the secrets-k8s-ranch secrets and the PKI are there.
If Vault won't start or stays sealed, run "docker logs vault". If the newer Kopia copy of
/volume3/docker/hcl-vault is restored later (step 6), prefer this snapshot anyway: Kopia copied
Vault's files while it was running, but the snapshot is guaranteed consistent.
Install the Kopia version from MANIFEST.txt from https://github.com/kopia/kopia/releases.
Prepare the SSH key:
mkdir -p ~/recovery/kopia && cp -a ~/recovery/bundle/kopia/. ~/recovery/kopia/
chmod 600 ~/recovery/kopia/ssh/*
Check the Storage Box's SSH host key. Compare the fingerprints printed here with the ones
Hetzner publishes for Storage Boxes (search "Hetzner Storage Box SSH host keys"):
ssh-keyscan -p 23 u465088.your-storagebox.de > ~/recovery/kopia/ssh/storagebox_known_hosts
ssh-keygen -lf ~/recovery/kopia/ssh/storagebox_known_hosts
Connect. Host, port, path and user are the values in kopia/repository.config. The password is
the single line in kopia/repository.config.kopia-password:
export KOPIA_PASSWORD="$(cat ~/recovery/kopia/repository.config.kopia-password)"
kopia --config-file ~/recovery/kopia/recovery.config repository connect sftp \
--host u465088.your-storagebox.de --port 23 --username u465088-sub1 \
--path ./diskstation \
--keyfile "$HOME/recovery/kopia/ssh/mark+2025@diskstation.rachelski.internal" \
--known-hosts ~/recovery/kopia/ssh/storagebox_known_hosts \
--override-hostname diskstation --override-username admin --readonly
List what is in the backup:
kopia --config-file ~/recovery/kopia/recovery.config snapshot list --all
You should see snapshots for /volume1/Public, /volume1/Storage, /volume1/homes/Leena,
/volume1/homes/Mark, /volume1/nextcloud-data, /volume3/docker and
/volume3/homelab/k3s/photos.
If the SSH login is refused, the key on the Storage Box sub-account was changed or removed. Log
in to the Hetzner console (login in Bitwarden), open Storage Box u465088, sub-account
u465088-sub1, and add the public key kopia/ssh/mark+2025@diskstation.rachelski.internal.pub.
Restore onto the replacement machine, not onto the recovery computer. Most important first:
Restore a snapshot with:
kopia --config-file ~/recovery/kopia/recovery.config snapshot restore <snapshot-id> <target-folder>
Or browse a snapshot as a folder with "kopia mount ". Remove
--readonly from the connect command only when the new machine is ready to take over the nightly
backups.