chore(runner): mount /opt/familienarchiv into job containers

The live runner config was missing /opt/familienarchiv in valid_volumes
and options, so deploy steps wrote files into the ephemeral job
container rather than the host — silently discarded on exit.

Updated /root/docker/gitea/runner-config.yaml on the server and
restarted gitea-runner. Repo file now matches the server exactly,
including the network: gitea_gitea setting that was previously
only on the server.

DEPLOYMENT.md: clarifies that /opt/familienarchiv does not need to be
in the runner container's own volumes (DooD spawns job containers from
the host daemon directly); updates restart command from systemctl to
docker restart; narrows the cp-r stale-file note to manual ops only
(CI uses rm -rf before copying).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-05-16 10:19:09 +02:00
parent 55ccd5f3c0
commit 134f1e2ae0
2 changed files with 26 additions and 31 deletions

View File

@@ -1,33 +1,26 @@
# runner-config.yaml — only the relevant section
container:
# passed as DOCKER_HOST inside the job container
# join the same network Gitea is on, so job containers can resolve 'gitea'
# for actions/checkout and other internal API calls.
network: gitea_gitea
# passed as DOCKER_HOST inside the job container; act_runner auto-mounts
# this socket path into the job, so no explicit -v option is needed.
docker_host: "unix:///var/run/docker.sock"
# Job workspaces are stored here on the NAS and mounted at the same
# absolute path inside job containers. Identical host container path
# is the requirement: Docker Compose resolves relative bind mounts to
# $(pwd) inside the job container and passes that absolute path to the
# host daemon — the daemon must find the file at that exact host path.
# Prerequisite: mkdir -p /srv/gitea-workspace on the host, and add
# - /srv/gitea-workspace:/srv/gitea-workspace
# to the runner service volumes in gitea's compose.yaml.
# Job workspaces are stored here and mounted at the same absolute path
# inside job containers. Identical host <-> container path is the requirement:
# Compose resolves relative bind mounts to $(pwd) inside the job container
# and passes that absolute path to the host daemon, which must find the file
# at that exact host path. Prerequisite: /srv/gitea-workspace exists on the
# host and is bind-mounted in the runner container (see compose.yaml).
workdir_parent: /srv/gitea-workspace
# whitelists volumes that workflow steps may bind-mount
valid_volumes:
- "/var/run/docker.sock"
- "/srv/gitea-workspace"
- "/opt/familienarchiv"
# appended to `docker run` when the runner spawns a job container
# SECURITY WARNING: This mount configuration grants CI job containers:
# 1. Root-equivalent access to the host Docker daemon (via the socket).
# 2. Read/write access to /opt/familienarchiv/ — including the main app's
# compose files, Caddy config, and observability configs. A malicious
# workflow step could overwrite any file in that directory.
# Both are acceptable ONLY because this runner is single-tenant: it executes
# code exclusively from this private repo with a fixed set of trusted authors.
# WARNING: Do NOT add this runner to any repo with external contributors or
# untrusted PRs — the blast radius includes the entire production deployment.
# See ADR-016 for the reasoning behind the /opt/familienarchiv mount.
options: "-v /var/run/docker.sock:/var/run/docker.sock -v /srv/gitea-workspace:/srv/gitea-workspace -v /opt/familienarchiv:/opt/familienarchiv"
# keep network mode default (bridge) — Testcontainers handles its own networking
# mount the workspace and the permanent obs/config directory into job containers.
# /opt/familienarchiv is the stable path CI copies configs to (ADR-016); it must
# be mounted here so deploy steps can write through to the host filesystem.
options: "-v /srv/gitea-workspace:/srv/gitea-workspace -v /opt/familienarchiv:/opt/familienarchiv"
# keep behavior default — Testcontainers handles its own networking
force_pull: false