-{ lib, pkgs, config, myconfig, ... }:
+{ lib, pkgs, config, ... }:
let
cfg = config.myServices.databases.mariadb;
in {
options.myServices.databases = {
mariadb = {
enable = lib.mkOption {
- default = cfg.enable;
+ default = false;
example = true;
description = "Whether to enable mariadb database";
type = lib.types.bool;
};
+ package = lib.mkOption {
+ type = lib.types.package;
+ default = pkgs.mariadb;
+ description = ''
+ Mariadb package to use.
+ '';
+ };
+ credentials = lib.mkOption {
+ default = {};
+ description = "Credentials";
+ type = lib.types.attrsOf lib.types.str;
+ };
+ ldapConfig = lib.mkOption {
+ description = "LDAP configuration to allow PAM identification via LDAP";
+ type = lib.types.submodule {
+ options = {
+ host = lib.mkOption { type = lib.types.str; };
+ base = lib.mkOption { type = lib.types.str; };
+ dn = lib.mkOption { type = lib.types.str; };
+ password = lib.mkOption { type = lib.types.str; };
+ filter = lib.mkOption { type = lib.types.str; };
+ };
+ };
+ };
+ replicationLdapConfig = lib.mkOption {
+ description = "LDAP configuration to allow replication";
+ type = lib.types.submodule {
+ options = {
+ host = lib.mkOption { type = lib.types.str; };
+ base = lib.mkOption { type = lib.types.str; };
+ dn = lib.mkOption { type = lib.types.str; };
+ password = lib.mkOption { type = lib.types.str; };
+ };
+ };
+ };
dataDir = lib.mkOption {
type = lib.types.path;
default = "/var/lib/mysql";
# User identified by LDAP:
# CREATE USER foo@% IDENTIFIED VIA pam USING 'mysql' REQUIRE SSL;
# CREATE USER foo@localhost IDENTIFIED VIA pam USING 'mysql';
+
+ # To create a user (host) for replication:
+ # CREATE USER 'host'@'%' IDENTIFIED VIA pam USING 'mysql_replication' REQUIRE SSL;
+ # GRANT REPLICATION SLAVE, REPLICATION CLIENT, RELOAD, LOCK TABLES, SELECT, SHOW VIEW ON *.* TO 'host'@'%';
+ # (the lock/select grant permits to let the replication host handle
+ # the initial fetch of the database)
+ # % should be valid for both localhost (for cron dumps) and the origin host.
services.mysql = {
enable = true;
- package = pkgs.mariadb;
+ package = cfg.package;
dataDir = cfg.dataDir;
- extraOptions = ''
- ssl_ca = ${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt
- ssl_key = ${config.security.acme.directory}/mysql/key.pem
- ssl_cert = ${config.security.acme.directory}/mysql/fullchain.pem
- '';
+ settings = {
+ mysqld = {
+ ssl_ca = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
+ ssl_key = "${config.security.acme.certs.mysql.directory}/key.pem";
+ ssl_cert = "${config.security.acme.certs.mysql.directory}/fullchain.pem";
+
+ # for replication
+ log-bin = "mariadb-bin";
+ server-id = "1";
+
+ # this introduces a small delay before storing on disk, but
+ # makes it order of magnitudes quicker
+ innodb_flush_log_at_trx_commit = "0";
+ };
+ };
};
users.users.mysql.extraGroups = [ "keys" ];
security.acme.certs."mysql" = config.myServices.databasesCerts // {
user = "mysql";
group = "mysql";
- plugins = [ "fullchain.pem" "key.pem" "account_key.json" ];
domain = "db-1.immae.eu";
postRun = ''
systemctl restart mysql.service
text = ''
[mysqldump]
user = root
- password = ${myconfig.env.databases.mysql.systemUsers.root}
+ password = ${cfg.credentials.root}
'';
}
{
permissions = "0400";
user = "mysql";
group = "mysql";
- text = with myconfig.env.databases.mysql.pam; ''
- host ${myconfig.env.ldap.host}
- base ${myconfig.env.ldap.base}
+ text = with cfg.ldapConfig; ''
+ host ${host}
+ base ${base}
binddn ${dn}
bindpw ${password}
pam_filter ${filter}
ssl start_tls
- '';
+ '';
+ }
+ {
+ dest = "mysql/pam_replication";
+ permissions = "0400";
+ user = "mysql";
+ group = "mysql";
+ text = with cfg.replicationLdapConfig; ''
+ host ${host}
+ base ${base}
+ binddn ${dn}
+ bindpw ${password}
+ pam_login_attribute cn
+ ssl start_tls
+ '';
}
];
- services.cron = {
- enable = true;
- systemCronJobs = [
- ''
- 30 1,13 * * * root ${pkgs.mariadb}/bin/mysqldump --defaults-file=${config.secrets.location}/mysql/mysqldump --all-databases > ${cfg.dataDir}/backup.sql
- ''
- ];
- };
-
security.pam.services = let
pam_ldap = "${pkgs.pam_ldap}/lib/security/pam_ldap.so";
- in [
- {
- name = "mysql";
+ in {
+ mysql = {
text = ''
# https://mariadb.com/kb/en/mariadb/pam-authentication-plugin/
auth required ${pam_ldap} config=${config.secrets.location}/mysql/pam
account required ${pam_ldap} config=${config.secrets.location}/mysql/pam
'';
- }
- ];
+ };
+ mysql_replication = {
+ text = ''
+ auth required ${pam_ldap} config=${config.secrets.location}/mysql/pam_replication
+ account required ${pam_ldap} config=${config.secrets.location}/mysql/pam_replication
+ '';
+ };
+ };
};
}
-