diff --git a/pp-woodpecker.nix b/pp-woodpecker.nix new file mode 100644 index 0000000..dfeb172 --- /dev/null +++ b/pp-woodpecker.nix @@ -0,0 +1,116 @@ +{ config, pkgs, lib, ... }: +with lib; +let + cfgBase = config.base; + cfg = config.services.ppWoodpecker; +in +{ + imports = [ + # Woodpeeker is not in stable yet but the module is good enought + (builtins.fetchurl { + url = "https://github.com/NixOS/nixpkgs/raw/nixos-unstable/nixos/modules/services/continuous-integration/woodpecker/server.nix"; + sha256 = "0fbgr0s690c3i90c8rmnazilh3gl9x698pm69f8lqg2glz9rq13f"; + }) + (builtins.fetchurl { + url = "https://github.com/NixOS/nixpkgs/raw/nixos-unstable/nixos/modules/services/continuous-integration/woodpecker/agents.nix"; + sha256 = "06zmmg95c2pbrl7i6vl9zypmh4hysl3hkwhqjp2ylnndddhh7ihc"; + }) + ]; + options.services.ppWoodpecker = { + serverEnvFile = mkOption { + type = types.str; + default = "/etc/woodpecker_server_env"; + description = "The file containing the env secrets WOODPECKER_AGENT_SECRET and WOODPECKER_GITEA_SECRET, cf https://woodpecker-ci.org/docs/administration/vcs/gitea#configuration for gitea"; + }; + agentEnvFile = mkOption { + type = types.str; + default = "/etc/woodpecker_agent_env"; + description = "The file containing the env secrets WOODPECKER_AGENT_SECRET"; + }; + domain = mkOption { + type = types.str; + default = "ci.${cfgBase.domainName}"; + example = "ci.example.com"; + description = "The domain of the server"; + }; + giteaDomain = mkOption { + type = types.str; + default = "git.${cfgBase.domainName}"; + example = "git.example.com"; + description = "The domain of the gitea server"; + }; + giteaClientId = mkOption { + type = types.str; + example = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"; + description = "The domain of the gitea server"; + }; + admins = mkOption { + type = lib.types.listOf lib.types.string; + default = []; + example = [ "user1" "user2" ]; + description = "List of admins"; + }; + maxProcsPerAgent = mkOption { + type = types.int; + default = 1; + example = 4; + description = "Number of possible paralle process per agent"; + }; + }; + + config = { + + services.woodpecker-server.enable = true; + # To put in woodpecker_server_env: + # ``` + # WOODPECKER_AGENT_SECRET=XXXXXX + # WOODPECKER_GITEA_SECRET=gto_XXXXXX + # ``` + services.woodpecker-server.environmentFile = "${cfg.serverEnvFile}"; + services.woodpecker-server.environment = { + WOODPECKER_HOST = "https://${cfg.domain}"; + WOODPECKER_OPEN = "true"; # This means user of gitea can connect to the ci + WOODPECKER_GITEA = "true"; + WOODPECKER_GITEA_CLIENT = "${cfg.giteaClientId}"; + WOODPECKER_GITEA_URL = "https://${cfg.giteaDomain}"; + WOODPECKER_ADMIN = lib.mkIf (cfg.admins != []) (lib.concatStringsSep "," cfg.admins); + }; + + virtualisation.podman.enable = true; + services.woodpecker-agents.agents.podman = { + enable = true; + extraGroups = [ "podman" ]; + environmentFile = [ "${cfg.agentEnvFile}" ]; + environment = { + WOODPECKER_BACKEND = "docker"; + DOCKER_HOST = "unix:////run/podman/podman.sock"; + WOODPECKER_MAX_PROCS = builtins.toString cfg.maxProcsPerAgent; + }; + }; + + security.acme.acceptTerms = true; + security.acme.defaults.email = cfgBase.adminEmail; + services.nginx = { + enable = true; + virtualHosts = { + "${cfg.domain}" = { + forceSSL = true; + enableACME = true; + locations."/" = { + proxyPass = "http://127.0.0.1:8000"; + extraConfig = '' + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Server $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $host; + proxy_pass_request_headers on; + ''; + }; + }; + }; + }; + networking.firewall.allowedTCPPorts = [ 80 443 ]; + }; +}