Backup Process

1. Overview & Architecture

This server (ul) implements an automated, multi-tiered backup system designed around high reliability, cryptographic security, redundancy, and verified recoverability. The backup infrastructure covers 43 containerized and native host services, maintaining local PAR2-protected rollbacks and GPG-encrypted multi-cloud offsite copies.

Key Philosophy


2. Directory & Data Structure

Path Purpose Access Control
/home/luke/git/backups/ul/scripts/ Shell and Python backup/restore execution scripts (GPG-signed git repository) Executable
/data/backups/services/current/<service>/ Most recent local backup run for each service 700 luke:luke
/data/backups/services/archive/<service>/ Previous local backup run(s) for point-in-time recovery 700 root:root
/data/backups/cloud/ Staged GPG-encrypted net archive ready for cloud upload 700 luke:luke
/data/backups/isos/ Staged optical media ISO images (when generating disk media) 700 luke:luke

3. End-to-End Backup Workflow

Local service archive creation, cloud staging, cloud upload, and optical ISO creation are separated into distinct commands under /home/luke/git/backups/ul/scripts/:

+-----------------------------------------------------------------------------------+
| 1. Local Service Backups (`sudo ./run_all_backups`)                               |
| Loop over /ul/scripts/backup/* -> Dump DBs, tar files, generate PAR2 -> /current |
| Self-archive backup scripts themselves into /current/backup                       |
+-----------------------------------------------------------------------------------+
                     |                                           |
                     v                                           v
+-----------------------------------------+   +-------------------------------------+
| 2a. Cloud Staging                       |   | 2b. Optical ISO Staging             |
| (`./stage_cloud_archive`)               |   | (`./stage_iso_archive`)             |
| Pack /current -> GPG Encrypt -> /cloud  |   | Pack /current -> GPG ISOs -> /isos  |
+-----------------------------------------+   +-------------------------------------+
                     |                                           |
                     v                                           v
+-----------------------------------------+   +-------------------------------------+
| 3a. Cloud Upload & Remote Rotation      |   | 3b. Optical Media Burn & Verify     |
| (`./upload_cloud_archive [remotes]`)    |   | (`./burn_and_verify_iso <iso>`)     |
| Upload /cloud -> rclone check -> Rotate |   | Burn DVD/M-DISC -> Verify SHA256    |
+-----------------------------------------+   +-------------------------------------+

Commands & Flags


4. Service-Level Backups (/ul/scripts/backup/)

Every service backup script performs atomic snapshots using the following standard pattern:

  1. Root Verification & Timestamping: Requires root permissions (EUID == 0) to preserve subordinate container UID/GID ownership (1100, 624288--689823), POSIX ACLs (--acls), and extended attributes (--xattrs). Timestamp format: YYYY-MM-DD_HHMM.SS.
  2. Local Archive Rotation: Moves existing /current/<service>/* directories to /archive/<service>/.
  3. Consistent Database & Cache Snapshots:
    • Native Host PostgreSQL (authentik, anchor, forgejo, immich, nextcloud_db, vikunja, wipstudio): Staged to /tmp/<fn>.dump first via sudo -u postgres pg_dump -F c -b -v before moving into /data/backups/services/current/<service>/.
    • Containerized PostgreSQL (penpot-postgres, funkwhale): Executed rootlessly via (cd /tmp && sudo -u docker-data podman exec penpot-postgres pg_dump -U penpot -F c -b penpot) and podman exec -u funkwhale funkwhale pg_dumpall -U funkwhale.
    • Containerized MariaDB (bookstack_db, romm-db, yourls-db): (cd /tmp && sudo -u docker-data podman exec <db_container> mariadb-dump --single-transaction --routines --triggers ...).
    • SQLite WAL Checkpoints (navidrome, subocr, vaultwarden): Consistent online .backup or PRAGMA wal_checkpoint(TRUNCATE).
    • Native Valkey (valkey.service): Triggers BGSAVE with dedicated read/save-only ACL user backup and archives /var/lib/valkey/dump.rdb + /etc/valkey/.
  4. Configuration, Quadlet & Volume Compression:
    • Compressed using multi-threaded XZ (XZ_OPT="-T0" tar --acls --xattrs -cJf ...).
    • Preserves .env, <service>.container, <service>.network, application data/assets, and host configs (systemd archives /etc/systemd, /etc/containers, /etc/haproxy, /etc/nftables.conf, and /home/docker-data/.config/containers/systemd).
  5. PAR2 Recovery Generation:
    • Generates 10% parity redundancy (par2 create -r10) directly alongside every database dump and tarball.
  6. Execution Logging: Captures output to backup_execution.log inside each timestamped service backup folder.

Backed-Up Services (43 Targets)

acme, amux, anchor, audiomass, authentik, bentopdf, bookstack, cam, craft, crowdsec, degoog, demucs, drawpile, excalidraw, forgejo, funkwhale, grill, immich, jellyfin, mc_manager, minecraft_router, navidrome, nextcloud, nginx, penpot, rclone, romm, scontrol, sopro, subocr, sunshine, systemd, tldraw, transmission, valkey, vaultwarden, vikunja, wavacity, webrcade, webshell, wick, wipstudio, wireguard, yourls.


5. Cloud Archiving & Encryption (archive_pack.py)

Local service backups are consolidated into a secure net package by archive_pack.py invoked via stage_cloud_archive:


6. Cloud Orchestration & Provider Synchronization

Cloud synchronization is orchestrated by upload_cloud_archive calling provider scripts in upload/:

Configured Providers

  1. Google Drive (upload/gdrive)
  2. Proton Drive (upload/protondrive)

Upload Reliability Features

Remote Retention Policy


7. Restoration Practice & Recovery Procedure

Restoration scripts reside in /home/luke/git/backups/ul/scripts/restore/. Each service script handles full state recovery:

Standard Restore Procedure

  1. Target Selection: Accepts an explicit backup directory or timestamp as argument. If omitted, defaults to the latest backup in /data/backups/services/current/<service>/.
  2. PAR2 Integrity Check & Self-Repair: Runs par2 verify on database dumps and file tarballs prior to performing any system modifications. Automatically executes par2 repair if corruption is detected.
  3. Interactive Confirmation: Prompts user for explicit confirmation (yes/no) before stopping services or modifying state.
  4. Service Suspension: Gracefully stops active rootless Podman Quadlet units (sudo -u docker-data XDG_RUNTIME_DIR=/run/user/1100 systemctl --user stop <service>.service) or native systemd units.
  5. Rollback Snapshot Creation: Preserves current configurations in a timestamped rollback folder (<service_dir>_rollback_<timestamp>).
  6. File & Database Restoration:
    • Extracts compressed tarball over service data directory with POSIX ACL/xattr and subordinate UID/GID preservation.
    • Re-creates target database schema and imports the SQL dump or PostgreSQL custom binary dump.
  7. Service Resumption: Reloads and restarts rootless Quadlets (sudo -u docker-data XDG_RUNTIME_DIR=/run/user/1100 systemctl --user daemon-reload && sudo -u docker-data XDG_RUNTIME_DIR=/run/user/1100 systemctl --user start <service>.service).

8. Retention Pruning Practice (prune_old_local_backups)

To prevent local storage exhaustion on the server, local service backup folders are managed by /home/luke/git/backups/ul/scripts/prune_old_local_backups:


Revision #6
Created 2026-08-16 16:08:16 UTC by admin
Updated 2026-10-20 03:45:58 UTC by luKe