# This is a NixOS module to allow a machine to act as an integration test # runner. This is used for the end-to-end VM test suite. { lib, config, pkgs, ... }: { # The GitHub Actions self-hosted runner service. services.github-runner = { enable = true; url = "https://github.com/tailscale/tailscale"; replace = true; extraLabels = [ "vm_integration_test" ]; # Justifications for the packages: extraPackages = with pkgs; [ # The test suite is written in Go. go # This contains genisoimage, which is needed to create cloud-init # seeds. cdrkit # This package is the virtual machine hypervisor we use in tests. qemu # This package contains tools like `ssh-keygen`. openssh # The C compiler so cgo builds work. gcc # The package manager Nix, just in case. nix # Used to generate a NixOS image for testing. nixos-generators # Used to extract things. gnutar # Used to decompress things. lzma ]; # Customize this to include your GitHub username so we can track # who is running which node. name = "YOUR-GITHUB-USERNAME-tstest-integration-vms"; # Replace this with the path to the GitHub Actions runner token on # your disk. tokenFile = "/run/decrypted/ts-oss-ghaction-token"; }; # A user account so there is a home directory and so they have kvm # access. Please don't change this account name. users.users.ghrunner = { createHome = true; isSystemUser = true; extraGroups = [ "kvm" ]; }; # The default github-runner service sets a lot of isolation features # that attempt to limit the damage that malicious code can use. # Unfortunately we rely on some "dangerous" features to do these tests, # so this shim will peel some of them away. systemd.services.github-runner = { serviceConfig = { # We need access to /dev to poke /dev/kvm. PrivateDevices = lib.mkForce false; # /dev/kvm is how qemu creates a virtual machine with KVM. DeviceAllow = lib.mkForce [ "/dev/kvm" ]; # Ensure the service has KVM permissions with the `kvm` group. ExtraGroups = [ "kvm" ]; # The service runs as a dynamic user by default. This makes it hard # to persistently store things in /var/lib/ghrunner. This line # disables the dynamic user feature. DynamicUser = lib.mkForce false; # Run this service as our ghrunner user. User = "ghrunner"; # We need access to /var/lib/ghrunner to store VM images. ProtectSystem = lib.mkForce null; }; }; }