diff --git a/hosts/tesla-nixos/configuration.nix b/hosts/tesla-nixos/configuration.nix index 7d5b5cb..0a3b85a 100644 --- a/hosts/tesla-nixos/configuration.nix +++ b/hosts/tesla-nixos/configuration.nix @@ -19,5 +19,164 @@ ]; }; # end isponsorblocktv }; + + boot.kernel.sysctl = { + "kernel.unprivileged_userns_clone" = 1; + }; + systemd.unified_cgroup_hierarchy = true; + # Persist GitLab Runner state on the host (tokens, cache, builds) + # so the container can be rebuilt without losing registration. + systemd.tmpfiles.rules = [ + "d /var/lib/gitlab-runner 0755 root root -" + ]; + + containers.ci = { + autoStart = true; + ephemeral = false; + + # Keep networking simple. If you want isolation, set privateNetwork = true + # and configure veth/bridge. With false it shares the host network namespace. + privateNetwork = false; + + # Podman rootless uses fuse-overlayfs → /dev/fuse must be available + allowedDevices = [ + { node = "/dev/fuse"; modifiers = [ "rwm" ]; } + ]; + + # Persist runner’s home/state and optionally cache + bindMounts = { + "/var/lib/gitlab-runner" = { + hostPath = "/var/lib/gitlab-runner"; + isReadOnly = false; + }; + # Optional: a big builds/cache dir for job artifacts + "/var/lib/gitlab-runner/builds" = { + hostPath = "/var/lib/gitlab-runner/builds"; + isReadOnly = false; + create = true; + }; + "/var/lib/gitlab-runner/cache" = { + hostPath = "/var/lib/gitlab-runner/cache"; + isReadOnly = false; + create = true; + }; + }; + + # The container runs its own NixOS config below: + config = { config, pkgs, lib, ... }: { + imports = [ ]; + + networking.hostName = "ci-nspawn"; + time.timeZone = "UTC"; + + # GitLab Runner user (will run jobs and the user-scoped Podman API) + users.users.gitlab-runner = { + isSystemUser = true; + # keep home on the persistent mount + home = "/var/lib/gitlab-runner"; + createHome = true; + shell = pkgs.bashInteractive; + extraGroups = [ "podman" "wheel" ]; + }; + users.groups.podman = { }; + + # Rootless Podman + virtualisation.podman = { + enable = true; + # Provide Docker-compatible CLI & /var/run/docker.sock shim (for rootful). + # We'll still point the runner directly at the rootless socket (recommended). + dockerCompat = true; + defaultNetwork.settings.dns_enabled = true; + }; + environment.systemPackages = with pkgs; [ + podman + fuse-overlayfs + slirp4netns + crun + skopeo + git + ]; + + # Ensure /etc/subuid /etc/subgid exist for rootless user namespace + environment.etc."subuid".text = '' + gitlab-runner:100000:65536 + ''; + environment.etc."subgid".text = '' + gitlab-runner:100000:65536 + ''; + + # Run a *user*-scoped Podman API service so GitLab Runner can talk to it. + # The socket ends up at: /run/user//podman/podman.sock + # We keep it always-on via linger below. + systemd.user.services."podman-api" = { + description = "Podman API (rootless)"; + serviceConfig = { + ExecStart = "${pkgs.podman}/bin/podman system service --time=0"; + Restart = "always"; + }; + WantedBy = [ "default.target" ]; + }; + + # Make the user session available at boot (so the user service can run) + # This is the NixOS way to call `loginctl enable-linger gitlab-runner`. + systemd.services."enable-linger-gitlab-runner" = { + description = "Enable linger for gitlab-runner"; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${pkgs.systemd}/bin/loginctl enable-linger gitlab-runner"; + # Harmless if already enabled + RemainAfterExit = true; + }; + }; + + # GitLab Runner + services.gitlab-runner = { + enable = true; + # service runs as this user so jobs share the same rootless Podman context + user = "gitlab-runner"; + + concurrent = 4; + runners = [ + { + name = "ci-nspawn-rootless-podman"; + url = "https://gitlab.com/"; # your GitLab URL + tokenFile = "/var/lib/gitlab-runner/registration-token"; # create this once + executor = "docker"; # GitLab's Docker executor (backed by Podman) + dockerImage = "alpine:3"; + dockerPrivileged = true; # often needed for DinD-like jobs; set false if you can + # Point the Docker executor at the *user* Podman socket: + environment = [ + # IMPORTANT: set to the gitlab-runner user's runtime dir + # You can find UID with: id -u gitlab-runner (in container) + "DOCKER_HOST=unix:///run/user/$(id -u gitlab-runner)/podman/podman.sock" + ]; + # Optional volumes for caching, etc. + dockerVolumes = [ + "/var/lib/gitlab-runner/cache:/cache" + ]; + # Helpful default pull behavior + dockerPullPolicy = "if-not-present"; + } + ]; + }; + + # Make sure systemd + cgroups are fully available inside the container + systemd.oomd.enable = false; # avoids noise in small containers + services.dbus.enable = true; + + # Storage tuning for rootless overlay + environment.etc."containers/storage.conf".text = '' + [storage] + driver = "overlay" + runroot = "/run/user/1000/containers" # will be per-user anyway + graphroot = "/var/lib/gitlab-runner/.local/share/containers/storage" + [storage.options] + mount_program = "${pkgs.fuse-overlayfs}/bin/fuse-overlayfs" + additionalimagestores = [] + ''; + }; # end containers.ci.config + }; # end containers.ci } # end file +