--- /dev/null
+{ lib, pkgs, config, myconfig, ... }:
+let
+ cfg = config.myServices.databases.mariadb;
+in {
+ options.myServices.databases = {
+ mariadb = {
+ enable = lib.mkOption {
+ default = cfg.enable;
+ example = true;
+ description = "Whether to enable mariadb database";
+ type = lib.types.bool;
+ };
+ 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';
+ services.mysql = {
+ enable = true;
+ package = pkgs.mariadb;
+ 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
+ '';
+ };
+
+ 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";
+ permissions = "0400";
+ user = "root";
+ group = "root";
+ text = ''
+ [mysqldump]
+ user = root
+ password = ${myconfig.env.databases.mysql.systemUsers.root}
+ '';
+ }
+ {
+ dest = "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}
+ 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
+ ''
+ ];
+ };
+
+ security.pam.services = let
+ pam_ldap = "${pkgs.pam_ldap}/lib/security/pam_ldap.so";
+ in [
+ {
+ name = "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
+ '';
+ }
+ ];
+
+ };
+}
+