at master 4.9 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 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; 37in 38{ 39 meta.maintainers = with lib.maintainers; [ 40 marie 41 natsukium 42 ]; 43 44 options.services.renovate = { 45 enable = mkEnableOption "renovate"; 46 package = mkPackageOption pkgs "renovate" { }; 47 schedule = mkOption { 48 type = with types; nullOr str; 49 description = "How often to run renovate. See {manpage}`systemd.time(7)` for the format."; 50 example = "*:0/10"; 51 default = null; 52 }; 53 credentials = mkOption { 54 type = with types; attrsOf path; 55 description = '' 56 Allows configuring environment variable credentials for renovate, read from files. 57 This should always be used for passing confidential data to renovate. 58 ''; 59 example = { 60 RENOVATE_TOKEN = "/etc/renovate/token"; 61 }; 62 default = { }; 63 }; 64 environment = mkOption { 65 type = 66 with types; 67 attrsOf ( 68 nullOr (oneOf [ 69 str 70 path 71 package 72 ]) 73 ); 74 description = '' 75 Extra environment variables to export to the Renovate process 76 from the systemd unit configuration. 77 78 See <https://docs.renovatebot.com/config-overview> for available environment variables. 79 ''; 80 example = { 81 LOG_LEVEL = "debug"; 82 }; 83 default = { }; 84 }; 85 runtimePackages = mkOption { 86 type = with types; listOf package; 87 description = "Packages available to renovate."; 88 default = [ ]; 89 }; 90 validateSettings = mkOption { 91 type = types.bool; 92 default = true; 93 description = "Whether to run renovate's config validator on the built configuration."; 94 }; 95 settings = mkOption { 96 type = json.type; 97 default = { }; 98 example = { 99 platform = "gitea"; 100 endpoint = "https://git.example.com"; 101 gitAuthor = "Renovate <renovate@example.com>"; 102 }; 103 description = '' 104 Renovate's global configuration. 105 If you want to pass secrets to renovate, please use {option}`services.renovate.credentials` for that. 106 107 See <https://docs.renovatebot.com/config-overview> for available settings. 108 ''; 109 }; 110 }; 111 112 config = mkIf cfg.enable { 113 services.renovate = { 114 settings = { 115 cacheDir = "/var/cache/renovate"; 116 baseDir = "/var/lib/renovate"; 117 }; 118 environment = { 119 RENOVATE_CONFIG_FILE = generateConfig "renovate-config.json" cfg.settings; 120 HOME = "/var/lib/renovate"; 121 }; 122 }; 123 124 systemd.services.renovate = { 125 description = "Renovate dependency updater"; 126 documentation = [ "https://docs.renovatebot.com/" ]; 127 after = [ "network.target" ]; 128 startAt = lib.optional (cfg.schedule != null) cfg.schedule; 129 path = [ 130 config.systemd.package 131 pkgs.git 132 ] 133 ++ cfg.runtimePackages; 134 inherit (cfg) environment; 135 136 serviceConfig = { 137 User = "renovate"; 138 Group = "renovate"; 139 DynamicUser = true; 140 LoadCredential = lib.mapAttrsToList (name: value: "SECRET-${name}:${value}") cfg.credentials; 141 CacheDirectory = "renovate"; 142 StateDirectory = "renovate"; 143 144 # Hardening 145 CapabilityBoundingSet = [ "" ]; 146 DeviceAllow = [ "" ]; 147 LockPersonality = true; 148 PrivateDevices = true; 149 PrivateUsers = true; 150 ProcSubset = "pid"; 151 ProtectClock = true; 152 ProtectControlGroups = true; 153 ProtectHome = true; 154 ProtectHostname = true; 155 ProtectKernelLogs = true; 156 ProtectKernelModules = true; 157 ProtectKernelTunables = true; 158 ProtectProc = "invisible"; 159 RestrictAddressFamilies = [ 160 "AF_INET" 161 "AF_INET6" 162 "AF_UNIX" 163 ]; 164 RestrictNamespaces = true; 165 RestrictRealtime = true; 166 SystemCallArchitectures = "native"; 167 UMask = "0077"; 168 }; 169 170 script = '' 171 ${lib.concatStringsSep "\n" ( 172 builtins.map (name: '' 173 ${name}="$(systemd-creds cat 'SECRET-${name}')" 174 export ${name} 175 '') (lib.attrNames cfg.credentials) 176 )} 177 exec ${lib.escapeShellArg (lib.getExe cfg.package)} 178 ''; 179 }; 180 }; 181}