From 7e343a2466d2128f82b42558b091b4d06e2daaa2 Mon Sep 17 00:00:00 2001 From: Sridhar Ratnakumar <3998+srid@users.noreply.github.com> Date: Sat, 27 Jan 2024 05:33:30 -0500 Subject: [PATCH] Github self-hosted runners (#40) --- flake.nix | 1 + nixos/github-runner.nix | 93 +++++++++++++++++++++++++++++++++++++++++ secrets.json | 10 +++-- 3 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 nixos/github-runner.nix diff --git a/flake.nix b/flake.nix index e933f3f..7ec07ba 100644 --- a/flake.nix +++ b/flake.nix @@ -70,6 +70,7 @@ ./nixos/docker.nix ./nixos/lxd.nix ./nixos/jenkins.nix + ./nixos/github-runner.nix ]; services.tailscale.enable = true; sops.defaultSopsFile = ./secrets.json; diff --git a/nixos/github-runner.nix b/nixos/github-runner.nix new file mode 100644 index 0000000..1b590af --- /dev/null +++ b/nixos/github-runner.nix @@ -0,0 +1,93 @@ +/* Module for setting up personal github runners + + TODOs + + - [ ] Run runners in containers + - [ ] 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? + +*/ +{ pkgs, lib, config, ... }: +let + inherit (lib) types; + getRunnerUser = name: + # systemd DynamicUser + "github-runner-${name}"; +in +{ + options = { + services.personal-github-runners = lib.mkOption { + default = { }; + type = types.submodule { + options = { + owner = lib.mkOption { + type = types.str; + default = "srid"; + }; + repositories = lib.mkOption { + type = types.listOf types.str; + default = [ + # My repositories configured to use self-hosted runners + # + # For each entry, make sure the token exists in secrets.json (use + # the `gh` command above to create this token from CLI) + "emanote" + "haskell-flake" + ]; + }; + 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 + ]; + extraLabels = [ "nixos" ]; + }; + }; + }; + }; + }; + }; + config = + let + cfg = config.services.personal-github-runners; + in + { + sops.secrets = lib.listToAttrs (builtins.map + (name: lib.nameValuePair "${cfg.sopsPrefix}/${name}" { + mode = "0440"; + }) + cfg.repositories); + + # TODO: Run inside container + services.github-runners = lib.listToAttrs (builtins.map + (name: lib.nameValuePair name (cfg.runnerConfig // { + enable = true; + tokenFile = config.sops.secrets."${cfg.sopsPrefix}/${name}".path; + url = "https://github.com/${cfg.owner}/${name}"; + })) + cfg.repositories); + + nix.settings.trusted-users = + lib.mapAttrsToList + (name: runner: + if runner.user == null + then getRunnerUser name + else runner.user) + config.services.github-runners; + }; +} diff --git a/secrets.json b/secrets.json index 9e5d151..cd74a48 100644 --- a/secrets.json +++ b/secrets.json @@ -1,4 +1,8 @@ { + "gh-selfhosted-tokens": { + "emanote": "ENC[AES256_GCM,data:NijPIoBgcRrp5zFsT48NthT6CjJUofv1aYv+3HA=,iv:W2e5y3vqMFL/rBKQ79fV89f+piUY4HI8GrETbj2NPq8=,tag:geiipLY0dmrMQJyRy2zidg==,type:str]", + "haskell-flake": "ENC[AES256_GCM,data:v3vTEuu7F8z3BmxGzjlMa/T6RSAtSyObDSDZIes=,iv:Z5NKQm3lGQw2hVVViPYKs9F2pYIw30sY9DZjws2odDg=,tag:oMPX0R3Yjsb7/19gznDmvA==,type:str]" + }, "jenkins-nix-ci": { "ssh-key": { "public_unencrypted": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCvFRiidXbhBfjIAsDFg72+GT4JxY7xorb/+6KnHoudks4ezhSsieNZRABvYZwJG5GZyCb3a49UFtihStEIlKh5nUCtxVGOcuh5Mjy9Go4asYtL3ZJewa8rmAs6i1ZtLcpg/cww6mywkcMylUGsunLsZcqMh375VIVCXtvTxCPGN++kRo8yOFiCYfvsiZKj2t364qV14b1pXNUbBmZO0mmc9yP+tTKrXzcOk6QCH0AYP7KdWaaGRZbORNpMUOg5VyROW7Q00O+wPoAtg+A3ssYxGmVExLtQDGGg/PTdRVbkrhlBTDAEQ2YH09HStztJNKueBOqZT0Xw6PWCQkrMkNEV8cC95LxMgwTg5puQqfvAkEqj+iI6wxlxV6Q62yYOZSVqFv0fNlEcMWgNXIe55S8UwpPOU4ylmQlNm8IL/r8jKAiXDzS+5R1ai+Nw5BDO7JVyo/Njf5Xi+dXMKfoX38FgzDI8oA2tKRk+eVoY5EUMZ3xcySBoDAwFnKKCkWgBbjZhlMYkYHlIGmA+JAlqswp7RTXQ2aYCmcIMwBptYdo+q4P0pRdeGCs1SqIU5jUDu7C3P8Pxi+U/EBwNJ7+e/Cw1VVCvhUK3AXVm7MEXNVU53xBV8t7yIV3fTGodkzGK8AIACTy93fIiuAVG8v9adxfKBHFvN7OkyieiiMUD0Kgm/w==\n", @@ -42,10 +46,10 @@ "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZdnowOWgwcjd1VXg4SGhW\nWjZMNG81Rmg5Z01xSjN0a0NGLzFOUGVnWkN3CmoydzJuNDNnSzllVlg1L0wya0Uv\nZHJBY1RJQ0FyaXQ2bXpnMkNoTGxEQ1kKLS0tIExEcDhUc3hoaWhtdm43OExXWlNI\nTWFzSVJmQzRod2x5Y2wySXZ1S2xzclUKVLrGlm0z8MXZh5PVoXuyZDDF0D4qTtVx\nMF+ELQOsxosHq9fOqxvZq8lCxP3btvZbvR5yuDVzzlOsybAYZOwoPw==\n-----END AGE ENCRYPTED FILE-----\n" } ], - "lastmodified": "2023-05-08T19:17:56Z", - "mac": "ENC[AES256_GCM,data:hE6Bs4V0jCeQ3Yi2T6LEiMyRGWVuT4ZeJpsjsv06JYbfjAfvdx8frksFLRWcdanJjvHaxAHsPHT+l416ZYVnmTYR4YkJIYL8hoy+l4uV4JDF5TQHFW26/9HE6+xFOUp7Op2kGryJKm32a5VSAAANAeBtu2HqjVZ2Vn8KfZ5SQzI=,iv:bYUzUWODdPf5giMtH708bdOSxQ9A74mnnwe7kdYi1Bk=,tag:9cOcHxQUHIu/W08b84Fo7A==,type:str]", + "lastmodified": "2024-01-27T06:54:58Z", + "mac": "ENC[AES256_GCM,data:uF7Ap2COmE8UuKabF7+mF9t6cmC/d5MVWP9WYtFAiWHFWYpOrZAylpDczfF0msNhJM81t762e/14YRufLgYWfamQzEGvarl2lTTwSBJ1S5CX6w3L7UjaktvjetjQCeKd4RDp1j8YohJgCEtbWOG5pGsPeMFkKYzC6UqUcdgkpZM=,iv:fo8samIchi9skamqzDyXYMOyJzowFcPyCojAsTHj5OY=,tag:I+MC/Zbi9zYqkJEjdXHaiQ==,type:str]", "pgp": null, "unencrypted_suffix": "_unencrypted", - "version": "3.7.3" + "version": "3.8.1" } } \ No newline at end of file