From 9b56677634938860eedd06f9415432add0491ad7 Mon Sep 17 00:00:00 2001 From: Aaron Andersen Date: Tue, 11 Aug 2020 21:09:41 -0400 Subject: [PATCH 1/7] nixos/mysql: remove variable with confusing name --- nixos/modules/services/databases/mysql.nix | 26 ++++++++++------------ 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/nixos/modules/services/databases/mysql.nix b/nixos/modules/services/databases/mysql.nix index 2e8c5b7640b2..63e769e0b0bc 100644 --- a/nixos/modules/services/databases/mysql.nix +++ b/nixos/modules/services/databases/mysql.nix @@ -6,12 +6,10 @@ let cfg = config.services.mysql; - mysql = cfg.package; - - isMariaDB = lib.getName mysql == lib.getName pkgs.mariadb; + isMariaDB = lib.getName cfg.package == lib.getName pkgs.mariadb; mysqldOptions = - "--user=${cfg.user} --datadir=${cfg.dataDir} --basedir=${mysql}"; + "--user=${cfg.user} --datadir=${cfg.dataDir} --basedir=${cfg.package}"; settingsFile = pkgs.writeText "my.cnf" ( generators.toINI { listsAsDuplicateKeys = true; } cfg.settings + @@ -329,7 +327,7 @@ in users.groups.mysql.gid = config.ids.gids.mysql; - environment.systemPackages = [mysql]; + environment.systemPackages = [ cfg.package ]; environment.etc."my.cnf".source = cfg.configFile; @@ -357,12 +355,12 @@ in preStart = if isMariaDB then '' if ! test -e ${cfg.dataDir}/mysql; then - ${mysql}/bin/mysql_install_db --defaults-file=/etc/my.cnf ${mysqldOptions} + ${cfg.package}/bin/mysql_install_db --defaults-file=/etc/my.cnf ${mysqldOptions} touch ${cfg.dataDir}/mysql_init fi '' else '' if ! test -e ${cfg.dataDir}/mysql; then - ${mysql}/bin/mysqld --defaults-file=/etc/my.cnf ${mysqldOptions} --initialize-insecure + ${cfg.package}/bin/mysqld --defaults-file=/etc/my.cnf ${mysqldOptions} --initialize-insecure touch ${cfg.dataDir}/mysql_init fi ''; @@ -372,7 +370,7 @@ in Restart = "on-abort"; RestartSec = "5s"; # The last two environment variables are used for starting Galera clusters - ExecStart = "${mysql}/bin/mysqld --defaults-file=/etc/my.cnf ${mysqldOptions} $_WSREP_NEW_CLUSTER $_WSREP_START_POSITION"; + ExecStart = "${cfg.package}/bin/mysqld --defaults-file=/etc/my.cnf ${mysqldOptions} $_WSREP_NEW_CLUSTER $_WSREP_START_POSITION"; ExecStartPost = let setupScript = pkgs.writeScript "mysql-setup" '' @@ -416,7 +414,7 @@ in cat ${database.schema}/mysql-databases/*.sql fi ''} - ) | ${mysql}/bin/mysql -u root -N + ) | ${cfg.package}/bin/mysql -u root -N fi '') cfg.initialDatabases} @@ -428,7 +426,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}';" - ) | ${mysql}/bin/mysql -u root -N + ) | ${cfg.package}/bin/mysql -u root -N ''} ${optionalString (cfg.replication.role == "slave") @@ -438,7 +436,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;" - ) | ${mysql}/bin/mysql -u root -N + ) | ${cfg.package}/bin/mysql -u root -N ''} ${optionalString (cfg.initialScript != null) @@ -446,7 +444,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} | ${mysql}/bin/mysql -u root -N + cat ${toString cfg.initialScript} | ${cfg.package}/bin/mysql -u root -N ''} rm ${cfg.dataDir}/mysql_init @@ -457,7 +455,7 @@ in ${concatMapStrings (database: '' echo "CREATE DATABASE IF NOT EXISTS \`${database}\`;" '') cfg.ensureDatabases} - ) | ${mysql}/bin/mysql -u root -N + ) | ${cfg.package}/bin/mysql -u root -N ''} ${concatMapStrings (user: @@ -466,7 +464,7 @@ in ${concatStringsSep "\n" (mapAttrsToList (database: permission: '' echo "GRANT ${permission} ON ${database} TO '${user.name}'@'localhost';" '') user.ensurePermissions)} - ) | ${mysql}/bin/mysql -u root -N + ) | ${cfg.package}/bin/mysql -u root -N '') cfg.ensureUsers} ''; in From 3792fef4ec8ec089ae244a35172e540d34a9b06c Mon Sep 17 00:00:00 2001 From: Aaron Andersen Date: Tue, 11 Aug 2020 21:12:59 -0400 Subject: [PATCH 2/7] nixos/mysql: add group option --- nixos/modules/services/databases/mysql.nix | 26 +++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/nixos/modules/services/databases/mysql.nix b/nixos/modules/services/databases/mysql.nix index 63e769e0b0bc..021a9bbe6eb5 100644 --- a/nixos/modules/services/databases/mysql.nix +++ b/nixos/modules/services/databases/mysql.nix @@ -59,6 +59,12 @@ in description = "User account under which MySQL runs"; }; + group = mkOption { + type = types.str; + default = "mysql"; + description = "Group under which MySQL runs."; + }; + dataDir = mkOption { type = types.path; example = "/var/lib/mysql"; @@ -319,21 +325,25 @@ in }) ]; - users.users.mysql = { - description = "MySQL server user"; - group = "mysql"; - uid = config.ids.uids.mysql; + users.users = optionalAttrs (cfg.user == "mysql") { + mysql = { + description = "MySQL server user"; + group = cfg.group; + uid = config.ids.uids.mysql; + }; }; - users.groups.mysql.gid = config.ids.gids.mysql; + users.groups = optionalAttrs (cfg.group == "mysql") { + mysql.gid = config.ids.gids.mysql; + }; environment.systemPackages = [ cfg.package ]; environment.etc."my.cnf".source = cfg.configFile; systemd.tmpfiles.rules = [ - "d '${cfg.dataDir}' 0700 ${cfg.user} mysql - -" - "z '${cfg.dataDir}' 0700 ${cfg.user} mysql - -" + "d '${cfg.dataDir}' 0700 '${cfg.user}' '${cfg.group}' - -" + "z '${cfg.dataDir}' 0700 '${cfg.user}' '${cfg.group}' - -" ]; systemd.services.mysql = let @@ -473,7 +483,7 @@ in "+${setupScript}"; # User and group User = cfg.user; - Group = "mysql"; + Group = cfg.group; # Runtime directory and mode RuntimeDirectory = "mysqld"; RuntimeDirectoryMode = "0755"; From ff9921f0fd26432b9a7ef46a70eab237fb4865ae Mon Sep 17 00:00:00 2001 From: Aaron Andersen Date: Tue, 11 Aug 2020 21:15:02 -0400 Subject: [PATCH 3/7] nixos/mysql: loosen mariadb check --- nixos/modules/services/databases/mysql.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/modules/services/databases/mysql.nix b/nixos/modules/services/databases/mysql.nix index 021a9bbe6eb5..c6d30b3796f5 100644 --- a/nixos/modules/services/databases/mysql.nix +++ b/nixos/modules/services/databases/mysql.nix @@ -347,7 +347,7 @@ in ]; systemd.services.mysql = let - hasNotify = (cfg.package == pkgs.mariadb); + hasNotify = isMariaDB; in { description = "MySQL Server"; From 31098a03a21b29204c4616d756878e05d399a3da Mon Sep 17 00:00:00 2001 From: Aaron Andersen Date: Tue, 11 Aug 2020 21:17:02 -0400 Subject: [PATCH 4/7] nixos/mysql: cleanup some descriptions --- nixos/modules/services/databases/mysql.nix | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/nixos/modules/services/databases/mysql.nix b/nixos/modules/services/databases/mysql.nix index c6d30b3796f5..4f5d442db8bf 100644 --- a/nixos/modules/services/databases/mysql.nix +++ b/nixos/modules/services/databases/mysql.nix @@ -20,7 +20,7 @@ in { imports = [ - (mkRemovedOptionModule [ "services" "mysql" "pidDir" ] "Don't wait for pidfiles, describe dependencies through systemd") + (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.") ]; @@ -44,19 +44,19 @@ in type = types.nullOr types.str; default = null; example = literalExample "0.0.0.0"; - description = "Address to bind to. The default is to bind to all addresses"; + description = "Address to bind to. The default is to bind to all addresses."; }; port = mkOption { type = types.int; default = 3306; - description = "Port of MySQL"; + description = "Port of MySQL."; }; user = mkOption { type = types.str; default = "mysql"; - description = "User account under which MySQL runs"; + description = "User account under which MySQL runs."; }; group = mkOption { @@ -68,7 +68,7 @@ in dataDir = mkOption { type = types.path; example = "/var/lib/mysql"; - description = "Location where MySQL stores its table files"; + description = "Location where MySQL stores its table files."; }; configFile = mkOption { @@ -175,7 +175,7 @@ in initialScript = mkOption { type = types.nullOr 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"; + 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 { @@ -263,33 +263,33 @@ in serverId = mkOption { type = types.int; default = 1; - description = "Id of the MySQL server instance. This number must be unique for each instance"; + description = "Id of the MySQL server instance. This number must be unique for each instance."; }; masterHost = mkOption { type = types.str; - description = "Hostname of the MySQL master server"; + description = "Hostname of the MySQL master server."; }; slaveHost = mkOption { type = types.str; - description = "Hostname of the MySQL slave server"; + description = "Hostname of the MySQL slave server."; }; masterUser = mkOption { type = types.str; - description = "Username of the MySQL replication user"; + description = "Username of the MySQL replication user."; }; masterPassword = mkOption { type = types.str; - description = "Password of the MySQL replication user"; + description = "Password of the MySQL replication user."; }; masterPort = mkOption { type = types.int; default = 3306; - description = "Port number on which the MySQL master server runs"; + description = "Port number on which the MySQL master server runs."; }; }; }; From e3c210dfd19f60587a98c055266570d0f950edec Mon Sep 17 00:00:00 2001 From: Aaron Andersen Date: Tue, 11 Aug 2020 21:54:51 -0400 Subject: [PATCH 5/7] nixos/mysql: run ExecStartPost as an unprivileged user --- nixos/modules/services/databases/mysql.nix | 26 +++++++++++++--------- 1 file changed, 16 insertions(+), 10 deletions(-) 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; From f08049e712e661503e3bbfffbea81a0efddab573 Mon Sep 17 00:00:00 2001 From: Aaron Andersen Date: Tue, 11 Aug 2020 22:04:16 -0400 Subject: [PATCH 6/7] nixos/mysql: move ExecStartPost into postStart --- nixos/modules/services/databases/mysql.nix | 208 ++++++++++----------- 1 file changed, 102 insertions(+), 106 deletions(-) diff --git a/nixos/modules/services/databases/mysql.nix b/nixos/modules/services/databases/mysql.nix index c1a6b895bdd1..7d0a3f9afc48 100644 --- a/nixos/modules/services/databases/mysql.nix +++ b/nixos/modules/services/databases/mysql.nix @@ -375,118 +375,114 @@ in fi ''; + postStart = let + # The super user account to use on *first* run of MySQL server + superUser = if isMariaDB then cfg.user else "root"; + in '' + ${optionalString (!hasNotify) '' + # Wait until the MySQL server is available for use + count=0 + while [ ! -e /run/mysqld/mysqld.sock ] + do + if [ $count -eq 30 ] + then + echo "Tried 30 times, giving up..." + exit 1 + fi + + echo "MySQL daemon not yet started. Waiting for 1 second..." + count=$((count++)) + sleep 1 + done + ''} + + 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 + echo "Creating initial database: ${database.name}" + ( echo 'create database `${database.name}`;' + + ${optionalString (database.schema != null) '' + echo 'use `${database.name}`;' + + # TODO: this silently falls through if database.schema does not exist, + # we should catch this somehow and exit, but can't do it here because we're in a subshell. + if [ -f "${database.schema}" ] + then + cat ${database.schema} + elif [ -d "${database.schema}" ] + then + cat ${database.schema}/mysql-databases/*.sql + fi + ''} + ) | ${cfg.package}/bin/mysql -u ${superUser} -N + fi + '') cfg.initialDatabases} + + ${optionalString (cfg.replication.role == "master") + '' + # Set up the replication master + + ( echo "use mysql;" + 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 ${superUser} -N + ''} + + ${optionalString (cfg.replication.role == "slave") + '' + # Set up the replication slave + + ( 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 ${superUser} -N + ''} + + ${optionalString (cfg.initialScript != null) + '' + # 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 ${superUser} -N + ''} + + rm ${cfg.dataDir}/mysql_init + fi + + ${optionalString (cfg.ensureDatabases != []) '' + ( + ${concatMapStrings (database: '' + echo "CREATE DATABASE IF NOT EXISTS \`${database}\`;" + '') cfg.ensureDatabases} + ) | ${cfg.package}/bin/mysql -N + ''} + + ${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: '' + echo "GRANT ${permission} ON ${database} TO '${user.name}'@'localhost';" + '') user.ensurePermissions)} + ) | ${cfg.package}/bin/mysql -N + '') cfg.ensureUsers} + ''; + serviceConfig = { Type = if hasNotify then "notify" else "simple"; Restart = "on-abort"; RestartSec = "5s"; # The last two environment variables are used for starting Galera clusters 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 - - ${optionalString (!hasNotify) '' - # Wait until the MySQL server is available for use - count=0 - while [ ! -e /run/mysqld/mysqld.sock ] - do - if [ $count -eq 30 ] - then - echo "Tried 30 times, giving up..." - exit 1 - fi - - echo "MySQL daemon not yet started. Waiting for 1 second..." - count=$((count++)) - sleep 1 - done - ''} - - 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 - echo "Creating initial database: ${database.name}" - ( echo 'create database `${database.name}`;' - - ${optionalString (database.schema != null) '' - echo 'use `${database.name}`;' - - # TODO: this silently falls through if database.schema does not exist, - # we should catch this somehow and exit, but can't do it here because we're in a subshell. - if [ -f "${database.schema}" ] - then - cat ${database.schema} - elif [ -d "${database.schema}" ] - then - cat ${database.schema}/mysql-databases/*.sql - fi - ''} - ) | ${cfg.package}/bin/mysql -u ${superUser} -N - fi - '') cfg.initialDatabases} - - ${optionalString (cfg.replication.role == "master") - '' - # Set up the replication master - - ( echo "use mysql;" - 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 ${superUser} -N - ''} - - ${optionalString (cfg.replication.role == "slave") - '' - # Set up the replication slave - - ( 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 ${superUser} -N - ''} - - ${optionalString (cfg.initialScript != null) - '' - # 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 ${superUser} -N - ''} - - rm ${cfg.dataDir}/mysql_init - fi - - ${optionalString (cfg.ensureDatabases != []) '' - ( - ${concatMapStrings (database: '' - echo "CREATE DATABASE IF NOT EXISTS \`${database}\`;" - '') cfg.ensureDatabases} - ) | ${cfg.package}/bin/mysql -N - ''} - - ${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: '' - echo "GRANT ${permission} ON ${database} TO '${user.name}'@'localhost';" - '') user.ensurePermissions)} - ) | ${cfg.package}/bin/mysql -N - '') cfg.ensureUsers} - ''; - in - "${setupScript}"; # User and group User = cfg.user; Group = cfg.group; From 806253800ba72152e9f12c9f2fd1e97a3ebecbe8 Mon Sep 17 00:00:00 2001 From: Aaron Andersen Date: Wed, 12 Aug 2020 07:50:24 -0400 Subject: [PATCH 7/7] nixos/mysql: update release notes --- nixos/doc/manual/release-notes/rl-2009.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/nixos/doc/manual/release-notes/rl-2009.xml b/nixos/doc/manual/release-notes/rl-2009.xml index 35ffadc17c5b..3a0c1865a624 100644 --- a/nixos/doc/manual/release-notes/rl-2009.xml +++ b/nixos/doc/manual/release-notes/rl-2009.xml @@ -109,6 +109,17 @@ systemd.services.mysql.serviceConfig.ProtectHome = lib.mkForce "read-only"; systemd.services.mysql.serviceConfig.ReadWritePaths = [ "/var/data" ]; + + The MySQL service no longer runs its systemd service startup script as root anymore. A dedicated non root + super user account is required for operation. This means users with an existing MySQL or MariaDB database server are required to run the following SQL statements + as a super admin user before upgrading: + +CREATE USER IF NOT EXISTS 'mysql'@'localhost' identified with unix_socket; +GRANT ALL PRIVILEGES ON *.* TO 'mysql'@'localhost' WITH GRANT OPTION; + + If you use MySQL instead of MariaDB please replace unix_socket with auth_socket. If you have changed the value of + from the default of mysql to a different user please change 'mysql'@'localhost' to the corresponding user instead. +