From 6a6db343e32eb1dc9e389df5ff5920bdff3256ed Mon Sep 17 00:00:00 2001 From: Christoph Hollizeck Date: Mon, 5 May 2025 22:59:04 +0200 Subject: [PATCH] loptland: modularize config a little by pulling out modules for gitea-runner and hydra --- .../nixos/services/gitea-runner/default.nix | 182 ++++++++++++++++++ modules/nixos/services/hydra/default.nix | 37 ++++ systems/x86_64-linux/loptland/default.nix | 65 ++----- 3 files changed, 230 insertions(+), 54 deletions(-) create mode 100644 modules/nixos/services/gitea-runner/default.nix create mode 100644 modules/nixos/services/hydra/default.nix diff --git a/modules/nixos/services/gitea-runner/default.nix b/modules/nixos/services/gitea-runner/default.nix new file mode 100644 index 0000000..b1491be --- /dev/null +++ b/modules/nixos/services/gitea-runner/default.nix @@ -0,0 +1,182 @@ +{ + lib, + config, + namespace, + pkgs, + ... +}: +with lib.${namespace}; +let + cfg = config.${namespace}.services.gitea-runner; + inherit (lib) mkIf mkOption mkEnableOption; + inherit (lib.types) + attrsOf + package + path + submodule + str + ; +in +{ + options.${namespace}.services.gitea-runner = { + enable = mkEnableOption "Enable gitea/forgejo runner"; + git-url = mkOption { + type = str; + default = "https://git.christophhollizeck.dev"; + }; + sopsFile = mkOption { + type = path; + default = lib.snowfall.fs.get-file "secrets/secrets.yaml"; + description = "SecretFile"; + }; + runner-package = mkOption { + type = package; + default = pkgs.forgejo-actions-runner; + description = "Which runner to use Gitea/Forgjo"; + }; + ## taken from nixos/modules/services/continuous-integration/gitea-actions-runner.nix + runner-instances = mkOption { + default = { }; + description = '' + Gitea Actions Runner instances. + ''; + type = attrsOf (submodule { + options = { + enable = mkEnableOption "Gitea Actions Runner instance"; + name = mkOption { + type = str; + example = literalExpression "config.networking.hostName"; + description = '' + The name identifying the runner instance towards the Gitea/Forgejo instance. + ''; + }; + url = mkOption { + type = str; + example = "https://forge.example.com"; + description = '' + Base URL of your Gitea/Forgejo instance. + ''; + }; + tokenFile = mkOption { + type = nullOr (either str path); + default = null; + description = '' + Path to an environment file, containing the `TOKEN` environment + variable, that holds a token to register at the configured + Gitea/Forgejo instance. + ''; + }; + labels = mkOption { + type = listOf str; + example = literalExpression '' + [ + # provide a debian base with nodejs for actions + "debian-latest:docker://node:18-bullseye" + # fake the ubuntu name, because node provides no ubuntu builds + "ubuntu-latest:docker://node:18-bullseye" + # provide native execution on the host + #"native:host" + ] + ''; + description = '' + Labels used to map jobs to their runtime environment. Changing these + labels currently requires a new registration token. + + Many common actions require bash, git and nodejs, as well as a filesystem + that follows the filesystem hierarchy standard. + ''; + }; + settings = mkOption { + description = '' + Configuration for `act_runner daemon`. + See https://gitea.com/gitea/act_runner/src/branch/main/internal/pkg/config/config.example.yaml for an example configuration + ''; + + type = types.submodule { + freeformType = settingsFormat.type; + }; + + default = { }; + }; + + hostPackages = mkOption { + type = listOf package; + default = with pkgs; [ + bash + coreutils + curl + gawk + gitMinimal + gnused + nodejs + wget + ]; + defaultText = literalExpression '' + with pkgs; [ + bash + coreutils + curl + gawk + gitMinimal + gnused + nodejs + wget + ] + ''; + description = '' + List of packages, that are available to actions, when the runner is configured + with a host execution label. + ''; + }; + }; + }); + }; + }; + + config = mkIf cfg.enable { + sops = { + secrets = { + "forgejo/runner/token" = { + inherit (cfg) sopsFile; + }; + }; + }; + + services.gitea-actions-runner = { + package = cfg.runner-package; + instances = { + native = { + enable = true; + name = "monolith"; + url = cfg.git-url; + tokenFile = config.sops.secrets."forgejo/runner/token".path; + labels = [ + "native:host" + ]; + hostPackages = with pkgs; [ + bash + coreutils + curl + gawk + gitMinimal + gnused + nodejs + wget + lix + ]; + settings = { + log.level = "info"; + runner = { + capacity = 1; + timeout = "3h"; + shutdown_timeout = "5s"; + fetch_timeout = "10s"; + fetch_inteval = "5s"; + }; + }; + }; + } // cfg.runner-instances; + }; + + }; +} diff --git a/modules/nixos/services/hydra/default.nix b/modules/nixos/services/hydra/default.nix new file mode 100644 index 0000000..b72696e --- /dev/null +++ b/modules/nixos/services/hydra/default.nix @@ -0,0 +1,37 @@ +{ + lib, + config, + namespace, + ... +}: +let + cfg = config.${namespace}.services.hydra; + inherit (lib) mkIf mkOption mkEnableOption; +in +{ + options.${namespace}.services.hydra = { + enable = mkEnableOption "Enable Hydra CI"; + httpPort = mkOption { + type = lib.types.int; + default = 2000; + description = "The path to host the http server on, relevant for nginx forwarding"; + }; + + enableCache = mkEnableOption "Enable cache using nix-server"; + }; + + config = mkIf cfg.enable { + services.nix-serve = mkIf cfg.enableCache { + enable = true; + secretKeyFile = "/var/cache-priv-key.pem"; + }; + + services.hydra = { + enable = true; + hydraURL = "http://localhost:${toString cfg.httpPort}"; + port = cfg.httpPort; + notificationSender = "hydra@localhost"; + useSubstitutes = true; + }; + }; +} diff --git a/systems/x86_64-linux/loptland/default.nix b/systems/x86_64-linux/loptland/default.nix index 5698701..0434742 100644 --- a/systems/x86_64-linux/loptland/default.nix +++ b/systems/x86_64-linux/loptland/default.nix @@ -35,9 +35,6 @@ in "forgejo/mail/passwordHash" = { inherit sopsFile; }; - "forgejo/runner/token" = { - inherit sopsFile; - }; }; }; @@ -55,7 +52,7 @@ in }; }; - "hydra.${domainName}" = { + "hydra.${domainName}" = mkIf config.${namespace}.services.hydra.enable { forceSSL = cfg.enableAcme; useACMEHost = mkIf cfg.enableAcme domainName; @@ -78,7 +75,7 @@ in }; }; - "nixcache.${domainName}" = { + "nixcache.${domainName}" = mkIf config.${namespace}.services.hydra.enableCache { forceSSL = cfg.enableAcme; useACMEHost = mkIf cfg.enableAcme domainName; @@ -180,60 +177,11 @@ in ]; }; - services.nix-serve = { - enable = true; - secretKeyFile = "/var/cache-priv-key.pem"; - }; - - services.hydra = { - enable = true; - hydraURL = "http://localhost:${toString hydraPort}"; - port = hydraPort; - notificationSender = "hydra@localhost"; - useSubstitutes = true; - }; - services.tailscale = { enable = true; useRoutingFeatures = "client"; }; - services.gitea-actions-runner = { - package = pkgs.forgejo-actions-runner; - instances = { - native = { - enable = true; - name = "monolith"; - url = "https://git.${domainName}"; - tokenFile = config.sops.secrets."forgejo/runner/token".path; - labels = [ - "native:host" - ]; - hostPackages = with pkgs; [ - bash - coreutils - curl - gawk - gitMinimal - gnused - nodejs - wget - lix - ]; - settings = { - log.level = "info"; - runner = { - capacity = 1; - timeout = "3h"; - shutdown_timeout = "5s"; - fetch_timeout = "10s"; - fetch_inteval = "5s"; - }; - }; - }; - }; - }; - networking.firewall.allowedTCPPorts = [ forgejoPort 80 @@ -251,6 +199,15 @@ in inherit sopsFile; }; openssh = enabled; + hydra = { + enable = true; + httpPort = hydraPort; + enableCache = true; + }; + gitea-runner = { + enable = true; + inherit sopsFile; + }; }; security = {