NixOS configuration for my homelab.
- Remote access and SSH authentication through Tailscale
- Secret management using 1Password with opnix
- Backups of all critical data to Backblaze B2 using restic
- Edge reverse proxy on picard with Caddy and wildcard TLS via ACME DNS-01 (Cloudflare)
- Containerized services (for example Home Assistant) plus native services (for example OpenClaw) with persistent appdata on
/mnt/fast
- picard (Unraid server): Runs the homelab edge (reverse proxy, DNS), plus apps (Immich, Paperless-ngx, etc.) in a NixOS VM on an Unraid host with a storage array and SSD cache drives.
- Shared edge settings live in
modules/infra/reverse-proxy.nix. - App modules (for example
modules/apps/immich.nixandmodules/apps/paperless.nix) only declare their ownservices.caddy.virtualHostsentries and local upstream target. homelab.apps.*is reserved for subdomain-routed app modules; supporting platform services belong underhomelab.infra.*.- Cloudflare DNS credentials for ACME are sourced through opnix using a secret file that contains
CF_DNS_API_TOKEN=....
homelab.mounts.fast(/mnt/fast) is for active app data with low-latency access needs.homelab.mounts.slow(/mnt/slow) is for the larger capacity tier exposed from Unraid.- On picard, Paperless documents and Immich media live on
/mnt/fast, so restoring thedocumentsrepository targets/mnt/fast/...paths.
# In any module
services.onepassword-secrets.secrets.my-secret = {
reference = "op://Homelab/my-item/my-field";
owner = "myuser";
services = [ "my-service" ]; # Services to restart when secret changes
};
# Access in systemd service
script = ''
SECRET=$(cat ${config.services.onepassword-secrets.secretsPath}/my-secret)
'';Backups are configured per machine in each machine file under homelab.infra.backup.jobs, while modules/infra/backup.nix provides shared restic/opnix plumbing.
Repository layout:
- One B2 bucket per machine.
- One restic repository prefix per resource inside that bucket.
- Shape:
s3:{endpoint}/{machine-bucket}/{resource}
Examples:
- Picard state:
s3:s3.eu-central-003.backblazeb2.com/leolab-backup-picard/state - Picard documents:
s3:s3.eu-central-003.backblazeb2.com/leolab-backup-picard/documents
Home Assistant mapping:
- Home Assistant config lives at
/mnt/fast/appdata/homeassistant/configand is included in Picard'sstatebackup job. - OpenClaw state lives under
/mnt/fast/appdata/openclaw(standard OpenClaw layout, includingopenclaw.json,workspace, andworkspace-labby) and is included in Picard'sstatebackup job. - Zigbee2MQTT config/state lives at
/mnt/fast/appdata/ziqbee2mqtt/configand is included in Picard'sstatebackup job. - Paperless internal app state lives at
/mnt/fast/appdata/paperlessand is included in Picard'sstatebackup job.
- Single file (preferred when possible)
- Single service (state/data for one service)
- Full host data restore
# Verify backup timers/services
systemctl list-timers 'restic-backups-*'
systemctl status restic-backups-state restic-backups-documents
# Stop affected services before restore (example: Paperless)
sudo systemctl stop paperless-scheduler# Must run as root so the wrapper can load credentials from 1Password
sudo restic -r s3:s3.eu-central-003.backblazeb2.com/leolab-backup-picard/state snapshots
sudo restic -r s3:s3.eu-central-003.backblazeb2.com/leolab-backup-picard/documents snapshots# Restore to staging directory, not directly to /
sudo mkdir -p /tmp/restore-state /tmp/restore-documents
sudo restic -r s3:s3.eu-central-003.backblazeb2.com/leolab-backup-picard/state restore latest --target /tmp/restore-state
sudo restic -r s3:s3.eu-central-003.backblazeb2.com/leolab-backup-picard/documents restore latest --target /tmp/restore-documents# Example targets for picard's current storage layout
sudo rsync -a --delete /tmp/restore-state/mnt/fast/appdata/ /mnt/fast/appdata/
sudo rsync -a --delete /tmp/restore-state/var/backup/ /var/backup/
sudo rsync -a --delete /tmp/restore-documents/mnt/fast/documents/ /mnt/fast/documents/
sudo rsync -a --delete /tmp/restore-documents/mnt/fast/photos/ /mnt/fast/photos/
# Fix service ownership where needed
sudo chown -R paperless:paperless /mnt/fast/appdata/paperless
sudo chown -R paperless:paperless /mnt/fast/documents
sudo chown -R immich:immich /mnt/fast/photossudo systemctl start paperless-scheduler
systemctl status paperless-schedulerTip
To quickly browse backups before restoring, use restic snapshots, restic ls latest, and restic find <pattern>. For interactive browsing, mount temporarily with restic mount /mnt/restic.