ci: let the runner execute what it builds
The upstream gitea-actions-runner unit uses DynamicUser, and systemd mounts a dynamic unit's state directory noexec. Measured from a job's own /proc/self/mountinfo on the live runner, with /tmp as the control: the state dir carries noexec, /tmp does not, and a script written and chmod +x'd in the workspace fails execve with EACCES while the same script in /tmp runs. This was invisible for as long as every workflow compiled inside the nix sandbox and executed nothing from the workspace. The first job that built a binary into the runner's own target dir -- an instrumented coverage run -- died on its first build script. ExecPaths= re-mounts the state dir executable. Both spellings are listed with the ignore-if-absent prefix because ExecPaths resolves against the host root, where the dynamic-user layout makes /var/lib/gitea-runner a symlink into private/.
This commit is contained in:
parent
8b845896e2
commit
5a5a4ddd15
1 changed files with 25 additions and 0 deletions
|
|
@ -355,6 +355,31 @@ in
|
|||
|
||||
systemd.services."gitea-runner-hive" = {
|
||||
path = [ pkgs.nix ];
|
||||
# A CI runner must be able to EXECUTE what it builds, and by
|
||||
# default it cannot: the upstream unit uses `DynamicUser`, and
|
||||
# systemd mounts a dynamic unit's state directory `noexec`.
|
||||
# Measured on the live runner rather than inferred — from a job's
|
||||
# own /proc/self/mountinfo:
|
||||
#
|
||||
# /var/lib/private ro,nosuid,nodev,noexec (tmpfs)
|
||||
# /var/lib/private/gitea-runner rw,nosuid,nodev,noexec,idmapped
|
||||
#
|
||||
# with /tmp as the control at rw,nosuid,nodev — no noexec, and a
|
||||
# script there executes fine. Nothing noticed for as long as every
|
||||
# workflow built inside the nix sandbox and executed nothing in the
|
||||
# workspace; the first job that compiled a build script into the
|
||||
# runner's own target dir died with EACCES on execve, reported as
|
||||
# "could not execute process ... (never executed)".
|
||||
#
|
||||
# Both spellings are listed because `ExecPaths=` resolves against
|
||||
# the HOST root, where the dynamic-user layout makes
|
||||
# /var/lib/gitea-runner a symlink into private/. The `-` prefix
|
||||
# means "ignore if absent", so whichever layout the unit ends up
|
||||
# with, the other is a no-op rather than a startup failure.
|
||||
serviceConfig.ExecPaths = [
|
||||
"-/var/lib/gitea-runner"
|
||||
"-/var/lib/private/gitea-runner"
|
||||
];
|
||||
# Trust the hive CA in Node-based actions. With self-signed TLS,
|
||||
# forgejo's ROOT_URL is `https://forge.<domain>` (CA-signed leaf),
|
||||
# so actions like `upload-artifact` — whose Node HTTP client uses
|
||||
|
|
|
|||
Loading…
Reference in a new issue