{ config, pkgs, lib, ... }: { services.mysql = { enable = true; package = pkgs.mariadb; dataDir = "/var/lib/mysql"; settings.mysqld = { bind-address = "0.0.0.0"; # InnoDB innodb_buffer_pool_size = "512M"; innodb_log_file_size = "128M"; innodb_flush_log_at_trx_commit = 1; innodb_file_per_table = 1; # GTID replication (required for MASTER_AUTO_POSITION) server-id = 1; log_bin = "mysql-bin"; binlog_format = "ROW"; sync_binlog = 1; expire_logs_days = 7; binlog_do_db = "noisebridge_mediawiki"; gtid_strict_mode = 1; # Performance max_connections = 100; tmp_table_size = "64M"; max_heap_table_size = "64M"; table_open_cache = 400; sort_buffer_size = "2M"; read_buffer_size = "2M"; # Character set character-set-server = "binary"; collation-server = "binary"; }; ensureDatabases = [ "noisebridge_mediawiki" ]; ensureUsers = [ { name = "wiki"; ensurePermissions = { "noisebridge_mediawiki.*" = "ALL PRIVILEGES"; }; } { name = "repl"; ensurePermissions = { "*.*" = "REPLICATION SLAVE, REPLICATION CLIENT"; }; } { name = "mysqld_exporter"; ensurePermissions = { "*.*" = "PROCESS, REPLICATION CLIENT, SELECT"; }; } ]; }; # Set repl user password (ensureUsers creates with no password / socket auth, # but the replica connects over TCP and needs a password) systemd.services.mysql-repl-password = { description = "Set MySQL replication user password"; after = [ "mysql.service" ]; requires = [ "mysql.service" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; }; script = '' REPL_PASS=$(cat ${config.age.secrets.mysql-replication.path}) ${pkgs.mariadb}/bin/mysql -u root -e \ "ALTER USER 'repl'@'%' IDENTIFIED BY '$REPL_PASS';" ''; }; # mysqld exporter for Prometheus services.prometheus.exporters.mysqld = { enable = true; port = 9104; runAsLocalSuperUser = true; }; age.secrets.mysql-replication = { file = ../../secrets/mysql-replication.age; owner = "mysql"; group = "mysql"; }; }