{ lib, pkgs, config, ... }: let sources = import ../../../npins; inherit (import "${sources.nix-templating}/lib.nix" { inherit pkgs; }) fileContents template_text; in { security.acme = { acceptTerms = true; defaults.email = "something@fediversity.eu"; }; users.groups = { woodpecker-server = { }; woodpecker-agent-docker = { }; }; users.users.nginx.extraGroups = [ "acme" ]; age.secrets = lib.mapAttrs (_: group: { owner = "root"; inherit group; mode = "440"; }) { woodpecker-gitea-client = "woodpecker-server"; woodpecker-gitea-secret = "woodpecker-server"; woodpecker-agent-container = "woodpecker-agent-docker"; }; # needs `sudo generate-vars` vars.settings.on-machine.enable = true; vars.generators.woodpecker-agent-secret = { runtimeInputs = [ pkgs.openssl ]; files.my-secret = { secret = true; group = "woodpecker-server"; }; script = '' openssl rand -hex 32 > "$out"/my-secret ''; }; vars.generators.woodpecker-rpc-secret = { runtimeInputs = with pkgs; [ coreutils bash ]; files.rpc-secret = { secret = true; group = "woodpecker-server"; }; # wrap in bash command to prevent `vars`' pipefail aborting half-way script = '' bash -c "tr -dc 'A-Za-z0-9\!?%=' < /dev/urandom | head -c 32 > $out/rpc-secret" ''; }; vars.generators.woodpecker = let fileNames = [ "woodpecker-gitea-client" "woodpecker-gitea-secret" "woodpecker-agent-container" ]; in { runtimeInputs = [ pkgs.coreutils pkgs.openssl ]; files = lib.genAttrs fileNames (_: { secret = true; }); script = '' ${lib.concatStringsSep "\n" ( lib.lists.map (file: ''cp ${config.age.secrets.${file}.path} "$out/"'') fileNames )} ''; }; # enable git-lfs programs.git = { enable = true; lfs.enable = true; }; systemd.services = { woodpecker-server.serviceConfig = { EnvironmentFile = lib.mkForce "-/tmp/woodpecker-server.conf"; ExecStartPre = "${ template_text { # FIXME find a place less public outPath = "/tmp/woodpecker-server.conf"; # https://woodpecker-ci.org/docs/administration/configuration/server text = '' WOODPECKER_DATABASE_DRIVER=sqlite3 WOODPECKER_DISABLE_USER_AGENT_REGISTRATION=false WOODPECKER_OPEN=false WOODPECKER_ADMIN=kiara,fricklerhandwerk,niols WOODPECKER_HOST=https://woodpecker.fediversity.eu WOODPECKER_GITEA=true WOODPECKER_GITEA_URL=https://git.fediversity.eu WOODPECKER_GITEA_CLIENT=${fileContents config.vars.generators.woodpecker.files.woodpecker-gitea-client.path} WOODPECKER_GITEA_SECRET=${fileContents config.vars.generators.woodpecker.files.woodpecker-gitea-secret.path} WOODPECKER_AGENT_SECRET=${fileContents config.vars.generators.woodpecker-agent-secret.files.my-secret.path} WOODPECKER_GRPC_SECRET=${fileContents config.vars.generators.woodpecker-rpc-secret.files.rpc-secret.path} WOODPECKER_LOG_LEVEL=info WOODPECKER_DEFAULT_CLONE_PLUGIN=docker.io/woodpeckerci/plugin-git WOODPECKER_SERVER_ADDR=:8000 WOODPECKER_GRPC_ADDR=:9000 ''; name = "write"; } }/bin/write"; }; woodpecker-agent-docker.serviceConfig = { EnvironmentFile = lib.mkForce "-/tmp/woodpecker-agent-podman.conf"; ExecStartPre = "${ template_text { # FIXME find a place less public outPath = "/tmp/woodpecker-agent-podman.conf"; # https://woodpecker-ci.org/docs/administration/configuration/backends/docker#environment-variables # https://woodpecker-ci.org/docs/administration/configuration/agent text = '' WOODPECKER_SERVER=localhost:9000 WOODPECKER_USERNAME=x-oauth-basic WOODPECKER_HOSTNAME=https://woodpecker.fediversity.eu WOODPECKER_MAX_WORKFLOWS=5 WOODPECKER_LOG_LEVEL=info WOODPECKER_DEBUG_PRETTY=true WOODPECKER_DEBUG_NOCOLOR=false WOODPECKER_GRPC_SECURE=true WOODPECKER_AGENT_SECRET=${fileContents config.vars.generators.woodpecker.files.woodpecker-agent-container.path} WOODPECKER_BACKEND=docker WOODPECKER_AGENT_LABELS=type=docker DOCKER_HOST=unix:///run/podman/podman.sock ''; name = "write"; } }/bin/write"; }; }; services = { nginx = { enable = true; recommendedProxySettings = true; recommendedOptimisation = true; recommendedTlsSettings = true; virtualHosts."woodpecker.fediversity.eu" = { enableACME = true; # forceSSL = true; locations."/" = { recommendedProxySettings = true; proxyPass = "http://127.0.0.1:8000"; }; }; }; woodpecker-server.enable = true; # https://woodpecker-ci.org/docs/administration/configuration/agent woodpecker-agents.agents = { docker = { enable = true; extraGroups = [ "podman" "woodpecker-agent-docker" ]; }; }; }; networking = { firewall = { enable = lib.mkForce true; allowedTCPPorts = [ 22 80 443 8000 9000 ]; # needed for podman to be able to talk over dns interfaces."podman+" = { allowedUDPPorts = [ 53 ]; allowedTCPPorts = [ 53 ]; }; }; # helps make sure DNS resolves from the containers nftables.enable = lib.mkForce false; }; virtualisation.podman = { enable = true; autoPrune = { enable = true; dates = "weekly"; }; defaultNetwork.settings = { dns_enabled = true; ipv6_enabled = true; }; }; systemd.services = { woodpecker-agent-docker = { wants = [ "podman.socket" ]; after = [ "podman.socket" ]; }; }; }