age backups everywhere
This commit is contained in:
parent
27e036eccd
commit
394f2519ff
11 changed files with 200 additions and 15 deletions
|
|
@ -39,6 +39,56 @@ The role pipes it into `age`, so plaintext never touches the disk. Use `-C /`
|
|||
with relative paths in `tar` rather than absolute ones: it avoids tar's "removing
|
||||
leading /" and makes the restore target explicit.
|
||||
|
||||
## Services that are not systemd
|
||||
|
||||
`backup_source_stop_service` runs `systemctl stop/start`. For anything else,
|
||||
give the pair explicitly — vaultwarden is a docker compose stack, so
|
||||
`systemctl stop vaultwarden` silently does nothing:
|
||||
|
||||
```yaml
|
||||
backup_source_stop_command: "docker compose -f /opt/vaultwarden/docker-compose.yml stop"
|
||||
backup_source_start_command: "docker compose -f /opt/vaultwarden/docker-compose.yml start"
|
||||
```
|
||||
|
||||
The same EXIT trap wraps both forms. The assert refuses a stop command without a
|
||||
matching start command, because that combination fails in the one way you would
|
||||
not notice: the service stops and never comes back.
|
||||
|
||||
## More than one thing to back up
|
||||
|
||||
`tar` takes several paths, so multiple files or directories are normally **one**
|
||||
artefact — headscale captures `/var/lib/headscale` and `/etc/headscale` together,
|
||||
lnbits captures its data directory and its `.env`.
|
||||
|
||||
Prefer one artefact. A backup should be a consistent snapshot, and two artefacts
|
||||
written by two runs can drift — you can end up restoring an `.env` that does not
|
||||
match the database it configures. Pulling a single file back out needs no
|
||||
unpacking:
|
||||
|
||||
```bash
|
||||
age -d -i <identity> <artefact> | tar -xzO opt/lnbits/lnbits/.env
|
||||
```
|
||||
|
||||
If you genuinely need separate artefacts, call the role twice with different
|
||||
`backup_source_name`s rather than extending it — but only one call may set
|
||||
`backup_source_stop_service`, or the service is stopped twice per night.
|
||||
|
||||
The case this shape cannot express is a **database dump plus a file tree**
|
||||
(`pg_dump` and a media directory, say): you cannot merge those into one stream
|
||||
without staging plaintext on disk, which is exactly what this design avoids.
|
||||
None of the current services need it — all are file trees, all stopped for the
|
||||
dump. A future one that does should use two role calls.
|
||||
|
||||
## Everything here is sqlite, so everything stops
|
||||
|
||||
All five services are sqlite-backed, several in WAL mode (`-wal`/`-shm` files
|
||||
present). A live copy of a WAL-mode database can be torn or stale, so each is
|
||||
stopped for the duration. Measured downtime: under a second for headscale and
|
||||
memos, ~6 s vaultwarden, ~11 s lnbits, and **2m36s for forgejo** — 2.7 G of repos
|
||||
and database. That last one is the real cost of a consistent snapshot; if it
|
||||
becomes unacceptable the answer is `sqlite3 .backup` plus an online repo copy,
|
||||
not skipping the stop.
|
||||
|
||||
## The trap is the reason this role exists
|
||||
|
||||
When `backup_source_stop_service` is set, the script stops the unit and installs
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue