restic: don't fall back to parent's HOME when picking the cache dir
CI / Test (linux/amd64) (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Build (windows/amd64) (push) Has been cancelled
CI / Build (linux/amd64) (push) Has been cancelled
CI / Build (linux/arm64) (push) Has been cancelled

Agent runs as root (HOME=/root from systemd) with ProtectHome=
read-only, so restic's `mkdir /root/.cache/restic` fails on the
first call. Backups still completed (restic falls back to no-cache)
but every job log started with a noisy red "unable to open cache"
warning.

Default to /var/lib/restic-manager unconditionally — that's already
in the unit's ReadWritePaths and survives ProtectHome. ExtraEnv
overrides still win for tests / unusual setups.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-02 13:43:10 +01:00
parent c565a7abd1
commit 1b947f5a2c
+7 -5
View File
@@ -10,7 +10,6 @@ import (
"errors"
"fmt"
"io"
"os"
"os/exec"
"strings"
"time"
@@ -229,18 +228,21 @@ func pumpPlain(r io.Reader, stream string, handle LineHandler) error {
// HOME / XDG_CACHE_HOME are set explicitly because restic insists
// on one or the other for its cache dir; without it the command
// fails before ever talking to the repo.
//
// Default to /var/lib/restic-manager — that's in the systemd unit's
// ReadWritePaths and survives ProtectHome=read-only. We do NOT fall
// back to the parent's HOME env var: the agent runs as root with
// HOME=/root, but ProtectHome makes /root read-only, so restic's
// `mkdir /root/.cache/restic` fails. ExtraEnv overrides win for
// callers that explicitly want a different cache location.
func (e Env) envSlice() []string {
home := "/var/lib/restic-manager"
if h, ok := e.ExtraEnv["HOME"]; ok && h != "" {
home = h
} else if h := os.Getenv("HOME"); h != "" {
home = h
}
xdg := home + "/.cache"
if x, ok := e.ExtraEnv["XDG_CACHE_HOME"]; ok && x != "" {
xdg = x
} else if x := os.Getenv("XDG_CACHE_HOME"); x != "" {
xdg = x
}
out := []string{
"RESTIC_REPOSITORY=" + mergeRestCreds(e.RepoURL, e.RepoUsername, e.RepoPassword),