nixos-config/nixos/github-runner.nix
Sridhar Ratnakumar ef9ed5bca5 limitations
2024-01-28 12:35:44 +05:30

150 lines
4.6 KiB
Nix

/* Module for setting up personal github runners
Limitations
- A runner can run only one job at a time: https://github.com/orgs/community/discussions/26769
- This makes sharing an org-wide runner less useful.
TODOs
- [x] Run runners in containers
- [ ] macOS runners: https://github.com/LnL7/nix-darwin/issues/582
- [ ] Support github orgs
- [ ] Unbreak cachix? https://github.com/cachix/cachix-action/issues/169
- [x] Or switch to nix-serve or attic
- [ ] Write a token creation script:
```sh
$ gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/srid/haskell-flake/actions/runners/registration-token
```
- [ ] Can we automate that to write directly to secrets.json?
*/
top@{ pkgs, lib, config, ... }:
let
inherit (lib) types;
in
{
options = {
services.personal-github-runners = lib.mkOption {
default = { };
type = types.submodule {
options = {
localAddress = lib.mkOption {
type = types.str;
description = ''
IP address of the host that will run containers.
'';
default =
(builtins.head (builtins.head (lib.attrValues config.networking.interfaces)).ipv4.addresses).address;
};
runnerUid = lib.mkOption {
type = types.int;
default = 1234;
description = ''
Shared UID between host and containers.
This allows the guest nix processes to access /nix/store of the host.
'';
};
owner = lib.mkOption {
type = types.str;
default = "srid";
};
repositories = lib.mkOption {
type = types.attrsOf types.str;
description = ''
My repositories configured to use self-hosted runners
*Before* adding an entry, make sure the token exists in
secrets.json (use the `gh` command above to create this token
from CLI)
Maps to container IP address to assign.
'';
default = {
"emanote" = "192.168.100.20";
"haskell-flake" = "192.168.100.21";
};
};
sopsPrefix = lib.mkOption {
type = types.str;
default = "gh-selfhosted-tokens";
};
runnerConfig = lib.mkOption {
type = types.lazyAttrsOf types.raw;
default = {
extraPackages = with pkgs; [
cachix
nixci
which
coreutils
docker
];
extraLabels = [ "nixos" ];
};
};
};
};
};
};
config =
let
cfg = config.services.personal-github-runners;
in
{
sops.secrets = lib.mapAttrs'
(name: _: lib.nameValuePair "${cfg.sopsPrefix}/${name}" {
mode = "0440";
})
cfg.repositories;
containers =
lib.mapAttrs'
(name: hostAddress:
let tokenFile = top.config.sops.secrets."${cfg.sopsPrefix}/${name}".path;
in lib.nameValuePair "github-runner-${name}" {
inherit (cfg) localAddress;
inherit hostAddress;
autoStart = true;
bindMounts."${tokenFile}" = {
hostPath = tokenFile;
isReadOnly = true;
};
config = { config, pkgs, ... }: {
system.stateVersion = "23.11";
users.users."github-runner-${name}" = {
uid = cfg.runnerUid;
isSystemUser = true;
group = "github-runner-${name}";
};
users.groups."github-runner-${name}" = { };
nix.settings = {
trusted-users = [ "github-runner-${name}" ]; # for cachix
experimental-features = "nix-command flakes repl-flake";
max-jobs = "auto";
};
services.github-runners."${name}" = cfg.runnerConfig // {
enable = true;
inherit tokenFile;
url = "https://github.com/${cfg.owner}/${name}";
};
};
})
cfg.repositories;
users.users."github-runner" = {
uid = cfg.runnerUid;
isSystemUser = true;
group = "github-runner";
};
users.groups.github-runner = { };
nix.settings = {
trusted-users = [ "github-runner" ];
allowed-users = [ "github-runner" ];
};
};
}