X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=modules%2Fprivate%2Fdatabases%2Fmariadb.nix;h=101eb3fb7c850157b9b31786199d4a4084543cb5;hb=4c4652aabf2cb3ac8b40f2856eca07a1df9c27e0;hp=21f4359957f8be4225f070d5bd52f8a2e4c57a7b;hpb=182ae57f53731be220075bc87aff4d47a35563b8;p=perso%2FImmae%2FConfig%2FNix.git diff --git a/modules/private/databases/mariadb.nix b/modules/private/databases/mariadb.nix index 21f4359..101eb3f 100644 --- a/modules/private/databases/mariadb.nix +++ b/modules/private/databases/mariadb.nix @@ -1,15 +1,50 @@ -{ 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"; @@ -48,78 +83,100 @@ in { # 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 = /var/lib/acme/mysql/key.pem - ssl_cert = /var/lib/acme/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 ''; }; - secrets.keys = [ - { - dest = "mysql/mysqldump"; + secrets.keys = { + "mysql/mysqldump" = { permissions = "0400"; user = "root"; group = "root"; text = '' [mysqldump] user = root - password = ${myconfig.env.databases.mysql.systemUsers.root} + password = ${cfg.credentials.root} ''; - } - { - dest = "mysql/pam"; + }; + "mysql/pam" = { 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 - ''; - } - ]; - - 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 - '' - ]; + ''; + }; + "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 + ''; + }; }; 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 + auth required ${pam_ldap} config=${config.secrets.fullPaths."mysql/pam"} + account required ${pam_ldap} config=${config.secrets.fullPaths."mysql/pam"} + ''; + }; + mysql_replication = { + text = '' + auth required ${pam_ldap} config=${config.secrets.fullPaths."mysql/pam_replication"} + account required ${pam_ldap} config=${config.secrets.fullPaths."mysql/pam_replication"} ''; - } - ]; + }; + }; }; } -