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