blob: 00381be4b75d3509e373908fa0ba4f15b53e895c (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
{ config, lib, pkgs, ... }:
with lib;
let
inherit (pkgs) mariadb gzip;
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 ${mariadb}/bin/mysqldump ${optionalString cfg.singleTransaction "--single-transaction"} ${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
{
options = {
services.mysqlBackup = {
enable = mkEnableOption "MySQL backups";
calendar = mkOption {
type = types.str;
default = "01:15:00";
description = ''
Configured when to run the backup service systemd unit (DayOfWeek Year-Month-Day Hour:Minute:Second).
'';
};
user = mkOption {
type = types.str;
default = defaultUser;
description = ''
User to be used to perform backup.
'';
};
databases = mkOption {
default = [];
type = types.listOf types.str;
description = ''
List of database names to dump.
'';
};
location = mkOption {
type = types.path;
default = "/var/backup/mysql";
description = ''
Location to put the gzipped MySQL database dumps.
'';
};
singleTransaction = mkOption {
default = false;
type = types.bool;
description = ''
Whether to create database dump in a single transaction
'';
};
};
};
config = mkIf cfg.enable {
users.users = optionalAttrs (cfg.user == defaultUser) {
${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 = {
Type = "oneshot";
User = cfg.user;
};
script = backupScript;
};
tmpfiles.rules = [
"d ${cfg.location} 0700 ${cfg.user} - - -"
];
};
};
}
|