1 { pkgs, config, lib, ... }:
3 cfg = config.myServices.databasesReplication.mariadb;
6 options.myServices.databasesReplication.mariadb = {
7 enable = lib.mkEnableOption "Enable mariadb replication";
11 Base path to put the replications
14 hosts = lib.mkOption {
19 type = lib.types.attrsOf (lib.types.submodule {
21 package = lib.mkOption {
22 type = lib.types.package;
23 default = pkgs.mariadb;
25 Mariadb package for this host
28 serverId = lib.mkOption {
31 Server id to use for replication cluster (must be unique among the cluster!)
52 password = lib.mkOption {
58 dumpUser = lib.mkOption {
61 User who can do a dump
64 dumpPassword = lib.mkOption {
67 Password for the dump user
75 config = lib.mkIf cfg.enable {
77 description = "MySQL server user";
79 uid = config.ids.uids.mysql;
80 extraGroups = [ "keys" ];
82 users.groups.mysql.gid = config.ids.gids.mysql;
84 secrets.keys = lib.flatten (lib.mapAttrsToList (name: hcfg: [
86 dest = "mysql_replication/${name}/slave_init_commands";
91 CHANGE MASTER TO master_host="${hcfg.host}", master_port=${hcfg.port}, master_user="${hcfg.user}", master_password="${hcfg.password}", master_ssl=1, master_use_gtid=slave_pos;
96 dest = "mysql_replication/${name}/mysqldump_remote";
103 password = ${hcfg.password}
107 dest = "mysql_replication/${name}/mysqldump";
108 permissions = "0400";
113 user = ${hcfg.dumpUser}
114 password = ${hcfg.dumpPassword}
118 dest = "mysql_replication/${name}/client";
119 permissions = "0400";
124 user = ${hcfg.dumpUser}
125 password = ${hcfg.dumpPassword}
132 systemCronJobs = lib.flatten (lib.mapAttrsToList (name: hcfg:
134 dataDir = "${cfg.base}/${name}/mysql";
135 backupDir = "${cfg.base}/${name}/mysql_backup";
136 backup_script = pkgs.writeScript "backup_mysql_${name}" ''
137 #!${pkgs.stdenv.shell}
141 ${hcfg.package}/bin/mysqldump \
142 --defaults-file=${config.secrets.location}/mysql_replication/${name}/mysqldump \
143 -S /run/mysqld_${name}/mysqld.sock \
147 --all-databases > ${backupDir}/$(${pkgs.coreutils}/bin/date -Iminutes).sql
149 u = pkgs.callPackage ./utils.nix {};
150 cleanup_script = pkgs.writeScript "cleanup_mysql_${name}" (u.exponentialDumps "sql" backupDir);
152 "0 22,4,10,16 * * * root ${backup_script}"
153 "0 3 * * * root ${cleanup_script}"
157 system.activationScripts = lib.attrsets.mapAttrs' (name: hcfg:
158 lib.attrsets.nameValuePair "mysql_replication_${name}" {
159 deps = [ "users" "groups" ];
161 install -m 0700 -o mysql -g mysql -d ${cfg.base}/${name}/mysql
162 install -m 0700 -o mysql -g mysql -d ${cfg.base}/${name}/mysql_backup
166 environment.etc = lib.attrsets.mapAttrs' (name: hcfg:
167 lib.attrsets.nameValuePair "mysql/${name}_my.cnf" {
171 socket = /run/mysqld_${name}/mysqld.sock
172 datadir = ${cfg.base}/${name}/mysql/
173 log-bin = mariadb-bin
174 server-id = ${builtins.toString hcfg.serverId}
179 systemd.services = lib.attrsets.mapAttrs' (name: hcfg:
181 dataDir = "${cfg.base}/${name}/mysql";
183 lib.attrsets.nameValuePair "mysql_backup_${name}" {
184 description = "Mysql replication for ${name}";
185 wantedBy = [ "multi-user.target" ];
186 after = [ "network.target" ];
187 restartTriggers = [ config.environment.etc."mysql/${name}_my.cnf".source ];
188 unitConfig.RequiresMountsFor = dataDir;
191 if ! test -e ${dataDir}/mysql; then
192 ${hcfg.package}/bin/mysqldump \
193 --defaults-file=${config.secrets.location}/mysql_replication/${name}/mysqldump_remote \
200 --all-databases > ${dataDir}/initial.sql
202 ${hcfg.package}/bin/mysql_install_db \
203 --defaults-file=/etc/mysql/${name}_my.cnf \
205 --datadir=${dataDir} \
206 --basedir=${hcfg.package}
213 RuntimeDirectory = "mysqld_${name}";
214 RuntimeDirectoryMode = "0755";
215 SupplementaryGroups = "keys";
216 PermissionsStartOnly = true;
219 ExecStart = "${hcfg.package}/bin/mysqld --defaults-file=/etc/mysql/${name}_my.cnf --user=mysql --datadir=${dataDir} --basedir=${hcfg.package}";
222 sql_before = pkgs.writeText "mysql-initial-before" ''
225 setupScript = pkgs.writeScript "mysql-setup" ''
226 #!${pkgs.runtimeShell} -e
228 if test -e ${dataDir}/initial.sql; then
231 ${dataDir}/initial.sql \
232 ${config.secrets.location}/mysql_replication/${name}/slave_init_commands \
233 | ${hcfg.package}/bin/mysql \
234 --defaults-file=/etc/mysql/${name}_my.cnf \
235 -S /run/mysqld_${name}/mysqld.sock \
237 rm -f ${dataDir}/initial.sql
242 # initial dump can take a long time
243 TimeoutStartSec="infinity";
244 TimeoutStopSec = 120;