Skip to content

Commit

Permalink
services.mysqlBackup: add option to change compression tool
Browse files Browse the repository at this point in the history
  • Loading branch information
6543 committed Dec 12, 2024
1 parent f98a28c commit a1eb7ca
Showing 1 changed file with 100 additions and 11 deletions.
111 changes: 100 additions & 11 deletions nixos/modules/services/backup/mysql-backup.nix
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,56 @@
...
}:
let

inherit (pkgs) mariadb gzip;
inherit (pkgs)
mariadb
gzip
p7zip
zstd
zip
;

cfg = config.services.mysqlBackup;
defaultUser = "mysqlbackup";

compressionPkg =
{
"gzip" = pkgs.gzip;
"zstd" = pkgs.zstd;
"7z" = pkgs.p7zip;
"zip" = pkgs.zip;
}
.${cfg.compression};

fileExt =
{
"gzip" = ".gz";
"zstd" = ".zst";
"7z" = ".7z";
"zip" = ".zip";
}
.${cfg.compression};

validCompressionLevels = {
"zstd" = range: 1 <= range && range <= 19;
"7z" = range: 0 <= range && range <= 9;
"zip" = range: 0 <= range && range <= 9;
"gzip" = range: false; # gzip doesn't use compressionLevel
};

compressionCmd =
let
zstdFlags = if cfg.compressionLevel != null then "-${toString cfg.compressionLevel}" else "";
sevenZipFlags = if cfg.compressionLevel != null then "-mx=${toString cfg.compressionLevel}" else "";
zipFlags = if cfg.compressionLevel != null then "-${toString cfg.compressionLevel}" else "";
in
{
"gzip" = "${gzip}/bin/gzip -c ${cfg.gzipOptions}";
"zstd" = "${zstd}/bin/zstd ${zstdFlags} -";
"7z" = "${p7zip}/bin/7z a -si -t7z ${sevenZipFlags}";
"zip" = ''TMPFILE=$(mktemp).sql && cat > "$TMPFILE" && ${zip}/bin/zip ${zipFlags} - "$TMPFILE" && rm -f "$TMPFILE"'';
}
.${cfg.compression};

backupScript = ''
set -o pipefail
failed=""
Expand All @@ -20,9 +64,10 @@ let
exit 1
fi
'';

backupDatabaseScript = db: ''
dest="${cfg.location}/${db}.gz"
if ${mariadb}/bin/mysqldump ${lib.optionalString cfg.singleTransaction "--single-transaction"} ${db} | ${gzip}/bin/gzip -c ${cfg.gzipOptions} > $dest.tmp; then
dest="${cfg.location}/${db}${fileExt}"
if ${mariadb}/bin/mysqldump ${lib.optionalString cfg.singleTransaction "--single-transaction"} ${db} | ${compressionCmd} > $dest.tmp; then
mv $dest.tmp $dest
echo "Backed up to $dest"
else
Expand All @@ -33,12 +78,9 @@ let
'';

in

{
options = {

services.mysqlBackup = {

enable = lib.mkEnableOption "MySQL backups";

calendar = lib.mkOption {
Expand All @@ -49,6 +91,32 @@ in
'';
};

compression = lib.mkOption {
type = lib.types.enum [
"gzip"
"zstd"
"7z"
"zip"
];
default = "gzip";
description = ''
Compression algorithm to use for database dumps.
Available options: gzip, zstd, 7z, zip
'';
};

compressionLevel = lib.mkOption {
type = lib.types.nullOr lib.types.int;
default = null;
description = ''
Compression level to use for zstd or 7z.
For zstd: 1-19
For 7z: 0-9
For zip: 0-9
Ignored for gzip (use gzipOptions instead)
'';
};

user = lib.mkOption {
type = lib.types.str;
default = defaultUser;
Expand All @@ -69,7 +137,7 @@ in
type = lib.types.path;
default = "/var/backup/mysql";
description = ''
Location to put the gzipped MySQL database dumps.
Location to put the compressed MySQL database dumps.
'';
};

Expand All @@ -86,13 +154,32 @@ in
type = lib.types.str;
description = ''
Command line options to use when invoking `gzip`.
Only used when compression is set to "gzip".
'';
};
};

};

config = lib.mkIf cfg.enable {
# assert config to be correct
assertions = [
{
assertion =
cfg.compressionLevel == null || validCompressionLevels.${cfg.compression} cfg.compressionLevel;
message =
let
rangeMsg = {
"zstd" = "zstd compression level must be between 1 and 19";
"7z" = "7z compression level must be between 0 and 9";
"zip" = "zip compression level must be between 0 and 9";
"gzip" = "gzip does not support compression level option, use gzipOptions instead";
};
in
rangeMsg.${cfg.compression};
}
];

# ensure unix user to be used to perform backup exist.
users.users = lib.optionalAttrs (cfg.user == defaultUser) {
${defaultUser} = {
isSystemUser = true;
Expand All @@ -102,11 +189,14 @@ in
};
};

# add the compression tool to the system environment.
environment.systemPackages = [ compressionPkg ];

# ensure database user to be used to perform backup exist.
services.mysql.ensureUsers = [
{
name = cfg.user;
ensurePermissions =
with lib;
let
privs = "SELECT, SHOW VIEW, TRIGGER, LOCK TABLES";
grant = db: lib.nameValuePair "${db}.*" privs;
Expand Down Expand Up @@ -139,5 +229,4 @@ in
];
};
};

}

0 comments on commit a1eb7ca

Please sign in to comment.