anyrun: 0-unstable-2024-11-08 -> 0-unstable-2024-12-27 (#369731)
[NixPkgs.git] / nixos / modules / services / monitoring / prometheus / exporters / restic.nix
blob99cdaf81305b2efd7c4db3775fd21446d0022773
2   config,
3   lib,
4   pkgs,
5   options,
6   ...
7 }:
9 let
10   cfg = config.services.prometheus.exporters.restic;
11   inherit (lib)
12     mkOption
13     types
14     concatStringsSep
15     mkIf
16     mapAttrs'
17     splitString
18     toUpper
19     optional
20     optionalAttrs
21     nameValuePair
22     ;
25   port = 9753;
26   extraOpts = {
27     repository = mkOption {
28       type = with lib.types; nullOr str;
29       default = null;
30       description = ''
31         URI pointing to the repository to monitor.
32       '';
33       example = "sftp:backup@192.168.1.100:/backups/example";
34     };
36     repositoryFile = mkOption {
37       type = with lib.types; nullOr path;
38       default = null;
39       description = ''
40         Path to the file containing the URI for the repository to monitor.
41       '';
42     };
44     passwordFile = mkOption {
45       type = types.path;
46       description = ''
47         File containing the password to the repository.
48       '';
49       example = "/etc/nixos/restic-password";
50     };
52     environmentFile = mkOption {
53       type = with types; nullOr path;
54       default = null;
55       description = ''
56         File containing the credentials to access the repository, in the
57         format of an EnvironmentFile as described by systemd.exec(5)
58       '';
59     };
61     refreshInterval = mkOption {
62       type = types.ints.unsigned;
63       default = 60;
64       description = ''
65         Refresh interval for the metrics in seconds.
66         Computing the metrics is an expensive task, keep this value as high as possible.
67       '';
68     };
70     rcloneOptions = mkOption {
71       type =
72         with types;
73         attrsOf (oneOf [
74           str
75           bool
76         ]);
77       default = { };
78       description = ''
79         Options to pass to rclone to control its behavior.
80         See <https://rclone.org/docs/#options> for
81         available options. When specifying option names, strip the
82         leading `--`. To set a flag such as
83         `--drive-use-trash`, which does not take a value,
84         set the value to the Boolean `true`.
85       '';
86     };
88     rcloneConfig = mkOption {
89       type =
90         with types;
91         attrsOf (oneOf [
92           str
93           bool
94         ]);
95       default = { };
96       description = ''
97         Configuration for the rclone remote being used for backup.
98         See the remote's specific options under rclone's docs at
99         <https://rclone.org/docs/>. When specifying
100         option names, use the "config" name specified in the docs.
101         For example, to set `--b2-hard-delete` for a B2
102         remote, use `hard_delete = true` in the
103         attribute set.
105         ::: {.warning}
106         Secrets set in here will be world-readable in the Nix
107         store! Consider using the {option}`rcloneConfigFile`
108         option instead to specify secret values separately. Note that
109         options set here will override those set in the config file.
110         :::
111       '';
112     };
114     rcloneConfigFile = mkOption {
115       type = with types; nullOr path;
116       default = null;
117       description = ''
118         Path to the file containing rclone configuration. This file
119         must contain configuration for the remote specified in this backup
120         set and also must be readable by root.
122         ::: {.caution}
123         Options set in `rcloneConfig` will override those set in this
124         file.
125         :::
126       '';
127     };
128   };
130   serviceOpts = {
131     script = ''
132       export RESTIC_REPOSITORY=${
133         if cfg.repositoryFile != null then
134           "$(cat $CREDENTIALS_DIRECTORY/RESTIC_REPOSITORY)"
135         else
136           "${cfg.repository}"
137       }
138       export RESTIC_PASSWORD_FILE=$CREDENTIALS_DIRECTORY/RESTIC_PASSWORD_FILE
139       ${pkgs.prometheus-restic-exporter}/bin/restic-exporter.py \
140         ${concatStringsSep " \\\n  " cfg.extraFlags}
141     '';
142     serviceConfig = {
143       EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile;
144       LoadCredential = [
145         "RESTIC_PASSWORD_FILE:${cfg.passwordFile}"
146       ] ++ optional (cfg.repositoryFile != null) [ "RESTIC_REPOSITORY:${cfg.repositoryFile}" ];
147     };
148     environment =
149       let
150         rcloneRemoteName = builtins.elemAt (splitString ":" cfg.repository) 1;
151         rcloneAttrToOpt = v: "RCLONE_" + toUpper (builtins.replaceStrings [ "-" ] [ "_" ] v);
152         rcloneAttrToConf = v: "RCLONE_CONFIG_" + toUpper (rcloneRemoteName + "_" + v);
153         toRcloneVal = v: if lib.isBool v then lib.boolToString v else v;
154       in
155       {
156         LISTEN_ADDRESS = cfg.listenAddress;
157         LISTEN_PORT = toString cfg.port;
158         REFRESH_INTERVAL = toString cfg.refreshInterval;
159       }
160       // (mapAttrs' (
161         name: value: nameValuePair (rcloneAttrToOpt name) (toRcloneVal value)
162       ) cfg.rcloneOptions)
163       // optionalAttrs (cfg.rcloneConfigFile != null) {
164         RCLONE_CONFIG = cfg.rcloneConfigFile;
165       }
166       // (mapAttrs' (
167         name: value: nameValuePair (rcloneAttrToConf name) (toRcloneVal value)
168       ) cfg.rcloneConfig);
169   };