nixos/postgresqlBackup: add backupAll option

For large setups it is useful to list all databases explicit
(for example if temporary databases are also present) and store them in extra
files.
For smaller setups it is more convenient to just backup all databases at once,
because it is easy to forget to update configuration when adding/renaming
databases. pg_dumpall also has the advantage that it backups users/passwords.

As a result the module becomes easier to use because it is sufficient
in the default case to just set one option (services.postgresqlBackup.enable).
This commit is contained in:
Jörg Thalheim 2019-01-19 10:33:20 +00:00
parent 9a601e228d
commit 1af4f366ca
No known key found for this signature in database
GPG key ID: CA4106B8D7CC79FA
2 changed files with 59 additions and 19 deletions

View file

@ -6,11 +6,11 @@ let
cfg = config.services.postgresqlBackup;
postgresqlBackupService = db :
postgresqlBackupService = db: dumpCmd:
{
enable = true;
description = "Backup of database ${db}";
description = "Backup of ${db} database(s)";
requires = [ "postgresql.service" ];
@ -26,7 +26,7 @@ let
${pkgs.coreutils}/bin/mv ${cfg.location}/${db}.sql.gz ${cfg.location}/${db}.prev.sql.gz
fi
${config.services.postgresql.package}/bin/pg_dump ${cfg.pgdumpOptions} ${db} | \
${dumpCmd} | \
${pkgs.gzip}/bin/gzip -c > ${cfg.location}/${db}.sql.gz
'';
@ -42,9 +42,7 @@ let
in {
options = {
services.postgresqlBackup = {
enable = mkOption {
default = false;
description = ''
@ -61,6 +59,19 @@ in {
'';
};
backupAll = mkOption {
default = cfg.databases == [];
defaultText = "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 = [];
description = ''
@ -79,18 +90,36 @@ in {
type = types.string;
default = "-Cbo";
description = ''
Command line options for pg_dump.
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.
'';
};
};
};
config = mkIf config.services.postgresqlBackup.enable {
systemd.services = listToAttrs (map (db : {
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 && cfg.backupAll) {
systemd.services.postgresqlBackup =
postgresqlBackupService "all" "${config.services.postgresql.package}/bin/pg_dumpall";
})
(mkIf (cfg.enable && !cfg.backupAll) {
systemd.services = listToAttrs (map (db:
let
cmd = "${config.services.postgresql.package}/bin/pg_dump ${cfg.pgdumpOptions} ${db}";
in {
name = "postgresqlBackup-${db}";
value = postgresqlBackupService db; } ) cfg.databases);
};
value = postgresqlBackupService db cmd;
}) cfg.databases);
})
];
}

View file

@ -21,7 +21,7 @@ let
CREATE TABLE xmltest ( doc xml );
INSERT INTO xmltest (doc) VALUES ('<test>ok</test>'); -- check if libxml2 enabled
'';
make-postgresql-test = postgresql-name: postgresql-package: makeTest {
make-postgresql-test = postgresql-name: postgresql-package: backup-all: makeTest {
name = postgresql-name;
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ zagy ];
@ -29,14 +29,17 @@ let
machine = {...}:
{
services.postgresql.package=postgresql-package;
services.postgresql.package = postgresql-package;
services.postgresql.enable = true;
services.postgresqlBackup.enable = true;
services.postgresqlBackup.databases = [ "postgres" ];
services.postgresqlBackup.databases = optional (!backup-all) "postgres";
};
testScript = ''
testScript = let
backupName = if backup-all then "all" else "postgres";
backupService = if backup-all then "postgresqlBackup" else "postgresqlBackup-postgres";
in ''
sub check_count {
my ($select, $nlines) = @_;
return 'test $(sudo -u postgres psql postgres -tAc "' . $select . '"|wc -l) -eq ' . $nlines;
@ -56,12 +59,20 @@ let
$machine->succeed(check_count("SELECT xpath(\'/test/text()\', doc) FROM xmltest;", 1));
# Check backup service
$machine->succeed("systemctl start postgresqlBackup-postgres.service");
$machine->succeed("zcat /var/backup/postgresql/postgres.sql.gz | grep '<test>ok</test>'");
$machine->succeed("stat -c '%a' /var/backup/postgresql/postgres.sql.gz | grep 600");
$machine->succeed("systemctl start ${backupService}.service");
$machine->succeed("zcat /var/backup/postgresql/${backupName}.sql.gz | grep '<test>ok</test>'");
$machine->succeed("stat -c '%a' /var/backup/postgresql/${backupName}.sql.gz | grep 600");
$machine->shutdown;
'';
};
in
mapAttrs' (p-name: p-package: {name=p-name; value=make-postgresql-test p-name p-package;}) postgresql-versions
(mapAttrs' (name: package: { inherit name; value=make-postgresql-test name package false;}) postgresql-versions) // (
# just pick one version for the dump all test
let
first = head (attrNames postgresql-versions);
name = "${first}-backup-all";
in {
${name} = make-postgresql-test name postgresql-versions.${first} true;
}
)