Per-Service Restore Procedures¶
How to recover each backed-up service from restic snapshots.
Prerequisites¶
resticinstalled on the recovery host- Access to
/etc/restic/password(the restic repo encryption key) - For tier-1 offsite restores: B2 credentials in
/etc/restic/b2.env
General Restore Pattern¶
All services follow the same basic flow:
# 1. List available snapshots
export RESTIC_REPOSITORY=/var/backups/restic/<service>
export RESTIC_PASSWORD_FILE=/etc/restic/password
restic snapshots
# 2. Restore the latest (or a specific snapshot)
restic restore latest --target /tmp/restore-<service>
# or: restic restore <snapshot-id> --target /tmp/restore-<service>
# 3. Copy restored files to the service directory
# (service-specific steps below)
# 4. Restart the service
cd /opt/homelab/services/<service>
docker compose down && docker compose up -d
Restoring from B2 (offsite, tier-1 only)¶
If the local repo is lost:
source /etc/restic/b2.env
export RESTIC_REPOSITORY=b2:<bucket>:<service>
export RESTIC_PASSWORD_FILE=/etc/restic/password
restic snapshots
restic restore latest --target /tmp/restore-<service>
Komodo (tier 1)¶
Komodo auto-manages MongoDB dumps to /etc/komodo/backups. Restic backs up
that directory.
# Restore
restic restore latest --target /tmp/restore-komodo
# Stop Komodo
cd /opt/homelab/services/komodo
docker compose down
# Replace the backups directory
cp -a /tmp/restore-komodo/etc/komodo/backups/* /etc/komodo/backups/
# Restart — Komodo will import the latest dump on startup
docker compose --env-file compose.env up -d
Verify: Open komodo.infra.realemail.app and confirm servers/stacks are
listed. Check Komodo logs: docker logs komodo-core.
Traefik (tier 1)¶
Backs up the static config directory and acme.json (Let's Encrypt certs).
# Restore
restic restore latest --target /tmp/restore-traefik
# Stop Traefik
cd /opt/homelab/services/traefik
docker compose down
# Replace config
cp -a /tmp/restore-traefik/opt/homelab/services/traefik/config/* ./config/
cp -a /tmp/restore-traefik/opt/homelab/services/traefik/acme.json ./acme.json
chmod 600 ./acme.json
# Decrypt secrets
SOPS_AGE_KEY_FILE=/etc/homelab/age-key.txt sops -d .env.sops.yaml \
| sed 's/: /=/' > .env
# Restart
docker compose up -d
Verify: curl -I https://homepage.infra.realemail.app returns a valid TLS
cert. If acme.json was lost, Traefik re-issues certs automatically (may take
a few minutes; watch for Let's Encrypt rate limits if you've done this multiple
times in a week).
ARA (tier 2)¶
SQLite database with Ansible run history. Regeneratable but useful to keep.
restic restore latest --target /tmp/restore-ara
cd /opt/homelab/services/ara
docker compose down
# The volume is a Docker named volume; replace its contents
docker run --rm -v ara_ara-data:/data -v /tmp/restore-ara:/backup \
alpine sh -c "rm -rf /data/* && cp -a /backup/* /data/"
docker compose up -d
Homepage (tier 2)¶
Config is generated from inventory — backup is convenience only.
restic restore latest --target /tmp/restore-homepage
# Copy config files back if needed. Or just re-run the generator:
cd /opt/homelab
uv run python inventory/generators/render-homepage.py
Monitoring (tier 2)¶
Grafana user customizations outside of code-managed provisioning.
restic restore latest --target /tmp/restore-monitoring
# Replace Grafana data volume
cd /opt/homelab/services/monitoring
docker compose stop grafana
docker run --rm \
-v monitoring_grafana-data:/data \
-v /tmp/restore-monitoring/var/lib/docker/volumes/monitoring_grafana-data/_data:/backup:ro \
alpine sh -c "rm -rf /data/* && cp -a /backup/* /data/"
docker compose up -d grafana
Note: Dashboards provisioned from monitoring/grafana/dashboards/ are
restored automatically on Grafana startup. Only user-created dashboards and
annotations need the volume restore.
External Services (not on infra-services)¶
Saltbox Secrets (saltierpoop)¶
The SOPS-encrypted source files are in git. To restore the deployed copies:
cd /opt/homelab
SOPS_AGE_KEY_FILE=/etc/homelab/age-key.txt \
sops -d infra/ansible/roles/saltbox-host/files/accounts.sops.yaml \
> /opt/saltbox/accounts.yml
Or re-run Ansible: ansible-pull will deploy the latest encrypted versions.
Authentik DB (saltierpoop)¶
Restore from the pg_dump backup:
restic restore latest --target /tmp/restore-authentik
docker exec -i authentik-postgres psql -U authentik \
< /tmp/restore-authentik/tmp/authentik-backup/authentik.sql.gz
docker restart authentik
HAOS Config¶
Restore the snapshot .tar via the HA Supervisor API or manually upload
through the HAOS UI at Settings > System > Backups.