base16-schemes: unstable-2024-06-21 -> unstable-2024-11-12
[NixPkgs.git] / nixos / modules / services / misc / renovate.nix
blob9fbd8ec9e1acbedc783c4ac71ead21cbb9d7f0db
2   config,
3   lib,
4   pkgs,
5   ...
6 }:
7 let
8   inherit (lib)
9     mkEnableOption
10     mkPackageOption
11     mkOption
12     types
13     mkIf
14     ;
15   json = pkgs.formats.json { };
16   cfg = config.services.renovate;
17   generateValidatedConfig =
18     name: value:
19     pkgs.callPackage (
20       { runCommand, jq }:
21       runCommand name
22         {
23           nativeBuildInputs = [
24             jq
25             cfg.package
26           ];
27           value = builtins.toJSON value;
28           passAsFile = [ "value" ];
29           preferLocalBuild = true;
30         }
31         ''
32           jq . "$valuePath"> $out
33           renovate-config-validator $out
34         ''
35     ) { };
36   generateConfig = if cfg.validateSettings then generateValidatedConfig else json.generate;
39   meta.maintainers = with lib.maintainers; [ marie natsukium ];
41   options.services.renovate = {
42     enable = mkEnableOption "renovate";
43     package = mkPackageOption pkgs "renovate" { };
44     schedule = mkOption {
45       type = with types; nullOr str;
46       description = "How often to run renovate. See {manpage}`systemd.time(7)` for the format.";
47       example = "*:0/10";
48       default = null;
49     };
50     credentials = mkOption {
51       type = with types; attrsOf path;
52       description = ''
53         Allows configuring environment variable credentials for renovate, read from files.
54         This should always be used for passing confidential data to renovate.
55       '';
56       example = {
57         RENOVATE_TOKEN = "/etc/renovate/token";
58       };
59       default = { };
60     };
61     runtimePackages = mkOption {
62       type = with types; listOf package;
63       description = "Packages available to renovate.";
64       default = [ ];
65     };
66     validateSettings = mkOption {
67       type = types.bool;
68       default = true;
69       description = "Weither to run renovate's config validator on the built configuration.";
70     };
71     settings = mkOption {
72       type = json.type;
73       default = { };
74       example = {
75         platform = "gitea";
76         endpoint = "https://git.example.com";
77         gitAuthor = "Renovate <renovate@example.com>";
78       };
79       description = ''
80         Renovate's global configuration.
81         If you want to pass secrets to renovate, please use {option}`services.renovate.credentials` for that.
82       '';
83     };
84   };
86   config = mkIf cfg.enable {
87     services.renovate.settings = {
88       cacheDir = "/var/cache/renovate";
89       baseDir = "/var/lib/renovate";
90     };
92     systemd.services.renovate = {
93       description = "Renovate dependency updater";
94       documentation = [ "https://docs.renovatebot.com/" ];
95       after = [ "network.target" ];
96       startAt = lib.optional (cfg.schedule != null) cfg.schedule;
97       path = [
98         config.systemd.package
99         pkgs.git
100       ] ++ cfg.runtimePackages;
102       serviceConfig = {
103         User = "renovate";
104         Group = "renovate";
105         DynamicUser = true;
106         LoadCredential = lib.mapAttrsToList (name: value: "SECRET-${name}:${value}") cfg.credentials;
107         Restart = "on-failure";
108         CacheDirectory = "renovate";
109         StateDirectory = "renovate";
111         # Hardening
112         CapabilityBoundingSet = [ "" ];
113         DeviceAllow = [ "" ];
114         LockPersonality = true;
115         PrivateDevices = true;
116         PrivateUsers = true;
117         ProcSubset = "pid";
118         ProtectClock = true;
119         ProtectControlGroups = true;
120         ProtectHome = true;
121         ProtectHostname = true;
122         ProtectKernelLogs = true;
123         ProtectKernelModules = true;
124         ProtectKernelTunables = true;
125         ProtectProc = "invisible";
126         RestrictAddressFamilies = [
127           "AF_INET"
128           "AF_INET6"
129           "AF_UNIX"
130         ];
131         RestrictNamespaces = true;
132         RestrictRealtime = true;
133         SystemCallArchitectures = "native";
134         UMask = "0077";
135       };
137       script = ''
138         ${lib.concatStringsSep "\n" (
139           builtins.map (name: "export ${name}=$(systemd-creds cat 'SECRET-${name}')") (
140             lib.attrNames cfg.credentials
141           )
142         )}
143         exec ${lib.escapeShellArg (lib.getExe cfg.package)}
144       '';
146       environment = {
147         RENOVATE_CONFIG_FILE = generateConfig "renovate-config.json" cfg.settings;
148         HOME = "/var/lib/renovate";
149       };
150     };
151   };