|
2 | 2 | config, |
3 | 3 | lib, |
4 | 4 | pkgs, |
5 | | - utils, |
6 | 5 | ... |
7 | 6 | }: |
8 | 7 |
|
|
26 | 25 | types |
27 | 26 | ; |
28 | 27 |
|
29 | | - inherit (utils) |
30 | | - escapeSystemdPath |
31 | | - ; |
32 | | - |
33 | 28 | cfg = config.services.forgejo.runner; |
34 | 29 |
|
35 | 30 | settingsFormat = pkgs.formats.yaml { }; |
|
92 | 87 | ''; |
93 | 88 | type = attrsOf ( |
94 | 89 | submodule ( |
95 | | - { name, ... }: |
| 90 | + { config, name, ... }: |
96 | 91 | { |
97 | 92 | options = { |
98 | 93 | labels = labelsOption; |
|
109 | 104 |
|
110 | 105 | url = urlOption; |
111 | 106 |
|
| 107 | + user = mkOption { |
| 108 | + type = types.str; |
| 109 | + description = "The dynamic username of the runner service."; |
| 110 | + default = "forgejo-runner-${config.name}"; |
| 111 | + defaultText = literalExpression "forgejo-runner-\${name}"; |
| 112 | + }; |
| 113 | + |
112 | 114 | registrationTokenFile = mkOption { |
113 | 115 | type = types.nullOr (types.either types.str types.path); |
114 | 116 | default = null; |
|
233 | 235 | config = mkIf (cfg.instances != { }) { |
234 | 236 | assertions = lib.foldlAttrs ( |
235 | 237 | acc_inst: _: instance: |
| 238 | + let |
| 239 | + userNameLength = builtins.stringLength instance.user; |
| 240 | + in |
236 | 241 | (lib.foldlAttrs ( |
237 | 242 | acc_conn: name: connection: |
238 | 243 | acc_conn |
|
270 | 275 | assertion = hasDockerScheme (instanceLabels instance) -> hasDocker || hasPodman; |
271 | 276 | message = "forgejo.runner.instances.${instance.name} label configuration requires either docker or podman."; |
272 | 277 | } |
| 278 | + { |
| 279 | + assertion = userNameLength <= 31; |
| 280 | + message = ''forgejo.runner.instances.${instance.name}.user = "${instance.user}" has a length of ${toString userNameLength} which exceeds 31 character limit from systemd+glibc. Shorten instance name or explicitly define `instances.<name>.user`.''; |
| 281 | + } |
273 | 282 | ] |
274 | 283 | ) [ ] cfg.instances; |
275 | 284 |
|
|
279 | 288 | _: instance: |
280 | 289 | let |
281 | 290 | allLabels = instanceLabels instance; |
282 | | - escapedName = escapeSystemdPath instance.name; |
283 | 291 | wantsContainer = hasDockerScheme allLabels; |
284 | 292 | wantsHost = hasHostScheme allLabels; |
285 | 293 | wantsDocker = wantsContainer && hasDocker; |
286 | 294 | wantsPodman = wantsContainer && hasPodman; |
287 | | - configFile = settingsFormat.generate "forgejo-runner-${escapedName}.yaml" instance.settings; |
| 295 | + configFile = settingsFormat.generate "forgejo-runner-${instance.name}.yaml" instance.settings; |
288 | 296 | in |
289 | | - nameValuePair "forgejo-runner@${escapedName}" { |
| 297 | + nameValuePair "forgejo-runner@${instance.name}" { |
290 | 298 | overrideStrategy = "asDropin"; |
291 | 299 | inherit (instance) enable; |
292 | 300 | wants = [ |
|
308 | 316 | path = [ pkgs.coreutils ] ++ lib.optionals wantsHost instance.hostPackages; |
309 | 317 |
|
310 | 318 | serviceConfig = { |
| 319 | + User = instance.user; |
311 | 320 | MemoryDenyWriteExecute = !wantsHost; |
312 | 321 |
|
313 | 322 | LoadCredential = |
|
317 | 326 | ++ lib.mapAttrsToList (name: value: "${name}:${value}") instance.credentials; |
318 | 327 |
|
319 | 328 | SupplementaryGroups = optionals wantsDocker [ "docker" ] ++ optionals wantsPodman [ "podman" ]; |
320 | | - ExecPaths = lib.optionals wantsHost [ "/var/lib/forgejo-runner/${escapedName}" ]; |
| 329 | + ExecPaths = lib.optionals wantsHost [ "/var/lib/forgejo-runner/${instance.name}" ]; |
321 | 330 |
|
322 | 331 | ExecStartPre = lib.optionals (instance.registrationTokenFile != null) [ |
323 | 332 | (lib.getExe ( |
324 | 333 | pkgs.writeShellApplication { |
325 | | - name = "forgejo-register-runner-${escapedName}"; |
| 334 | + name = "forgejo-register-runner-${instance.name}"; |
326 | 335 | text = '' |
327 | 336 | INSTANCE_DIR="$STATE_DIRECTORY" |
328 | 337 | mkdir -vp "$INSTANCE_DIR" |
|
0 commit comments