grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / misc / renovate.nix
blob9062b7424b6811a93deaf7817c865a70bc0409f6
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         Type = "oneshot";
104         User = "renovate";
105         Group = "renovate";
106         DynamicUser = true;
107         LoadCredential = lib.mapAttrsToList (name: value: "SECRET-${name}:${value}") cfg.credentials;
108         RemainAfterExit = false;
109         Restart = "on-failure";
110         CacheDirectory = "renovate";
111         StateDirectory = "renovate";
113         # Hardening
114         CapabilityBoundingSet = [ "" ];
115         DeviceAllow = [ "" ];
116         LockPersonality = true;
117         PrivateDevices = true;
118         PrivateUsers = true;
119         ProcSubset = "pid";
120         ProtectClock = true;
121         ProtectControlGroups = true;
122         ProtectHome = true;
123         ProtectHostname = true;
124         ProtectKernelLogs = true;
125         ProtectKernelModules = true;
126         ProtectKernelTunables = true;
127         ProtectProc = "invisible";
128         RestrictAddressFamilies = [
129           "AF_INET"
130           "AF_INET6"
131           "AF_UNIX"
132         ];
133         RestrictNamespaces = true;
134         RestrictRealtime = true;
135         SystemCallArchitectures = "native";
136         UMask = "0077";
137       };
139       script = ''
140         ${lib.concatStringsSep "\n" (
141           builtins.map (name: "export ${name}=$(systemd-creds cat 'SECRET-${name}')") (
142             lib.attrNames cfg.credentials
143           )
144         )}
145         exec ${lib.escapeShellArg (lib.getExe cfg.package)}
146       '';
148       environment = {
149         RENOVATE_CONFIG_FILE = generateConfig "renovate-config.json" cfg.settings;
150         HOME = "/var/lib/renovate";
151       };
152     };
153   };