at 23.11-pre 3.1 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 inherit (pkgs) mariadb gzip; 8 9 cfg = config.services.mysqlBackup; 10 defaultUser = "mysqlbackup"; 11 12 backupScript = '' 13 set -o pipefail 14 failed="" 15 ${concatMapStringsSep "\n" backupDatabaseScript cfg.databases} 16 if [ -n "$failed" ]; then 17 echo "Backup of database(s) failed:$failed" 18 exit 1 19 fi 20 ''; 21 backupDatabaseScript = db: '' 22 dest="${cfg.location}/${db}.gz" 23 if ${mariadb}/bin/mysqldump ${optionalString cfg.singleTransaction "--single-transaction"} ${db} | ${gzip}/bin/gzip -c > $dest.tmp; then 24 mv $dest.tmp $dest 25 echo "Backed up to $dest" 26 else 27 echo "Failed to back up to $dest" 28 rm -f $dest.tmp 29 failed="$failed ${db}" 30 fi 31 ''; 32 33in 34 35{ 36 options = { 37 38 services.mysqlBackup = { 39 40 enable = mkEnableOption (lib.mdDoc "MySQL backups"); 41 42 calendar = mkOption { 43 type = types.str; 44 default = "01:15:00"; 45 description = lib.mdDoc '' 46 Configured when to run the backup service systemd unit (DayOfWeek Year-Month-Day Hour:Minute:Second). 47 ''; 48 }; 49 50 user = mkOption { 51 type = types.str; 52 default = defaultUser; 53 description = lib.mdDoc '' 54 User to be used to perform backup. 55 ''; 56 }; 57 58 databases = mkOption { 59 default = []; 60 type = types.listOf types.str; 61 description = lib.mdDoc '' 62 List of database names to dump. 63 ''; 64 }; 65 66 location = mkOption { 67 type = types.path; 68 default = "/var/backup/mysql"; 69 description = lib.mdDoc '' 70 Location to put the gzipped MySQL database dumps. 71 ''; 72 }; 73 74 singleTransaction = mkOption { 75 default = false; 76 type = types.bool; 77 description = lib.mdDoc '' 78 Whether to create database dump in a single transaction 79 ''; 80 }; 81 }; 82 83 }; 84 85 config = mkIf cfg.enable { 86 users.users = optionalAttrs (cfg.user == defaultUser) { 87 ${defaultUser} = { 88 isSystemUser = true; 89 createHome = false; 90 home = cfg.location; 91 group = "nogroup"; 92 }; 93 }; 94 95 services.mysql.ensureUsers = [{ 96 name = cfg.user; 97 ensurePermissions = with lib; 98 let 99 privs = "SELECT, SHOW VIEW, TRIGGER, LOCK TABLES"; 100 grant = db: nameValuePair "${db}.*" privs; 101 in 102 listToAttrs (map grant cfg.databases); 103 }]; 104 105 systemd = { 106 timers.mysql-backup = { 107 description = "Mysql backup timer"; 108 wantedBy = [ "timers.target" ]; 109 timerConfig = { 110 OnCalendar = cfg.calendar; 111 AccuracySec = "5m"; 112 Unit = "mysql-backup.service"; 113 }; 114 }; 115 services.mysql-backup = { 116 description = "MySQL backup service"; 117 enable = true; 118 serviceConfig = { 119 Type = "oneshot"; 120 User = cfg.user; 121 }; 122 script = backupScript; 123 }; 124 tmpfiles.rules = [ 125 "d ${cfg.location} 0700 ${cfg.user} - - -" 126 ]; 127 }; 128 }; 129 130}