{ config, pkgs, lib, ... }: # I gave up writing this lol with lib; let cfg = config.services.woodpecker; droneserver = config.users.users.droneserver.name; in { options = { enable = mkEnableOption "Woodpecker CI/CD"; user = mkOption { type = types.str; default = "woodpeckerserver"; description = "User account under which woodpecker server runs."; }; group = mkOption { type = types.str; default = "woodpeckerserver"; description = "Group account under which woodpecker server runs."; }; hostname = mkOption { type = types.str; example = "woodpecker.example.com"; description = "VirtualHost created for nginx"; }; }; config = mkIf cfg.enable { users.users = optionalAttrs (cfg.user == name) { ${name} = { group = cfg.group; description = "woodpecker server user"; home = cfg.dataDir; createHome = true; }; }; users.groups = optionalAttrs (cfg.group == name) { ${name}.gid = config.ids.gids.headphones; }; services.nginx.virtualHosts."drone.my-server.tld" = { enableACME = true; forceSSL = true; locations."/".proxyPass = "http://localhost:3030/"; }; services.postgresql = { ensureDatabases = [ droneserver ]; ensureUsers = [{ name = droneserver; ensurePermissions = { "DATABASE ${droneserver}" = "ALL PRIVILEGES"; }; }]; }; # Secrets configured: # - DRONE_GITEA_CLIENT_ID # - DRONE_GITEA_CLIENT_SECRET # - DRONE_RPC_SECRET # To get these secrets, please check Drone's documentation for Gitea integration: # https://docs.drone.io/server/provider/gitea/ # agenix secret systemd.services.drone-server = { wantedBy = [ "multi-user.target" ]; serviceConfig = { EnvironmentFile = [ config.sops.secrets.drone.path ]; Environment = [ "DRONE_DATABASE_DATASOURCE=postgres:///droneserver?host=/run/postgresql" "DRONE_DATABASE_DRIVER=postgres" "DRONE_SERVER_PORT=:3030" "DRONE_USER_CREATE=username:viperML,admin:true" # set your admin username "DRONE_GITEA_SERVER=https://git.my-domain.tld" "DRONE_SERVER_HOST=drone.my-domain.tld" "DRONE_SERVER_PROTO=https" ]; ExecStart = "${pkgs.drone}/bin/drone-server"; User = droneserver; Group = droneserver; }; }; ### Docker runner users.users.drone-runner-docker = { isSystemUser = true; group = "drone-runner-docker"; }; users.groups.drone-runner-docker = { }; # Allow the runner to use docker users.groups.docker.members = [ "drone-runner-docker" ]; systemd.services.drone-runner-docker = { enable = true; wantedBy = [ "multi-user.target" ]; ### MANUALLY RESTART SERVICE IF CHANGED restartIfChanged = false; serviceConfig = { Environment = [ "DRONE_RPC_PROTO=http" "DRONE_RPC_HOST=localhost:3030" "DRONE_RUNNER_CAPACITY=2" "DRONE_RUNNER_NAME=drone-runner-docker" ]; EnvironmentFile = [ config.sops.secrets.drone.path ]; ExecStart = "${pkgs.drone-runner-docker}/bin/drone-runner-docker"; User = "drone-runner-docker"; Group = "drone-runner-docker"; }; }; ### Exec runner users.users.drone-runner-exec = { isSystemUser = true; group = "drone-runner-exec"; }; users.groups.drone-runner-exec = { }; # Allow the exec runner to write to build with nix nix.allowedUsers = [ "drone-runner-exec" ]; systemd.services.drone-runner-exec = { enable = true; wantedBy = [ "multi-user.target" ]; ### MANUALLY RESTART SERVICE IF CHANGED restartIfChanged = true; confinement.enable = true; confinement.packages = [ pkgs.git pkgs.gnutar pkgs.bash pkgs.nixFlakes pkgs.gzip ]; path = [ pkgs.git pkgs.gnutar pkgs.bash pkgs.nixFlakes pkgs.gzip ]; serviceConfig = { Environment = [ "DRONE_RPC_PROTO=http" "DRONE_RPC_HOST=127.0.0.1:3030" "DRONE_RUNNER_CAPACITY=2" "DRONE_RUNNER_NAME=drone-runner-exec" "NIX_REMOTE=daemon" "PAGER=cat" "DRONE_DEBUG=true" ]; BindPaths = [ "/nix/var/nix/daemon-socket/socket" "/run/nscd/socket" # "/var/lib/drone" ]; BindReadOnlyPaths = [ "/etc/passwd:/etc/passwd" "/etc/group:/etc/group" "/nix/var/nix/profiles/system/etc/nix:/etc/nix" "${config.environment.etc."ssl/certs/ca-certificates.crt".source}:/etc/ssl/certs/ca-certificates.crt" "${config.environment.etc."ssh/ssh_known_hosts".source}:/etc/ssh/ssh_known_hosts" "${builtins.toFile "ssh_config" '' Host git.ayats.org ForwardAgent yes ''}:/etc/ssh/ssh_config" "/etc/machine-id" "/etc/resolv.conf" "/nix/" ]; EnvironmentFile = [ config.sops.secrets.drone.path ]; ExecStart = "${pkgs.drone-runner-exec}/bin/drone-runner-exec"; User = "drone-runner-exec"; Group = "drone-runner-exec"; }; }; };