diff options
Diffstat (limited to 'nixos/modules/services/backup/postgresql-backup.nix')
-rw-r--r-- | nixos/modules/services/backup/postgresql-backup.nix | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/nixos/modules/services/backup/postgresql-backup.nix b/nixos/modules/services/backup/postgresql-backup.nix new file mode 100644 index 00000000000..562458eb457 --- /dev/null +++ b/nixos/modules/services/backup/postgresql-backup.nix @@ -0,0 +1,164 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.postgresqlBackup; + + postgresqlBackupService = db: dumpCmd: + let + compressSuffixes = { + "none" = ""; + "gzip" = ".gz"; + "zstd" = ".zstd"; + }; + compressSuffix = getAttr cfg.compression compressSuffixes; + + compressCmd = getAttr cfg.compression { + "none" = "cat"; + "gzip" = "${pkgs.gzip}/bin/gzip -c"; + "zstd" = "${pkgs.zstd}/bin/zstd -c"; + }; + + mkSqlPath = prefix: suffix: "${cfg.location}/${db}${prefix}.sql${suffix}"; + curFile = mkSqlPath "" compressSuffix; + prevFile = mkSqlPath ".prev" compressSuffix; + prevFiles = map (mkSqlPath ".prev") (attrValues compressSuffixes); + inProgressFile = mkSqlPath ".in-progress" compressSuffix; + in { + enable = true; + + description = "Backup of ${db} database(s)"; + + requires = [ "postgresql.service" ]; + + path = [ pkgs.coreutils config.services.postgresql.package ]; + + script = '' + set -e -o pipefail + + umask 0077 # ensure backup is only readable by postgres user + + if [ -e ${curFile} ]; then + rm -f ${toString prevFiles} + mv ${curFile} ${prevFile} + fi + + ${dumpCmd} \ + | ${compressCmd} \ + > ${inProgressFile} + + mv ${inProgressFile} ${curFile} + ''; + + serviceConfig = { + Type = "oneshot"; + User = "postgres"; + }; + + startAt = cfg.startAt; + }; + +in { + + imports = [ + (mkRemovedOptionModule [ "services" "postgresqlBackup" "period" ] '' + A systemd timer is now used instead of cron. + The starting time can be configured via <literal>services.postgresqlBackup.startAt</literal>. + '') + ]; + + options = { + services.postgresqlBackup = { + enable = mkEnableOption "PostgreSQL dumps"; + + startAt = mkOption { + default = "*-*-* 01:15:00"; + type = with types; either (listOf str) str; + description = '' + This option defines (see <literal>systemd.time</literal> for format) when the + databases should be dumped. + The default is to update at 01:15 (at night) every day. + ''; + }; + + backupAll = mkOption { + default = cfg.databases == []; + defaultText = literalExpression "services.postgresqlBackup.databases == []"; + type = lib.types.bool; + description = '' + Backup all databases using pg_dumpall. + This option is mutual exclusive to + <literal>services.postgresqlBackup.databases</literal>. + The resulting backup dump will have the name all.sql.gz. + This option is the default if no databases are specified. + ''; + }; + + databases = mkOption { + default = []; + type = types.listOf types.str; + description = '' + List of database names to dump. + ''; + }; + + location = mkOption { + default = "/var/backup/postgresql"; + type = types.path; + description = '' + Path of directory where the PostgreSQL database dumps will be placed. + ''; + }; + + pgdumpOptions = mkOption { + type = types.separatedString " "; + default = "-C"; + description = '' + Command line options for pg_dump. This options is not used + if <literal>config.services.postgresqlBackup.backupAll</literal> is enabled. + Note that config.services.postgresqlBackup.backupAll is also active, + when no databases where specified. + ''; + }; + + compression = mkOption { + type = types.enum ["none" "gzip" "zstd"]; + default = "gzip"; + description = '' + The type of compression to use on the generated database dump. + ''; + }; + }; + + }; + + config = mkMerge [ + { + assertions = [{ + assertion = cfg.backupAll -> cfg.databases == []; + message = "config.services.postgresqlBackup.backupAll cannot be used together with config.services.postgresqlBackup.databases"; + }]; + } + (mkIf cfg.enable { + systemd.tmpfiles.rules = [ + "d '${cfg.location}' 0700 postgres - - -" + ]; + }) + (mkIf (cfg.enable && cfg.backupAll) { + systemd.services.postgresqlBackup = + postgresqlBackupService "all" "pg_dumpall"; + }) + (mkIf (cfg.enable && !cfg.backupAll) { + systemd.services = listToAttrs (map (db: + let + cmd = "pg_dump ${cfg.pgdumpOptions} ${db}"; + in { + name = "postgresqlBackup-${db}"; + value = postgresqlBackupService db cmd; + }) cfg.databases); + }) + ]; + +} |