Skip to content

Per-Service Restore Procedures

How to recover each backed-up service from restic snapshots.

Prerequisites

  • restic installed 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.