1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8let
9 cfg = config.services.woodpecker-server;
10in
11{
12 meta.maintainers = with lib.maintainers; [ ambroisie ];
13
14 options = {
15 services.woodpecker-server = {
16 enable = lib.mkEnableOption "the Woodpecker-Server, a CI/CD application for automatic builds, deployments and tests";
17 package = lib.mkPackageOption pkgs "woodpecker-server" { };
18 environment = lib.mkOption {
19 default = { };
20 type = lib.types.attrsOf lib.types.str;
21 example = lib.literalExpression ''
22 {
23 WOODPECKER_HOST = "https://woodpecker.example.com";
24 WOODPECKER_OPEN = "true";
25 WOODPECKER_GITEA = "true";
26 WOODPECKER_GITEA_CLIENT = "ffffffff-ffff-ffff-ffff-ffffffffffff";
27 WOODPECKER_GITEA_URL = "https://git.example.com";
28 }
29 '';
30 description = "woodpecker-server config environment variables, for other options read the [documentation](https://woodpecker-ci.org/docs/administration/server-config)";
31 };
32 environmentFile = lib.mkOption {
33 type = with lib.types; coercedTo path (f: [ f ]) (listOf path);
34 default = [ ];
35 example = [ "/root/woodpecker-server.env" ];
36 description = ''
37 File to load environment variables
38 from. This is helpful for specifying secrets.
39 Example content of environmentFile:
40 ```
41 WOODPECKER_AGENT_SECRET=your-shared-secret-goes-here
42 WOODPECKER_GITEA_SECRET=gto_**************************************
43 ```
44 '';
45 };
46 };
47 };
48
49 config = lib.mkIf cfg.enable {
50 systemd.services = {
51 woodpecker-server = {
52 description = "Woodpecker-Server Service";
53 wantedBy = [ "multi-user.target" ];
54 after = [ "network-online.target" ];
55 wants = [ "network-online.target" ];
56 serviceConfig = {
57 DynamicUser = true;
58 WorkingDirectory = "%S/woodpecker-server";
59 StateDirectory = "woodpecker-server";
60 StateDirectoryMode = "0700";
61 UMask = "0007";
62 ConfigurationDirectory = "woodpecker-server";
63 EnvironmentFile = cfg.environmentFile;
64 ExecStart = "${cfg.package}/bin/woodpecker-server";
65 Restart = "on-failure";
66 RestartSec = 15;
67 CapabilityBoundingSet = "";
68 # Security
69 NoNewPrivileges = true;
70 # Sandboxing
71 ProtectSystem = "strict";
72 ProtectHome = true;
73 PrivateTmp = true;
74 PrivateDevices = true;
75 PrivateUsers = true;
76 ProtectHostname = true;
77 ProtectClock = true;
78 ProtectKernelTunables = true;
79 ProtectKernelModules = true;
80 ProtectKernelLogs = true;
81 ProtectControlGroups = true;
82 RestrictAddressFamilies = [ "AF_UNIX AF_INET AF_INET6" ];
83 LockPersonality = true;
84 MemoryDenyWriteExecute = true;
85 RestrictRealtime = true;
86 RestrictSUIDSGID = true;
87 PrivateMounts = true;
88 # System Call Filtering
89 SystemCallArchitectures = "native";
90 SystemCallFilter = "~@clock @privileged @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @setuid @swap";
91 };
92 inherit (cfg) environment;
93 };
94 };
95 };
96}