1 { config, lib, pkgs, ... }:
4 inherit (pkgs) mariadb gzip;
6 cfg = config.services.mysqlBackup;
7 defaultUser = "mysqlbackup";
12 ${lib.concatMapStringsSep "\n" backupDatabaseScript cfg.databases}
13 if [ -n "$failed" ]; then
14 echo "Backup of database(s) failed:$failed"
18 backupDatabaseScript = db: ''
19 dest="${cfg.location}/${db}.gz"
20 if ${mariadb}/bin/mysqldump ${lib.optionalString cfg.singleTransaction "--single-transaction"} ${db} | ${gzip}/bin/gzip -c ${cfg.gzipOptions} > $dest.tmp; then
22 echo "Backed up to $dest"
24 echo "Failed to back up to $dest"
26 failed="$failed ${db}"
35 services.mysqlBackup = {
37 enable = lib.mkEnableOption "MySQL backups";
39 calendar = lib.mkOption {
43 Configured when to run the backup service systemd unit (DayOfWeek Year-Month-Day Hour:Minute:Second).
49 default = defaultUser;
51 User to be used to perform backup.
55 databases = lib.mkOption {
57 type = lib.types.listOf lib.types.str;
59 List of database names to dump.
63 location = lib.mkOption {
64 type = lib.types.path;
65 default = "/var/backup/mysql";
67 Location to put the gzipped MySQL database dumps.
71 singleTransaction = lib.mkOption {
73 type = lib.types.bool;
75 Whether to create database dump in a single transaction
79 gzipOptions = lib.mkOption {
80 default = "--no-name --rsyncable";
83 Command line options to use when invoking `gzip`.
90 config = lib.mkIf cfg.enable {
91 users.users = lib.optionalAttrs (cfg.user == defaultUser) {
100 services.mysql.ensureUsers = [{
102 ensurePermissions = with lib;
104 privs = "SELECT, SHOW VIEW, TRIGGER, LOCK TABLES";
105 grant = db: lib.nameValuePair "${db}.*" privs;
107 lib.listToAttrs (map grant cfg.databases);
111 timers.mysql-backup = {
112 description = "Mysql backup timer";
113 wantedBy = [ "timers.target" ];
115 OnCalendar = cfg.calendar;
117 Unit = "mysql-backup.service";
120 services.mysql-backup = {
121 description = "MySQL backup service";
127 script = backupScript;
130 "d ${cfg.location} 0700 ${cfg.user} - - -"