summary refs log tree commit diff
path: root/nixos/modules/services/backup/mysql-backup.nix
diff options
context:
space:
mode:
authorRodney Lorrimar <dev@rodney.id.au>2017-09-23 15:58:07 +0100
committerRobin Gloster <mail@glob.in>2017-09-27 18:44:49 +0200
commit56eba66f77bb1d4711e824158e3b9a8d55a929f1 (patch)
treedab3d2a609304bfa93422bf493c41ae48a0997e3 /nixos/modules/services/backup/mysql-backup.nix
parent75ba415fbcfe48fdf5fb88f2aa461ce83921303f (diff)
downloadnixpkgs-56eba66f77bb1d4711e824158e3b9a8d55a929f1.tar
nixpkgs-56eba66f77bb1d4711e824158e3b9a8d55a929f1.tar.gz
nixpkgs-56eba66f77bb1d4711e824158e3b9a8d55a929f1.tar.bz2
nixpkgs-56eba66f77bb1d4711e824158e3b9a8d55a929f1.tar.lz
nixpkgs-56eba66f77bb1d4711e824158e3b9a8d55a929f1.tar.xz
nixpkgs-56eba66f77bb1d4711e824158e3b9a8d55a929f1.tar.zst
nixpkgs-56eba66f77bb1d4711e824158e3b9a8d55a929f1.zip
mysqlBackup service: let it work with default settings
* Grants enough privileges to the configured user so that it can run
  mysqldump.

* Adds a nixos test.

* Use systemd timers instead of a cronjob (by @fadenb).

* Creates a new user for backups by default, instead of using mysql
  user.

* Ensures that backup user has write permissions on backup location.

* Write backup to a temporary file before renaming so that a failed
  backup won't overwrite the previous backup, and so that the backup
  location will never contain a partial backup.

Breaking changes:

 * Renamed period to calendar to reflect the change in how to
   configure the backup time.

 * A failed backup will no longer result in cron sending an e-mail --
   users' monitoring systems must be updated.

Resolves #24728
Diffstat (limited to 'nixos/modules/services/backup/mysql-backup.nix')
-rw-r--r--nixos/modules/services/backup/mysql-backup.nix90
1 files changed, 70 insertions, 20 deletions
diff --git a/nixos/modules/services/backup/mysql-backup.nix b/nixos/modules/services/backup/mysql-backup.nix
index 28f607861f7..3f533fa457d 100644
--- a/nixos/modules/services/backup/mysql-backup.nix
+++ b/nixos/modules/services/backup/mysql-backup.nix
@@ -6,10 +6,28 @@ let
 
   inherit (pkgs) mysql gzip;
 
-  cfg = config.services.mysqlBackup ;
-  location = cfg.location ;
-  mysqlBackupCron = db : ''
-    ${cfg.period} ${cfg.user} ${mysql}/bin/mysqldump ${if cfg.singleTransaction then "--single-transaction" else ""} ${db} | ${gzip}/bin/gzip -c > ${location}/${db}.gz
+  cfg = config.services.mysqlBackup;
+  defaultUser = "mysqlbackup";
+
+  backupScript = ''
+    set -o pipefail
+    failed=""
+    ${concatMapStringsSep "\n" backupDatabaseScript cfg.databases}
+    if [ -n "$failed" ]; then
+      echo "Backup of database(s) failed:$failed"
+      exit 1
+    fi
+  '';
+  backupDatabaseScript = db: ''
+    dest="${cfg.location}/${db}.gz"
+    if ${mysql}/bin/mysqldump ${if cfg.singleTransaction then "--single-transaction" else ""} ${db} | ${gzip}/bin/gzip -c > $dest.tmp; then
+      mv $dest.tmp $dest
+      echo "Backed up to $dest"
+    else
+      echo "Failed to back up to $dest"
+      rm -f $dest.tmp
+      failed="$failed ${db}"
+    fi
   '';
 
 in
@@ -26,17 +44,16 @@ in
         '';
       };
 
-      period = mkOption {
-        default = "15 01 * * *";
+      calendar = mkOption {
+        type = types.str;
+        default = "01:15:00";
         description = ''
-          This option defines (in the format used by cron) when the
-          databases should be dumped.
-          The default is to update at 01:15 (at night) every day.
+          Configured when to run the backup service systemd unit (DayOfWeek Year-Month-Day Hour:Minute:Second).
         '';
       };
 
       user = mkOption {
-        default = "mysql";
+        default = defaultUser;
         description = ''
           User to be used to perform backup.
         '';
@@ -66,16 +83,49 @@ in
 
   };
 
-  config = mkIf config.services.mysqlBackup.enable {
-
-    services.cron.systemCronJobs = map mysqlBackupCron config.services.mysqlBackup.databases;
-
-    system.activationScripts.mysqlBackup = stringAfter [ "stdio" "users" ]
-      ''
-        mkdir -m 0700 -p ${config.services.mysqlBackup.location}
-        chown ${config.services.mysqlBackup.user} ${config.services.mysqlBackup.location}
-      '';
-
+  config = mkIf cfg.enable {
+    users.extraUsers = optionalAttrs (cfg.user == defaultUser) (singleton
+      { name = defaultUser;
+        isSystemUser = true;
+        createHome = false;
+        home = cfg.location;
+        group = "nogroup";
+      });
+
+    services.mysql.ensureUsers = [{
+      name = cfg.user;
+      ensurePermissions = with lib;
+        let
+          privs = "SELECT, SHOW VIEW, TRIGGER, LOCK TABLES";
+          grant = db: nameValuePair "${db}.*" privs;
+        in
+          listToAttrs (map grant cfg.databases);
+    }];
+
+    systemd = {
+      timers."mysql-backup" = {
+        description = "Mysql backup timer";
+        wantedBy = [ "timers.target" ];
+        timerConfig = {
+          OnCalendar = cfg.calendar;
+          AccuracySec = "5m";
+          Unit = "mysql-backup.service";
+        };
+      };
+      services."mysql-backup" = {
+        description = "Mysql backup service";
+        enable = true;
+        serviceConfig = {
+          User = cfg.user;
+          PermissionsStartOnly = true;
+        };
+        preStart = ''
+          mkdir -m 0700 -p ${cfg.location}
+          chown -R ${cfg.user} ${cfg.location}
+        '';
+        script = backupScript;
+      };
+    };
   };
 
 }