Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Blame · packaging/systemd/vole-runner.service

Line attribution on main · 72 line(s)

d0d4239f
Keenan Nemetz
3d ago
1 [Unit]
2 Description=Vole CI runner
ed03b3d1
Keenan Nemetz
4h ago
3 Documentation=https://rodent.software/vole
d0d4239f
Keenan Nemetz
3d ago
4 After=network-online.target
5 Wants=network-online.target
6
7 # An instance that is down, or a name that does not resolve yet, is not a reason
8 # to give up on the machine: the runner waits and tries again.
9 StartLimitIntervalSec=0
10
11 [Service]
12 Type=simple
13
14 # A dedicated unprivileged account with a home directory and a subuid and subgid
15 # range, so the container runtime is rootless. docs/deploy/runner.md has the two
16 # commands that set it up. The instance's own account is not this one: a job that
17 # escapes its container should not find the forge's data on the same machine.
18 User=ci-runner
19 Group=ci-runner
20 Environment=HOME=/var/lib/vole-runner
21 WorkingDirectory=/var/lib/vole-runner
22 RuntimeDirectory=vole-runner
23 RuntimeDirectoryMode=0700
24 Environment=XDG_RUNTIME_DIR=/run/vole-runner
25
26 # The arguments live in a file so one unit serves every machine: --remote,
27 # --label, --dir, --known-hosts, --container-network. See the example shipped as
28 # /etc/vole/runner.env.
29 EnvironmentFile=-/etc/vole/runner.env
30 ExecStartPre=/bin/sh -c 'test -n "$VOLE_RUNNER_ARGS" || { echo "runner is not configured: set VOLE_RUNNER_ARGS in /etc/vole/runner.env" >&2; exit 1; }'
31 ExecStart=/usr/bin/vole runner $VOLE_RUNNER_ARGS
32
33 Restart=on-failure
34 RestartSec=10s
35 TimeoutStopSec=60s
36
37 # Rootless podman creates a cgroup per container, which it can only do if this
38 # service's own cgroup is delegated to it.
39 Delegate=yes
40
4e3759da
Keenan Nemetz
2h ago
41 # The backstop under the container limits. Each job gets --container-memory, and this
42 # bounds the whole runner including every job in flight, for the case where a job gets
43 # past its own cgroup: a percentage is of the machine, so the unit does not have to
44 # know how big it is. Size --jobs times --container-memory below it, and leave the rest
45 # for the kernel and the runtime's own storage. TasksMax is deliberately not set: the
46 # container's own --container-pids already applies to everything the runner starts,
47 # and a unit-level value would have to track --jobs and --container-pids, failing
48 # builds in a way that looks like the workflow's fault when it drifts.
49 MemoryMax=90%
50
d0d4239f
Keenan Nemetz
3d ago
51 # A core dump of this process is a copy of the runner's SSH key, which leases jobs
52 # and reports their results.
53 LimitCORE=0
54 LimitNOFILE=65536
55 UMask=0027
56 PrivateTmp=true
57
58 # Deliberately less sandboxed than vole.service: the isolation a job gets is its
59 # container, and the runtime needs user namespaces and a writable home to build
60 # one. Nothing here reaches the instance's data, because it is not on this
61 # machine.
9704d735
Keenan Nemetz
3h ago
62 #
63 # NoNewPrivileges is off for the same reason, and it is the one setting the unit
64 # cannot keep. Rootless podman, Docker, and nerdctl all map the calling user into
65 # the container through setuid newuidmap and newgidmap, and this setting stops a
66 # setuid helper from gaining privilege, so the mapping fails before a container
67 # exists: "newuidmap: write to uid_map failed: Operation not permitted". A job's
68 # isolation is its container, not this sandbox, so the rest of the hardening stays.
69 NoNewPrivileges=false
d0d4239f
Keenan Nemetz
3d ago
70
71 [Install]
72 WantedBy=multi-user.target