ADR 007 — local-path-provisioner + Restic for storage and backup
Status
Accepted
Context
Atlas runs on a single node (ADR 002). Workloads need persistent storage (Harbor blobs, Postgres databases for Authentik / Infisical / Harbor, Grafana state, Prometheus and Loki TSDBs), and the operator needs the data to survive disk and host failures.
The options considered were:
- local-path-provisioner (Rancher) — a simple CSI driver that provisions
hostPath-backed PersistentVolumes on demand. - Longhorn — replicated block storage. Built for HA across nodes. Snapshots and backups built in.
- OpenEBS LocalPV + Velero — local volumes plus Velero for snapshots.
- Manual
hostPathPVs — no CSI, no provisioner.
For backup:
- Restic / Kopia to an external S3-compatible bucket (Backblaze B2, MinIO elsewhere, Hetzner Object Storage).
- Velero for full cluster manifests + PV snapshots.
- No backup, accepting data loss on disk failure.
The cluster has one node and one disk. Replicated volumes solve a problem (node-loss) that does not exist here. Backups, on the other hand, solve disk-loss and operator-error, which absolutely do.
Decision
Use local-path-provisioner as the default StorageClass, and Restic in a CronJob to back up the on-disk volumes to an external S3-compatible bucket.
Consequences
Positive
- Lowest-overhead storage on a single node. A PVC becomes a directory under
/var/mnt/local-path-provisioner/. No replication tax, no extra controllers, no extra RAM. - Restic is the right shape for the problem: encrypted, deduplicated, incremental snapshots to S3. Restoring is
restic restore <snapshot> --target ./. - Off-site backup decouples backup failure modes from cluster failure modes. Losing the node does not lose the backups.
- Postgres dumps are part of the same backup job — Restic snapshots both the volume contents and a SQL dump produced by a pre-backup hook, so restores are consistent.
- Backup verification is scriptable. A periodic CronJob runs
restic checkand reports to Alertmanager.
Negative
- No HA, no live replication. A disk failure means downtime until the disk is replaced and the latest Restic snapshot is restored. Acceptable for a homelab; not acceptable for production. RPO is the last nightly backup; RTO is "how long it takes me to restore", typically an hour.
hostPath-style volumes are tied to the node. They cannot be scheduled elsewhere. On a single-node cluster, this is a non-issue.- Restic snapshots are only as good as their target. The S3 bucket must use immutable object versioning or a separate write-only key, otherwise a compromised cluster could delete its own backups.
- Hot Postgres data should not be snapshotted at the block level. The backup CronJob explicitly produces SQL dumps before snapshotting, avoiding inconsistent restores.
Why not Longhorn
Longhorn is a great fit for a 3-node HA cluster with multiple disks. On a single node, it adds a replication layer that has nothing to replicate, costs hundreds of MB of RAM, and introduces a moving part (its own controller and engine pods per volume) that can break. Atlas pays no resource budget for a redundancy it cannot achieve.
Why not Velero
Velero is excellent for full-cluster disaster recovery — manifests + PV snapshots — in environments where the underlying storage supports CSI snapshots. local-path-provisioner does not. Velero's restic-based plugin would work but duplicates the Restic-cronjob approach Atlas already runs, with more moving parts.