+++ /dev/null
-{ lib, pkgs, config, ... }:
-let
- cfg = config.myServices.databases.mariadb;
-in {
- options.myServices.databases = {
- mariadb = {
- enable = lib.mkOption {
- 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";
- description = ''
- The directory where Mariadb stores its data.
- '';
- };
- # Output variables
- socketsDir = lib.mkOption {
- type = lib.types.path;
- default = "/run/mysqld";
- description = ''
- The directory where Mariadb puts sockets.
- '';
- };
- sockets = lib.mkOption {
- type = lib.types.attrsOf lib.types.path;
- default = {
- mysqld = "${cfg.socketsDir}/mysqld.sock";
- };
- readOnly = true;
- description = ''
- Mariadb sockets
- '';
- };
- };
- };
-
- config = lib.mkIf cfg.enable {
- networking.firewall.allowedTCPPorts = [ 3306 ];
-
- # for adminer, ssl is implemented with mysqli only, which is
- # currently disabled because it’s not compatible with pam.
- # Thus we need to generate two users for each 'remote': one remote
- # with SSL, and one localhost without SSL.
- # 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 = cfg.package;
- dataDir = cfg.dataDir;
- 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";
- domain = "db-1.immae.eu";
- postRun = ''
- systemctl restart mysql.service
- '';
- };
-
- secrets.keys = {
- "mysql/mysqldump" = {
- permissions = "0400";
- user = "root";
- group = "root";
- text = ''
- [mysqldump]
- user = root
- password = ${cfg.credentials.root}
- '';
- };
- "mysql/pam" = {
- permissions = "0400";
- user = "mysql";
- group = "mysql";
- text = with cfg.ldapConfig; ''
- host ${host}
- base ${base}
- binddn ${dn}
- bindpw ${password}
- pam_filter ${filter}
- ssl start_tls
- '';
- };
- "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 {
- mysql = {
- text = ''
- # https://mariadb.com/kb/en/mariadb/pam-authentication-plugin/
- 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"}
- '';
- };
- };
-
- };
-}