fix(backup): name preserved env vars instead of relying on sudo -E
sudo-rs — the default sudo from Ubuntu 25.10, so on 26.04 — does not
implement bare -E. It does not reject it either: it warns to stderr
("preserving the entire environment is not supported, '-E' is ignored")
and runs the command with the environment DROPPED, leaving the exit
status untouched. Callers capture stderr, so the warning is invisible and
the backup engines simply never receive RESTIC_PASSWORD / BORG_PASSPHRASE
/ KOPIA_PASSWORD and cannot open the repository.
Name the nine vars explicitly via --preserve-env=<list>, which sudo-rs
and classic sudo (>=1.8.21, so Debian 10's 1.8.27) both honour, so this
needs no version gate. The list is cross-checked against every
RESTIC_/BORG_/KOPIA_ var the engine env scripts export.
The list lives in variables.sh with a literal fallback in runBackupOp,
because init.sh sources run_privileged.sh directly during install without
ever loading variables.sh — an unguarded empty list would silently
reproduce the same dropped-credential bug.
restoreFirstRunDiscover now goes through runBackupOp rather than issuing
its own sudo. It was the only backup-engine call bypassing that funnel,
which is why it missed this fix by construction; routing it back also
gives it the -H that keeps restic's cache under the backup user's HOME.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
9b9b2054d3
commit
48cb5d9380
@ -99,17 +99,26 @@ runCfgOp() {
|
||||
}
|
||||
|
||||
# Backup-engine command (borg/restic/kopia) run AS the dedicated backup user
|
||||
# ($docker_install_user), with the environment preserved (-E) so the repo
|
||||
# password and BORG_/RESTIC_/KOPIA_ env vars reach the tool. Never root — the
|
||||
# scoped sudoers lets the manager drop to this user. Single funnel so the
|
||||
# backup subsystem's privilege drop has one audit point.
|
||||
# ($docker_install_user), with the repo password and BORG_/RESTIC_/KOPIA_ env
|
||||
# vars carried across the privilege drop. Never root — the scoped sudoers lets
|
||||
# the manager drop to this user. Single funnel so the backup subsystem's
|
||||
# privilege drop has one audit point.
|
||||
# The vars are named explicitly instead of using bare `-E`: sudo-rs (the default
|
||||
# from Ubuntu 25.10, so on 26.04) doesn't implement -E — it prints "preserving
|
||||
# the entire environment is not supported, '-E' is ignored" to stderr and then
|
||||
# runs the command with the environment DROPPED. Exit status is unaffected and
|
||||
# callers capture stderr, so that failure is invisible; the engine just can't
|
||||
# open the repository. --preserve-env=<list> is honoured by both sudo-rs and
|
||||
# classic sudo (>=1.8.21, so Debian 10's 1.8.27 included).
|
||||
# The literal fallback mirrors $backup_env_preserve in variables.sh, which isn't
|
||||
# loaded when init.sh sources this file directly during install.
|
||||
# -H resets HOME to the target user's so restic finds (or creates) its cache
|
||||
# under /home/$docker_install_user/.cache/restic instead of inheriting the
|
||||
# manager's HOME (which dockerinstall can't write into, surfacing as
|
||||
# "unable to open cache: mkdir /home/libreportal/.cache/restic: permission denied"
|
||||
# on every backup).
|
||||
runBackupOp() {
|
||||
sudo -E -H -u "$docker_install_user" "$@"
|
||||
sudo --preserve-env="${backup_env_preserve:-BORG_PASSPHRASE,BORG_REPO,BORG_RSH,KOPIA_CHECK_FOR_UPDATES,KOPIA_CONFIG_PATH,KOPIA_PASSWORD,RESTIC_PASSWORD,RESTIC_REPOSITORY,RESTIC_SFTP_COMMAND}" -H -u "$docker_install_user" "$@"
|
||||
}
|
||||
|
||||
# Run one of the ROOT-OWNED LibrePortal helpers installed (root:root 0755) under
|
||||
|
||||
@ -10,7 +10,10 @@ restoreFirstRunDiscover()
|
||||
fi
|
||||
|
||||
resticEnvExport "$idx" || return 1
|
||||
sudo -E -u "$docker_install_user" restic snapshots --tag engine=libreportal --json --no-lock 2>/dev/null
|
||||
# Via runBackupOp rather than its own sudo: this was the one backup-engine
|
||||
# call bypassing that funnel, so it silently missed the -E fix for sudo-rs
|
||||
# (and the -H that puts restic's cache under the backup user's HOME).
|
||||
runBackupOp restic snapshots --tag engine=libreportal --json --no-lock 2>/dev/null
|
||||
local rc=$?
|
||||
resticEnvUnset
|
||||
return $rc
|
||||
|
||||
@ -49,6 +49,15 @@ sysctl="/etc/sysctl.d/99-libreportal-rootless.conf"
|
||||
# aren't loaded. Ubuntu 24.04/26.04 don't autoload them on a fresh box, so we
|
||||
# both modprobe them now and persist them here for subsequent boots.
|
||||
modules_load="/etc/modules-load.d/libreportal-rootless.conf"
|
||||
|
||||
# Env vars that must survive the privilege drop into $docker_install_user for the
|
||||
# backup engines to open their repository (repo URI + passphrase + ssh transport).
|
||||
# Named explicitly rather than relying on `sudo -E`: sudo-rs, the default on
|
||||
# Ubuntu 25.10+ (incl. 26.04), does not implement bare -E — it warns and runs the
|
||||
# command with the environment dropped. Keep in sync with the fallback list in
|
||||
# scripts/docker/command/run_privileged.sh (init.sh sources that file directly,
|
||||
# without this one).
|
||||
backup_env_preserve="BORG_PASSPHRASE,BORG_REPO,BORG_RSH,KOPIA_CHECK_FOR_UPDATES,KOPIA_CONFIG_PATH,KOPIA_PASSWORD,RESTIC_PASSWORD,RESTIC_REPOSITORY,RESTIC_SFTP_COMMAND"
|
||||
docker_log_file=libreportal.log
|
||||
backup_log_file=backup.log
|
||||
db_file=database.db
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user