diff --git a/nixos/modules/services/databases/mysql.nix b/nixos/modules/services/databases/mysql.nix index 4f5d442db8bf..c1a6b895bdd1 100644 --- a/nixos/modules/services/databases/mysql.nix +++ b/nixos/modules/services/databases/mysql.nix @@ -321,7 +321,7 @@ in binlog-ignore-db = [ "information_schema" "performance_schema" "mysql" ]; }) (mkIf (!isMariaDB) { - plugin-load-add = optional (cfg.ensureUsers != []) "auth_socket.so"; + plugin-load-add = "auth_socket.so"; }) ]; @@ -383,6 +383,8 @@ in ExecStart = "${cfg.package}/bin/mysqld --defaults-file=/etc/my.cnf ${mysqldOptions} $_WSREP_NEW_CLUSTER $_WSREP_START_POSITION"; ExecStartPost = let + # The super user account to use on *first* run of MySQL server + superUser = if isMariaDB then cfg.user else "root"; setupScript = pkgs.writeScript "mysql-setup" '' #!${pkgs.runtimeShell} -e @@ -405,6 +407,12 @@ in if [ -f ${cfg.dataDir}/mysql_init ] then + # While MariaDB comes with a 'mysql' super user account since 10.4.x MySQL does not + # Since we don't want to run this service as 'root' we need to ensure the account exists on first run + ( echo "CREATE USER IF NOT EXISTS '${cfg.user}'@'localhost' IDENTIFIED WITH ${if isMariaDB then "unix_socket" else "auth_socket"};" + echo "GRANT ALL PRIVILEGES ON *.* TO '${cfg.user}'@'localhost' WITH GRANT OPTION;" + ) | ${cfg.package}/bin/mysql -u ${superUser} -N + ${concatMapStrings (database: '' # Create initial databases if ! test -e "${cfg.dataDir}/${database.name}"; then @@ -424,7 +432,7 @@ in cat ${database.schema}/mysql-databases/*.sql fi ''} - ) | ${cfg.package}/bin/mysql -u root -N + ) | ${cfg.package}/bin/mysql -u ${superUser} -N fi '') cfg.initialDatabases} @@ -436,7 +444,7 @@ in echo "CREATE USER '${cfg.replication.masterUser}'@'${cfg.replication.slaveHost}' IDENTIFIED WITH mysql_native_password;" echo "SET PASSWORD FOR '${cfg.replication.masterUser}'@'${cfg.replication.slaveHost}' = PASSWORD('${cfg.replication.masterPassword}');" echo "GRANT REPLICATION SLAVE ON *.* TO '${cfg.replication.masterUser}'@'${cfg.replication.slaveHost}';" - ) | ${cfg.package}/bin/mysql -u root -N + ) | ${cfg.package}/bin/mysql -u ${superUser} -N ''} ${optionalString (cfg.replication.role == "slave") @@ -446,7 +454,7 @@ in ( echo "stop slave;" echo "change master to master_host='${cfg.replication.masterHost}', master_user='${cfg.replication.masterUser}', master_password='${cfg.replication.masterPassword}';" echo "start slave;" - ) | ${cfg.package}/bin/mysql -u root -N + ) | ${cfg.package}/bin/mysql -u ${superUser} -N ''} ${optionalString (cfg.initialScript != null) @@ -454,7 +462,7 @@ in # Execute initial script # using toString to avoid copying the file to nix store if given as path instead of string, # as it might contain credentials - cat ${toString cfg.initialScript} | ${cfg.package}/bin/mysql -u root -N + cat ${toString cfg.initialScript} | ${cfg.package}/bin/mysql -u ${superUser} -N ''} rm ${cfg.dataDir}/mysql_init @@ -465,7 +473,7 @@ in ${concatMapStrings (database: '' echo "CREATE DATABASE IF NOT EXISTS \`${database}\`;" '') cfg.ensureDatabases} - ) | ${cfg.package}/bin/mysql -u root -N + ) | ${cfg.package}/bin/mysql -N ''} ${concatMapStrings (user: @@ -474,13 +482,11 @@ in ${concatStringsSep "\n" (mapAttrsToList (database: permission: '' echo "GRANT ${permission} ON ${database} TO '${user.name}'@'localhost';" '') user.ensurePermissions)} - ) | ${cfg.package}/bin/mysql -u root -N + ) | ${cfg.package}/bin/mysql -N '') cfg.ensureUsers} ''; in - # ensureDatbases & ensureUsers depends on this script being run as root - # when the user has secured their mysql install - "+${setupScript}"; + "${setupScript}"; # User and group User = cfg.user; Group = cfg.group;