Every nightly run had been failing since 20 Sep, writing the reason only to
a log file nobody reads. The last backup on the share was from 19 Sep.
Root cause: a sudoers rule that names arguments matches only that exact
argument list. The rule allowed
sudo /usr/bin/sqlite3 /var/.../db.sqlite3
but the script ran
sudo sqlite3 /var/.../db.sqlite3 ".backup '/tmp/.../db'"
The second argument was not in the rule, so it did not match, sudo fell
through to the password-required bdm ALL=(ALL) ALL, and cron has no
terminal to prompt on. Reproduced with -n, so neither call could prompt:
sudo -n sqlite3 <db> # 1 arg, matches -> exit 0
sudo -n sqlite3 <db> "SELECT 1" # 2 args, no match -> password required
Two further problems were hidden behind that early exit:
The cleanup phase called sudo mount/umount/find inline, but sudoers only
whitelisted helper scripts that existed and were never invoked. The 60-day
retention was dead too. The old cleanup also could not distinguish "share
not mounted" from "nothing to delete": find matched nothing and the script
exited 0 reporting a healthy run.
The helpers that *were* whitelisted lived under /home/bdm and are owned by
bdm, so the grant was equivalent to unrestricted root.
Changes:
Move each privileged step into a root-owned helper in /usr/local/sbin,
deployed from the repo as source of truth. This avoids depending on fragile
argument globs and lets the rule constrain the one argument that varies.
vw-backup-db re-validates the destination path itself rather than trusting
the sudoers pattern.
Call the helpers from the script and drop the inline sudo. Verify the
snapshot with PRAGMA integrity_check before uploading, and abort rather
than shipping a copy that does not verify. Check smbclient's exit status
directly instead of piping into grep, which would have let SIGPIPE mask a
failed upload.
Add a systemd staleness watchdog so this cannot hide again. It mounts the
share read-only and separates STALE (nothing recent) from CANNOT VERIFY
(could not mount), which mean different things.
Also chmod 0440 /etc/sudoers.d/bdm, which visudo was warning about.
Tested with a cold sudo cache, since timestamp_type=global means an
interactive sudo -v otherwise masks the failure. A real cron invocation
succeeded end to end: snapshot, integrity check, upload, and prune.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
18 lines
564 B
Desktop File
18 lines
564 B
Desktop File
[Unit]
|
|
Description=Check that the vaultwarden backup is not stale
|
|
Documentation=file:/home/bdm/scripts/vaultwarden-backup-helpers/README.md
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
# Runs as root so it can mount the share itself; no sudo is involved.
|
|
ExecStart=/usr/local/sbin/vw-backup-check
|
|
# Exit 1 means stale, exit 2 means it could not verify. Both are failures, and
|
|
# both leave a failed unit behind so "systemctl status" shows the problem.
|
|
SuccessExitStatus=0
|
|
TimeoutStartSec=120
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|