]> git.immae.eu Git - perso/Immae/Config/Nix.git/blobdiff - modules/private/databases/mariadb.nix
Move secrets to flakes
[perso/Immae/Config/Nix.git] / modules / private / databases / mariadb.nix
index 21f4359957f8be4225f070d5bd52f8a2e4c57a7b..75ea747147896437ad6480a2159a52a0e19f31e6 100644 (file)
@@ -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,22 +83,38 @@ 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
@@ -79,7 +130,7 @@ in {
         text = ''
           [mysqldump]
           user = root
-          password = ${myconfig.env.databases.mysql.systemUsers.root}
+          password = ${cfg.credentials.root}
         '';
       }
       {
@@ -87,39 +138,48 @@ in {
         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
+          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"}
+          '';
+      };
+    };
 
   };
 }
-