Unverified Commit cc42a1be authored by Felix Bühler's avatar Felix Bühler Committed by GitHub
Browse files

nixos/services.mysql: remove `with lib;` (#338048)

parents 1d1c1c1b 8e91c6b7
Loading
Loading
Loading
Loading
+74 −77
Original line number Diff line number Diff line
{ config, lib, pkgs, ... }:

with lib;

let

  cfg = config.services.mysql;
@@ -9,7 +6,7 @@ let
  isMariaDB = lib.getName cfg.package == lib.getName pkgs.mariadb;
  isOracle = lib.getName cfg.package == lib.getName pkgs.mysql80;
  # Oracle MySQL has supported "notify" service type since 8.0
  hasNotify = isMariaDB || (isOracle && versionAtLeast cfg.package.version "8.0");
  hasNotify = isMariaDB || (isOracle && lib.versionAtLeast cfg.package.version "8.0");

  mysqldOptions =
    "--user=${cfg.user} --datadir=${cfg.dataDir} --basedir=${cfg.package}";
@@ -21,11 +18,11 @@ in

{
  imports = [
    (mkRemovedOptionModule [ "services" "mysql" "pidDir" ] "Don't wait for pidfiles, describe dependencies through systemd.")
    (mkRemovedOptionModule [ "services" "mysql" "rootPassword" ] "Use socket authentication or set the password outside of the nix store.")
    (mkRemovedOptionModule [ "services" "mysql" "extraOptions" ] "Use services.mysql.settings.mysqld instead.")
    (mkRemovedOptionModule [ "services" "mysql" "bind" ] "Use services.mysql.settings.mysqld.bind-address instead.")
    (mkRemovedOptionModule [ "services" "mysql" "port" ] "Use services.mysql.settings.mysqld.port instead.")
    (lib.mkRemovedOptionModule [ "services" "mysql" "pidDir" ] "Don't wait for pidfiles, describe dependencies through systemd.")
    (lib.mkRemovedOptionModule [ "services" "mysql" "rootPassword" ] "Use socket authentication or set the password outside of the nix store.")
    (lib.mkRemovedOptionModule [ "services" "mysql" "extraOptions" ] "Use services.mysql.settings.mysqld instead.")
    (lib.mkRemovedOptionModule [ "services" "mysql" "bind" ] "Use services.mysql.settings.mysqld.bind-address instead.")
    (lib.mkRemovedOptionModule [ "services" "mysql" "port" ] "Use services.mysql.settings.mysqld.port instead.")
  ];

  ###### interface
@@ -34,18 +31,18 @@ in

    services.mysql = {

      enable = mkEnableOption "MySQL server";
      enable = lib.mkEnableOption "MySQL server";

      package = mkOption {
        type = types.package;
        example = literalExpression "pkgs.mariadb";
      package = lib.mkOption {
        type = lib.types.package;
        example = lib.literalExpression "pkgs.mariadb";
        description = ''
          Which MySQL derivation to use. MariaDB packages are supported too.
        '';
      };

      user = mkOption {
        type = types.str;
      user = lib.mkOption {
        type = lib.types.str;
        default = "mysql";
        description = ''
          User account under which MySQL runs.
@@ -58,8 +55,8 @@ in
        '';
      };

      group = mkOption {
        type = types.str;
      group = lib.mkOption {
        type = lib.types.str;
        default = "mysql";
        description = ''
          Group account under which MySQL runs.
@@ -72,8 +69,8 @@ in
        '';
      };

      dataDir = mkOption {
        type = types.path;
      dataDir = lib.mkOption {
        type = lib.types.path;
        example = "/var/lib/mysql";
        description = ''
          The data directory for MySQL.
@@ -85,8 +82,8 @@ in
        '';
      };

      configFile = mkOption {
        type = types.path;
      configFile = lib.mkOption {
        type = lib.types.path;
        default = configFile;
        defaultText = ''
          A configuration file automatically generated by NixOS.
@@ -95,7 +92,7 @@ in
          Override the configuration file used by MySQL. By default,
          NixOS generates one automatically from {option}`services.mysql.settings`.
        '';
        example = literalExpression ''
        example = lib.literalExpression ''
          pkgs.writeText "my.cnf" '''
            [mysqld]
            datadir = /var/lib/mysql
@@ -107,7 +104,7 @@ in
        '';
      };

      settings = mkOption {
      settings = lib.mkOption {
        type = format.type;
        default = {};
        description = ''
@@ -123,7 +120,7 @@ in
          `1`, or `0`. See the provided example below.
          :::
        '';
        example = literalExpression ''
        example = lib.literalExpression ''
          {
            mysqld = {
              key_buffer_size = "6G";
@@ -139,17 +136,17 @@ in
        '';
      };

      initialDatabases = mkOption {
        type = types.listOf (types.submodule {
      initialDatabases = lib.mkOption {
        type = lib.types.listOf (lib.types.submodule {
          options = {
            name = mkOption {
              type = types.str;
            name = lib.mkOption {
              type = lib.types.str;
              description = ''
                The name of the database to create.
              '';
            };
            schema = mkOption {
              type = types.nullOr types.path;
            schema = lib.mkOption {
              type = lib.types.nullOr lib.types.path;
              default = null;
              description = ''
                The initial schema of the database; if null (the default),
@@ -163,7 +160,7 @@ in
          List of database names and their initial schemas that should be used to create databases on the first startup
          of MySQL. The schema attribute is optional: If not specified, an empty database is created.
        '';
        example = literalExpression ''
        example = lib.literalExpression ''
          [
            { name = "foodatabase"; schema = ./foodatabase.sql; }
            { name = "bardatabase"; }
@@ -171,14 +168,14 @@ in
        '';
      };

      initialScript = mkOption {
        type = types.nullOr types.path;
      initialScript = lib.mkOption {
        type = lib.types.nullOr lib.types.path;
        default = null;
        description = "A file containing SQL statements to be executed on the first startup. Can be used for granting certain permissions on the database.";
      };

      ensureDatabases = mkOption {
        type = types.listOf types.str;
      ensureDatabases = lib.mkOption {
        type = lib.types.listOf lib.types.str;
        default = [];
        description = ''
          Ensures that the specified databases exist.
@@ -192,17 +189,17 @@ in
        ];
      };

      ensureUsers = mkOption {
        type = types.listOf (types.submodule {
      ensureUsers = lib.mkOption {
        type = lib.types.listOf (lib.types.submodule {
          options = {
            name = mkOption {
              type = types.str;
            name = lib.mkOption {
              type = lib.types.str;
              description = ''
                Name of the user to ensure.
              '';
            };
            ensurePermissions = mkOption {
              type = types.attrsOf types.str;
            ensurePermissions = lib.mkOption {
              type = lib.types.attrsOf lib.types.str;
              default = {};
              description = ''
                Permissions to ensure for the user, specified as attribute set.
@@ -216,7 +213,7 @@ in
                [GRANT syntax](https://mariadb.com/kb/en/library/grant/).
                The attributes are used as `GRANT ''${attrName} ON ''${attrValue}`.
              '';
              example = literalExpression ''
              example = lib.literalExpression ''
                {
                  "database.*" = "ALL PRIVILEGES";
                  "*.*" = "SELECT, LOCK TABLES";
@@ -234,7 +231,7 @@ in
          option is changed. This means that users created and permissions assigned once through this option or
          otherwise have to be removed manually.
        '';
        example = literalExpression ''
        example = lib.literalExpression ''
          [
            {
              name = "nextcloud";
@@ -253,40 +250,40 @@ in
      };

      replication = {
        role = mkOption {
          type = types.enum [ "master" "slave" "none" ];
        role = lib.mkOption {
          type = lib.types.enum [ "master" "slave" "none" ];
          default = "none";
          description = "Role of the MySQL server instance.";
        };

        serverId = mkOption {
          type = types.int;
        serverId = lib.mkOption {
          type = lib.types.int;
          default = 1;
          description = "Id of the MySQL server instance. This number must be unique for each instance.";
        };

        masterHost = mkOption {
          type = types.str;
        masterHost = lib.mkOption {
          type = lib.types.str;
          description = "Hostname of the MySQL master server.";
        };

        slaveHost = mkOption {
          type = types.str;
        slaveHost = lib.mkOption {
          type = lib.types.str;
          description = "Hostname of the MySQL slave server.";
        };

        masterUser = mkOption {
          type = types.str;
        masterUser = lib.mkOption {
          type = lib.types.str;
          description = "Username of the MySQL replication user.";
        };

        masterPassword = mkOption {
          type = types.str;
        masterPassword = lib.mkOption {
          type = lib.types.str;
          description = "Password of the MySQL replication user.";
        };

        masterPort = mkOption {
          type = types.port;
        masterPort = lib.mkOption {
          type = lib.types.port;
          default = 3306;
          description = "Port number on which the MySQL master server runs.";
        };
@@ -298,30 +295,30 @@ in

  ###### implementation

  config = mkIf cfg.enable {
  config = lib.mkIf cfg.enable {

    services.mysql.dataDir =
      mkDefault (if versionAtLeast config.system.stateVersion "17.09" then "/var/lib/mysql"
      lib.mkDefault (if lib.versionAtLeast config.system.stateVersion "17.09" then "/var/lib/mysql"
                 else "/var/mysql");

    services.mysql.settings.mysqld = mkMerge [
    services.mysql.settings.mysqld = lib.mkMerge [
      {
        datadir = cfg.dataDir;
        port = mkDefault 3306;
        port = lib.mkDefault 3306;
      }
      (mkIf (cfg.replication.role == "master" || cfg.replication.role == "slave") {
      (lib.mkIf (cfg.replication.role == "master" || cfg.replication.role == "slave") {
        log-bin = "mysql-bin-${toString cfg.replication.serverId}";
        log-bin-index = "mysql-bin-${toString cfg.replication.serverId}.index";
        relay-log = "mysql-relay-bin";
        server-id = cfg.replication.serverId;
        binlog-ignore-db = [ "information_schema" "performance_schema" "mysql" ];
      })
      (mkIf (!isMariaDB) {
      (lib.mkIf (!isMariaDB) {
        plugin-load-add = "auth_socket.so";
      })
    ];

    users.users = optionalAttrs (cfg.user == "mysql") {
    users.users = lib.optionalAttrs (cfg.user == "mysql") {
      mysql = {
        description = "MySQL server user";
        group = cfg.group;
@@ -329,7 +326,7 @@ in
      };
    };

    users.groups = optionalAttrs (cfg.group == "mysql") {
    users.groups = lib.optionalAttrs (cfg.group == "mysql") {
      mysql.gid = config.ids.gids.mysql;
    };

@@ -380,7 +377,7 @@ in
        # The super user account to use on *first* run of MySQL server
        superUser = if isMariaDB then cfg.user else "root";
      in ''
        ${optionalString (!hasNotify) ''
        ${lib.optionalString (!hasNotify) ''
          # Wait until the MySQL server is available for use
          while [ ! -e /run/mysqld/mysqld.sock ]
          do
@@ -397,13 +394,13 @@ in
              echo "GRANT ALL PRIVILEGES ON *.* TO '${cfg.user}'@'localhost' WITH GRANT OPTION;"
            ) | ${cfg.package}/bin/mysql -u ${superUser} -N

            ${concatMapStrings (database: ''
            ${lib.concatMapStrings (database: ''
              # Create initial databases
              if ! test -e "${cfg.dataDir}/${database.name}"; then
                  echo "Creating initial database: ${database.name}"
                  ( echo 'create database `${database.name}`;'

                    ${optionalString (database.schema != null) ''
                    ${lib.optionalString (database.schema != null) ''
                    echo 'use `${database.name}`;'

                    # TODO: this silently falls through if database.schema does not exist,
@@ -420,7 +417,7 @@ in
              fi
            '') cfg.initialDatabases}

            ${optionalString (cfg.replication.role == "master")
            ${lib.optionalString (cfg.replication.role == "master")
              ''
                # Set up the replication master

@@ -431,7 +428,7 @@ in
                ) | ${cfg.package}/bin/mysql -u ${superUser} -N
              ''}

            ${optionalString (cfg.replication.role == "slave")
            ${lib.optionalString (cfg.replication.role == "slave")
              ''
                # Set up the replication slave

@@ -441,7 +438,7 @@ in
                ) | ${cfg.package}/bin/mysql -u ${superUser} -N
              ''}

            ${optionalString (cfg.initialScript != null)
            ${lib.optionalString (cfg.initialScript != null)
              ''
                # Execute initial script
                # using toString to avoid copying the file to nix store if given as path instead of string,
@@ -452,25 +449,25 @@ in
            rm ${cfg.dataDir}/mysql_init
        fi

        ${optionalString (cfg.ensureDatabases != []) ''
        ${lib.optionalString (cfg.ensureDatabases != []) ''
          (
          ${concatMapStrings (database: ''
          ${lib.concatMapStrings (database: ''
            echo "CREATE DATABASE IF NOT EXISTS \`${database}\`;"
          '') cfg.ensureDatabases}
          ) | ${cfg.package}/bin/mysql -N
        ''}

        ${concatMapStrings (user:
        ${lib.concatMapStrings (user:
          ''
            ( echo "CREATE USER IF NOT EXISTS '${user.name}'@'localhost' IDENTIFIED WITH ${if isMariaDB then "unix_socket" else "auth_socket"};"
              ${concatStringsSep "\n" (mapAttrsToList (database: permission: ''
              ${lib.concatStringsSep "\n" (lib.mapAttrsToList (database: permission: ''
                echo "GRANT ${permission} ON ${database} TO '${user.name}'@'localhost';"
              '') user.ensurePermissions)}
            ) | ${cfg.package}/bin/mysql -N
          '') cfg.ensureUsers}
      '';

      serviceConfig = mkMerge [
      serviceConfig = lib.mkMerge [
        {
          Type = if hasNotify then "notify" else "simple";
          Restart = "on-abort";
@@ -506,7 +503,7 @@ in
          # System Call Filtering
          SystemCallArchitectures = "native";
        }
        (mkIf (cfg.dataDir == "/var/lib/mysql") {
        (lib.mkIf (cfg.dataDir == "/var/lib/mysql") {
          StateDirectory = "mysql";
          StateDirectoryMode = "0700";
        })