backup: encrypted daily backups — VPS generates, Mac pulls (Tanda B, point 1)
ci / lint-test-leaks (pull_request) Canceled after 0s
ci / lint-test-leaks (pull_request) Canceled after 0s
deploy/backup/make-backup.sh (installed as /usr/local/bin/cayce-make-backup): - pg_dump custom-format of the cayce-ops DB (URL from env or .env, SQLAlchemy driver qualifier stripped, credentials never logged) - gitea dump (repos + sqlite + attachments), live; consistency notes in RESTORE.md - config tar: Caddyfile(+d), gitea app.ini + internal_token, cayce-* units, .env - EACH artifact encrypted with age BEFORE leaving the tmpdir; recipient read from /etc/cayce-backup/age-recipient.pub (public key only). The private age key never touches this server. - plaintext exists ONLY in a mktemp dir removed by an EXIT trap; a partial day directory is removed on failure; any step failure => exit != 0 => journald entry - manifest.sha256 over the encrypted artifacts (pull side verifies integrity WITHOUT the age private key) - destination /var/backups/cayce/YYYY-MM-DD/ (750 root:backup-pull, 640) - retention: 7 daily dirs, pruned by mtime systemd: cayce-backup.service (oneshot, hardened: ProtectSystem=strict, NoNewPrivileges, ProtectHome=read-only) + cayce-backup.timer (daily 03:15 UTC, Persistent). Timer ENABLED on the VPS per operator instruction; runs fail loudly (exit 1, clear journald message) until the age recipient is provided — that is the designed not-configured state.
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=Cayce — encrypted daily backup (CayceOps DB + Gitea + config)
|
||||
After=network-online.target postgresql.service
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/bin/cayce-make-backup
|
||||
# hardening
|
||||
NoNewPrivileges=true
|
||||
ProtectHome=read-only
|
||||
ReadWritePaths=/var/backups/cayce /tmp
|
||||
ProtectSystem=strict
|
||||
PrivateTmp=false
|
||||
Reference in New Issue
Block a user