1{ config, lib, pkgs, ... }:
2
3let
4
5 inherit (lib) concatMapStringsSep concatStringsSep isInt isList literalExpression;
6 inherit (lib) mapAttrs mapAttrsToList mkDefault mkEnableOption mkIf mkOption mkRenamedOptionModule optional types;
7
8 cfg = config.services.automysqlbackup;
9 pkg = pkgs.automysqlbackup;
10 user = "automysqlbackup";
11 group = "automysqlbackup";
12
13 toStr = val:
14 if isList val then "( ${concatMapStringsSep " " (val: "'${val}'") val} )"
15 else if isInt val then toString val
16 else if true == val then "'yes'"
17 else if false == val then "'no'"
18 else "'${toString val}'";
19
20 configFile = pkgs.writeText "automysqlbackup.conf" ''
21 #version=${pkg.version}
22 # DONT'T REMOVE THE PREVIOUS VERSION LINE!
23 #
24 ${concatStringsSep "\n" (mapAttrsToList (name: value: "CONFIG_${name}=${toStr value}") cfg.config)}
25 '';
26
27in
28{
29 imports = [
30 (mkRenamedOptionModule [ "services" "automysqlbackup" "config" ] [ "services" "automysqlbackup" "settings" ])
31 ];
32
33 # interface
34 options = {
35 services.automysqlbackup = {
36
37 enable = mkEnableOption (lib.mdDoc "AutoMySQLBackup");
38
39 calendar = mkOption {
40 type = types.str;
41 default = "01:15:00";
42 description = lib.mdDoc ''
43 Configured when to run the backup service systemd unit (DayOfWeek Year-Month-Day Hour:Minute:Second).
44 '';
45 };
46
47 settings = mkOption {
48 type = with types; attrsOf (oneOf [ str int bool (listOf str) ]);
49 default = {};
50 description = lib.mdDoc ''
51 automysqlbackup configuration. Refer to
52 {file}`''${pkgs.automysqlbackup}/etc/automysqlbackup.conf`
53 for details on supported values.
54 '';
55 example = literalExpression ''
56 {
57 db_names = [ "nextcloud" "matomo" ];
58 table_exclude = [ "nextcloud.oc_users" "nextcloud.oc_whats_new" ];
59 mailcontent = "log";
60 mail_address = "admin@example.org";
61 }
62 '';
63 };
64
65 };
66 };
67
68 # implementation
69 config = mkIf cfg.enable {
70
71 assertions = [
72 { assertion = !config.services.mysqlBackup.enable;
73 message = "Please choose one of services.mysqlBackup or services.automysqlbackup.";
74 }
75 ];
76
77 services.automysqlbackup.config = mapAttrs (name: mkDefault) {
78 mysql_dump_username = user;
79 mysql_dump_host = "localhost";
80 mysql_dump_socket = "/run/mysqld/mysqld.sock";
81 backup_dir = "/var/backup/mysql";
82 db_exclude = [ "information_schema" "performance_schema" ];
83 mailcontent = "stdout";
84 mysql_dump_single_transaction = true;
85 };
86
87 systemd.timers.automysqlbackup = {
88 description = "automysqlbackup timer";
89 wantedBy = [ "timers.target" ];
90 timerConfig = {
91 OnCalendar = cfg.calendar;
92 AccuracySec = "5m";
93 };
94 };
95
96 systemd.services.automysqlbackup = {
97 description = "automysqlbackup service";
98 serviceConfig = {
99 User = user;
100 Group = group;
101 ExecStart = "${pkg}/bin/automysqlbackup ${configFile}";
102 };
103 };
104
105 environment.systemPackages = [ pkg ];
106
107 users.users.${user} = {
108 group = group;
109 isSystemUser = true;
110 };
111 users.groups.${group} = { };
112
113 systemd.tmpfiles.rules = [
114 "d '${cfg.config.backup_dir}' 0750 ${user} ${group} - -"
115 ];
116
117 services.mysql.ensureUsers = optional (config.services.mysql.enable && cfg.config.mysql_dump_host == "localhost") {
118 name = user;
119 ensurePermissions = {
120 "*.*" = "SELECT, SHOW VIEW, TRIGGER, LOCK TABLES, EVENT";
121
122 # https://forums.mysql.com/read.php?10,668311,668315#msg-668315
123 "function sys.extract_table_from_file_name" = "execute";
124 "function sys.format_path" = "execute";
125 "function sys.format_statement" = "execute";
126 "function sys.extract_schema_from_file_name" = "execute";
127 "function sys.ps_thread_account" = "execute";
128 "function sys.format_time" = "execute";
129 "function sys.format_bytes" = "execute";
130 };
131 };
132
133 };
134}