nixos/mysql: run ExecStartPost as root (again) to preserve com… (#63862)
nixos/mysql: run ExecStartPost as root (again) to preserve compatibility with secured installs
This commit is contained in:
commit
51bcf119f3
@ -317,104 +317,105 @@ in
|
|||||||
RuntimeDirectoryMode = "0755";
|
RuntimeDirectoryMode = "0755";
|
||||||
# The last two environment variables are used for starting Galera clusters
|
# 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 = "${mysql}/bin/mysqld --defaults-file=/etc/my.cnf ${mysqldOptions} $_WSREP_NEW_CLUSTER $_WSREP_START_POSITION";
|
||||||
};
|
ExecStartPost =
|
||||||
|
let
|
||||||
|
setupScript = pkgs.writeShellScript "mysql-setup" ''
|
||||||
|
${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
|
||||||
|
|
||||||
postStart =
|
echo "MySQL daemon not yet started. Waiting for 1 second..."
|
||||||
let
|
count=$((count++))
|
||||||
cmdWatchForMysqlSocket = ''
|
sleep 1
|
||||||
# Wait until the MySQL server is available for use
|
done
|
||||||
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..."
|
if [ -f /tmp/mysql_init ]
|
||||||
count=$((count++))
|
then
|
||||||
sleep 1
|
${concatMapStrings (database: ''
|
||||||
done
|
# Create initial databases
|
||||||
'';
|
if ! test -e "${cfg.dataDir}/${database.name}"; then
|
||||||
cmdInitialDatabases = concatMapStrings (database: ''
|
echo "Creating initial database: ${database.name}"
|
||||||
# Create initial databases
|
( echo 'create database `${database.name}`;'
|
||||||
if ! test -e "${cfg.dataDir}/${database.name}"; then
|
|
||||||
echo "Creating initial database: ${database.name}"
|
|
||||||
( echo 'create database `${database.name}`;'
|
|
||||||
|
|
||||||
${optionalString (database.schema != null) ''
|
${optionalString (database.schema != null) ''
|
||||||
echo 'use `${database.name}`;'
|
echo 'use `${database.name}`;'
|
||||||
|
|
||||||
# TODO: this silently falls through if database.schema does not exist,
|
# 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.
|
# we should catch this somehow and exit, but can't do it here because we're in a subshell.
|
||||||
if [ -f "${database.schema}" ]
|
if [ -f "${database.schema}" ]
|
||||||
then
|
then
|
||||||
cat ${database.schema}
|
cat ${database.schema}
|
||||||
elif [ -d "${database.schema}" ]
|
elif [ -d "${database.schema}" ]
|
||||||
then
|
then
|
||||||
cat ${database.schema}/mysql-databases/*.sql
|
cat ${database.schema}/mysql-databases/*.sql
|
||||||
fi
|
fi
|
||||||
''}
|
''}
|
||||||
|
) | ${mysql}/bin/mysql -u root -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}';"
|
||||||
|
) | ${mysql}/bin/mysql -u root -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;"
|
||||||
|
) | ${mysql}/bin/mysql -u root -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} | ${mysql}/bin/mysql -u root -N
|
||||||
|
''}
|
||||||
|
|
||||||
|
rm /tmp/mysql_init
|
||||||
|
fi
|
||||||
|
|
||||||
|
${optionalString (cfg.ensureDatabases != []) ''
|
||||||
|
(
|
||||||
|
${concatMapStrings (database: ''
|
||||||
|
echo "CREATE DATABASE IF NOT EXISTS \`${database}\`;"
|
||||||
|
'') cfg.ensureDatabases}
|
||||||
) | ${mysql}/bin/mysql -u root -N
|
) | ${mysql}/bin/mysql -u root -N
|
||||||
fi
|
''}
|
||||||
'') cfg.initialDatabases;
|
|
||||||
in
|
|
||||||
|
|
||||||
lib.optionalString (!hasNotify) cmdWatchForMysqlSocket + ''
|
${concatMapStrings (user:
|
||||||
if [ -f /tmp/mysql_init ]
|
|
||||||
then
|
|
||||||
${cmdInitialDatabases}
|
|
||||||
${optionalString (cfg.replication.role == "master")
|
|
||||||
''
|
''
|
||||||
# Set up the replication master
|
( 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 "use mysql;"
|
echo "GRANT ${permission} ON ${database} TO '${user.name}'@'localhost';"
|
||||||
echo "CREATE USER '${cfg.replication.masterUser}'@'${cfg.replication.slaveHost}' IDENTIFIED WITH mysql_native_password;"
|
'') user.ensurePermissions)}
|
||||||
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
|
) | ${mysql}/bin/mysql -u root -N
|
||||||
''}
|
'') cfg.ensureUsers}
|
||||||
|
'';
|
||||||
${optionalString (cfg.replication.role == "slave")
|
in
|
||||||
''
|
# ensureDatbases & ensureUsers depends on this script being run as root
|
||||||
# Set up the replication slave
|
# when the user has secured their mysql install
|
||||||
|
"+${setupScript}";
|
||||||
( 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
|
|
||||||
''}
|
|
||||||
|
|
||||||
${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} | ${mysql}/bin/mysql -u root -N
|
|
||||||
''}
|
|
||||||
|
|
||||||
rm /tmp/mysql_init
|
|
||||||
fi
|
|
||||||
|
|
||||||
${optionalString (cfg.ensureDatabases != []) ''
|
|
||||||
(
|
|
||||||
${concatMapStrings (database: ''
|
|
||||||
echo "CREATE DATABASE IF NOT EXISTS \`${database}\`;"
|
|
||||||
'') cfg.ensureDatabases}
|
|
||||||
) | ${mysql}/bin/mysql -u root -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)}
|
|
||||||
) | ${mysql}/bin/mysql -u root -N
|
|
||||||
'') cfg.ensureUsers}
|
|
||||||
|
|
||||||
''; # */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -28,6 +28,12 @@ import ./make-test.nix ({ pkgs, ...} : {
|
|||||||
{
|
{
|
||||||
users.users.testuser = { };
|
users.users.testuser = { };
|
||||||
services.mysql.enable = true;
|
services.mysql.enable = true;
|
||||||
|
services.mysql.initialScript = pkgs.writeText "mariadb-init.sql" ''
|
||||||
|
echo "ALTER USER root@localhost IDENTIFIED WITH unix_socket;"
|
||||||
|
echo "DELETE FROM mysql.user WHERE password = ''' AND plugin = ''';"
|
||||||
|
echo "DELETE FROM mysql.user WHERE user = ''';"
|
||||||
|
echo "FLUSH PRIVILEGES;"
|
||||||
|
'';
|
||||||
services.mysql.ensureDatabases = [ "testdb" ];
|
services.mysql.ensureDatabases = [ "testdb" ];
|
||||||
services.mysql.ensureUsers = [{
|
services.mysql.ensureUsers = [{
|
||||||
name = "testuser";
|
name = "testuser";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user