{ 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 = "13dzbcb0fi0bwam0mlf6d6ly0x90pr8sq68kzs65mszbvsd5lqjb"; }) (builtins.fetchurl { url = "https://github.com/NixOS/nixpkgs/raw/nixos-unstable/nixos/modules/services/continuous-integration/woodpecker/agents.nix"; sha256 = "14kjj9ybahmfqflvsa8p0va1z3zhliybggxd148fzz4bnjsqpsla"; }) ]; 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; virtualisation.podman.defaultNetwork.dnsname.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 ]; }; }