{ pkgs, config, name, tag, nixTag, ... }: # Based on: https://git.clan.lol/clan/clan-infra/src/branch/main/modules/web01/gitea/actions-runner.nix let forgejoUrl = "https://git.kempkens.io"; storeDepsBins = [ pkgs.attic-client pkgs.coreutils pkgs.findutils pkgs.gnugrep pkgs.gawk pkgs.git pkgs.nixVersions.stable pkgs.nix-update pkgs.bash pkgs.jq pkgs.nodejs ]; storeDeps = pkgs.runCommand "store-deps" { } '' mkdir -p $out/bin for dir in ${toString storeDepsBins}; do for bin in "$dir"/bin/*; do ln -s "$bin" "$out/bin/$(basename "$bin")" done done # Add SSL CA certs mkdir -p $out/etc/ssl/certs cp -a "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt" $out/etc/ssl/certs/ca-bundle.crt ''; in { systemd.services = { forgejo-runner-nix-image = { wantedBy = [ "multi-user.target" ]; after = [ "podman.service" ]; requires = [ "podman.service" ]; path = [ config.virtualisation.podman.package pkgs.gnutar pkgs.shadow pkgs.getent ]; script = '' set -eux -o pipefail mkdir -p etc/nix touch etc/passwd etc/group groupid=$(cut -d: -f3 < <(getent group nix-ci-user)) userid=$(cut -d: -f3 < <(getent passwd nix-ci-user)) groupadd --prefix $(pwd) --gid "$groupid" nix-ci-user emptypassword='$6$1ero.LwbisiU.h3D$GGmnmECbPotJoPQ5eoSTD6tTjKnSWZcjHoVTkxFLZP17W9hRi/XkmCiAMOfWruUwy8gMjINrBMNODc7cYEo4K.' useradd --prefix $(pwd) -p "$emptypassword" -m -d /tmp -u "$userid" -g "$groupid" -G nix-ci-user nix-ci-user cat < etc/nix/nix.conf accept-flake-config = true experimental-features = nix-command flakes NIX_CONFIG cat < etc/nsswitch.conf passwd: files mymachines systemd group: files mymachines systemd shadow: files hosts: files mymachines dns myhostname networks: files ethers: files services: files protocols: files rpc: files NSSWITCH tar -cv . | tar -tvf - tar -cv . | podman import --change "LABEL io.kempkens.keepImage=true" - forgejo-runner-nix ''; serviceConfig = { RuntimeDirectory = "forgejo-runner-nix-image"; WorkingDirectory = "/run/forgejo-runner-nix-image"; Type = "oneshot"; RemainAfterExit = true; }; }; forgejo-runner-nix = { after = [ "forgejo-runner-nix-image.service" ]; requires = [ "forgejo-runner-nix-image.service" ]; serviceConfig = { # Hardening (may overlap with DynamicUser=) # The following options are only for optimizing output of systemd-analyze AmbientCapabilities = ""; CapabilityBoundingSet = ""; # ProtectClock= adds DeviceAllow=char-rtc r DeviceAllow = ""; NoNewPrivileges = true; PrivateDevices = true; PrivateMounts = true; PrivateTmp = true; PrivateUsers = true; ProtectClock = true; ProtectControlGroups = true; ProtectHome = true; ProtectHostname = true; ProtectKernelLogs = true; ProtectKernelModules = true; ProtectKernelTunables = true; ProtectSystem = "strict"; RemoveIPC = true; RestrictNamespaces = true; RestrictRealtime = true; RestrictSUIDSGID = true; UMask = "0066"; ProtectProc = "invisible"; SystemCallFilter = [ "~@clock" "~@cpu-emulation" "~@module" "~@mount" "~@obsolete" "~@raw-io" "~@reboot" "~@swap" # needed by go? #"~@resources" "~@privileged" "~capset" "~setdomainname" "~sethostname" ]; RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" "AF_NETLINK" ]; # Needs network access PrivateNetwork = false; # Cannot be true due to Node MemoryDenyWriteExecute = false; # The more restrictive "pid" option makes `nix` commands in CI emit # "GC Warning: Couldn't read /proc/stat" # You may want to set this to "pid" if not using `nix` commands ProcSubset = "all"; # Coverage programs for compiled code such as `cargo-tarpaulin` disable # ASLR (address space layout randomization) which requires the # `personality` syscall # You may want to set this to `true` if not using coverage tooling on # compiled code LockPersonality = false; # Note that this has some interactions with the User setting; so you may # want to consult the systemd docs if using both. DynamicUser = true; }; }; }; users.users.nix-ci-user = { group = "nix-ci-user"; description = "Used for running nix-based CI jobs"; home = "/var/empty"; isSystemUser = true; }; users.groups.nix-ci-user = { }; services.gitea-actions-runner = { package = pkgs.forgejo-actions-runner; instances = { act = { enable = true; url = forgejoUrl; inherit name; tokenFile = config.age.secrets.forgejo-actions-token.path; labels = [ "${tag}:docker://ghcr.io/catthehacker/ubuntu:act-latest" ]; }; nix = { enable = true; url = forgejoUrl; name = "${name}-nix"; tokenFile = config.age.secrets.forgejo-actions-token.path; labels = [ "nix-${nixTag}:docker://forgejo-runner-nix" ]; settings = { container.options = "-e NIX_BUILD_SHELL=/bin/bash -e PAGER=cat -e PATH=/bin -e SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt --device /dev/kvm -v /nix:/nix -v ${storeDeps}/bin:/bin -v ${storeDeps}/etc/ssl:/etc/ssl --user nix-ci-user"; container.valid_volumes = [ "/nix" "${storeDeps}/bin" "${storeDeps}/etc/ssl" ]; }; }; }; }; }