vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / backup / postgresql-backup.nix
blob3302375c78899dd2bdfb7b736a70eb7c17e19433
1 { config, lib, pkgs, ... }:
2 let
4   cfg = config.services.postgresqlBackup;
6   postgresqlBackupService = db: dumpCmd:
7     let
8       compressSuffixes = {
9         "none" = "";
10         "gzip" = ".gz";
11         "zstd" = ".zstd";
12       };
13       compressSuffix = lib.getAttr cfg.compression compressSuffixes;
15       compressCmd = lib.getAttr cfg.compression {
16         "none" = "cat";
17         "gzip" = "${pkgs.gzip}/bin/gzip -c -${toString cfg.compressionLevel} --rsyncable";
18         "zstd" = "${pkgs.zstd}/bin/zstd -c -${toString cfg.compressionLevel} --rsyncable";
19       };
21       mkSqlPath = prefix: suffix: "${cfg.location}/${db}${prefix}.sql${suffix}";
22       curFile = mkSqlPath "" compressSuffix;
23       prevFile = mkSqlPath ".prev" compressSuffix;
24       prevFiles = map (mkSqlPath ".prev") (lib.attrValues compressSuffixes);
25       inProgressFile = mkSqlPath ".in-progress" compressSuffix;
26     in {
27       enable = true;
29       description = "Backup of ${db} database(s)";
31       requires = [ "postgresql.service" ];
33       path = [ pkgs.coreutils config.services.postgresql.package ];
35       script = ''
36         set -e -o pipefail
38         umask 0077 # ensure backup is only readable by postgres user
40         if [ -e ${curFile} ]; then
41           rm -f ${toString prevFiles}
42           mv ${curFile} ${prevFile}
43         fi
45         ${dumpCmd} \
46           | ${compressCmd} \
47           > ${inProgressFile}
49         mv ${inProgressFile} ${curFile}
50       '';
52       serviceConfig = {
53         Type = "oneshot";
54         User = "postgres";
55       };
57       startAt = cfg.startAt;
58     };
60 in {
62   imports = [
63     (lib.mkRemovedOptionModule [ "services" "postgresqlBackup" "period" ] ''
64        A systemd timer is now used instead of cron.
65        The starting time can be configured via <literal>services.postgresqlBackup.startAt</literal>.
66     '')
67   ];
69   options = {
70     services.postgresqlBackup = {
71       enable = lib.mkEnableOption "PostgreSQL dumps";
73       startAt = lib.mkOption {
74         default = "*-*-* 01:15:00";
75         type = with lib.types; either (listOf str) str;
76         description = ''
77           This option defines (see `systemd.time` for format) when the
78           databases should be dumped.
79           The default is to update at 01:15 (at night) every day.
80         '';
81       };
83       backupAll = lib.mkOption {
84         default = cfg.databases == [];
85         defaultText = lib.literalExpression "services.postgresqlBackup.databases == []";
86         type = lib.types.bool;
87         description = ''
88           Backup all databases using pg_dumpall.
89           This option is mutual exclusive to
90           `services.postgresqlBackup.databases`.
91           The resulting backup dump will have the name all.sql.gz.
92           This option is the default if no databases are specified.
93         '';
94       };
96       databases = lib.mkOption {
97         default = [];
98         type = lib.types.listOf lib.types.str;
99         description = ''
100           List of database names to dump.
101         '';
102       };
104       location = lib.mkOption {
105         default = "/var/backup/postgresql";
106         type = lib.types.path;
107         description = ''
108           Path of directory where the PostgreSQL database dumps will be placed.
109         '';
110       };
112       pgdumpOptions = lib.mkOption {
113         type = lib.types.separatedString " ";
114         default = "-C";
115         description = ''
116           Command line options for pg_dump. This options is not used
117           if `config.services.postgresqlBackup.backupAll` is enabled.
118           Note that config.services.postgresqlBackup.backupAll is also active,
119           when no databases where specified.
120         '';
121       };
123       compression = lib.mkOption {
124         type = lib.types.enum ["none" "gzip" "zstd"];
125         default = "gzip";
126         description = ''
127           The type of compression to use on the generated database dump.
128         '';
129       };
131       compressionLevel = lib.mkOption {
132         type = lib.types.ints.between 1 19;
133         default = 6;
134         description = ''
135           The compression level used when compression is enabled.
136           gzip accepts levels 1 to 9. zstd accepts levels 1 to 19.
137         '';
138       };
139     };
141   };
143   config = lib.mkMerge [
144     {
145       assertions = [
146         {
147           assertion = cfg.backupAll -> cfg.databases == [];
148           message = "config.services.postgresqlBackup.backupAll cannot be used together with config.services.postgresqlBackup.databases";
149         }
150         {
151           assertion = cfg.compression == "none" ||
152             (cfg.compression == "gzip" && cfg.compressionLevel >= 1 && cfg.compressionLevel <= 9) ||
153             (cfg.compression == "zstd" && cfg.compressionLevel >= 1 && cfg.compressionLevel <= 19);
154           message = "config.services.postgresqlBackup.compressionLevel must be set between 1 and 9 for gzip and 1 and 19 for zstd";
155         }
156       ];
157     }
158     (lib.mkIf cfg.enable {
159       systemd.tmpfiles.rules = [
160         "d '${cfg.location}' 0700 postgres - - -"
161       ];
162     })
163     (lib.mkIf (cfg.enable && cfg.backupAll) {
164       systemd.services.postgresqlBackup =
165         postgresqlBackupService "all" "pg_dumpall";
166     })
167     (lib.mkIf (cfg.enable && !cfg.backupAll) {
168       systemd.services = lib.listToAttrs (map (db:
169         let
170           cmd = "pg_dump ${cfg.pgdumpOptions} ${db}";
171         in {
172           name = "postgresqlBackup-${db}";
173           value = postgresqlBackupService db cmd;
174         }) cfg.databases);
175     })
176   ];
178   meta.maintainers = with lib.maintainers; [ Scrumplex ];