mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-11 04:05:40 +03:00
nixos/services.mysql: format with nixfmt-rfc-style
This commit is contained in:
parent
48134064dd
commit
0256f1180c
1 changed files with 185 additions and 138 deletions
|
@ -1,4 +1,9 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
|
||||
cfg = config.services.mysql;
|
||||
|
@ -8,8 +13,7 @@ let
|
|||
# Oracle MySQL has supported "notify" service type since 8.0
|
||||
hasNotify = isMariaDB || (isOracle && lib.versionAtLeast cfg.package.version "8.0");
|
||||
|
||||
mysqldOptions =
|
||||
"--user=${cfg.user} --datadir=${cfg.dataDir} --basedir=${cfg.package}";
|
||||
mysqldOptions = "--user=${cfg.user} --datadir=${cfg.dataDir} --basedir=${cfg.package}";
|
||||
|
||||
format = pkgs.formats.ini { listsAsDuplicateKeys = true; };
|
||||
configFile = format.generate "my.cnf" cfg.settings;
|
||||
|
@ -18,11 +22,31 @@ in
|
|||
|
||||
{
|
||||
imports = [
|
||||
(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.")
|
||||
(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
|
||||
|
@ -106,7 +130,7 @@ in
|
|||
|
||||
settings = lib.mkOption {
|
||||
type = format.type;
|
||||
default = {};
|
||||
default = { };
|
||||
description = ''
|
||||
MySQL configuration. Refer to
|
||||
<https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html>,
|
||||
|
@ -137,25 +161,27 @@ in
|
|||
};
|
||||
|
||||
initialDatabases = lib.mkOption {
|
||||
type = lib.types.listOf (lib.types.submodule {
|
||||
options = {
|
||||
name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
The name of the database to create.
|
||||
'';
|
||||
type = lib.types.listOf (
|
||||
lib.types.submodule {
|
||||
options = {
|
||||
name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
The name of the database to create.
|
||||
'';
|
||||
};
|
||||
schema = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
description = ''
|
||||
The initial schema of the database; if null (the default),
|
||||
an empty database is created.
|
||||
'';
|
||||
};
|
||||
};
|
||||
schema = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
description = ''
|
||||
The initial schema of the database; if null (the default),
|
||||
an empty database is created.
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
default = [];
|
||||
}
|
||||
);
|
||||
default = [ ];
|
||||
description = ''
|
||||
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.
|
||||
|
@ -176,7 +202,7 @@ in
|
|||
|
||||
ensureDatabases = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
description = ''
|
||||
Ensures that the specified databases exist.
|
||||
This option will never delete existing databases, especially not when the value of this
|
||||
|
@ -190,39 +216,41 @@ in
|
|||
};
|
||||
|
||||
ensureUsers = lib.mkOption {
|
||||
type = lib.types.listOf (lib.types.submodule {
|
||||
options = {
|
||||
name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Name of the user to ensure.
|
||||
'';
|
||||
};
|
||||
ensurePermissions = lib.mkOption {
|
||||
type = lib.types.attrsOf lib.types.str;
|
||||
default = {};
|
||||
description = ''
|
||||
Permissions to ensure for the user, specified as attribute set.
|
||||
The attribute names specify the database and tables to grant the permissions for,
|
||||
separated by a dot. You may use wildcards here.
|
||||
The attribute values specfiy the permissions to grant.
|
||||
You may specify one or multiple comma-separated SQL privileges here.
|
||||
type = lib.types.listOf (
|
||||
lib.types.submodule {
|
||||
options = {
|
||||
name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Name of the user to ensure.
|
||||
'';
|
||||
};
|
||||
ensurePermissions = lib.mkOption {
|
||||
type = lib.types.attrsOf lib.types.str;
|
||||
default = { };
|
||||
description = ''
|
||||
Permissions to ensure for the user, specified as attribute set.
|
||||
The attribute names specify the database and tables to grant the permissions for,
|
||||
separated by a dot. You may use wildcards here.
|
||||
The attribute values specfiy the permissions to grant.
|
||||
You may specify one or multiple comma-separated SQL privileges here.
|
||||
|
||||
For more information on how to specify the target
|
||||
and on which privileges exist, see the
|
||||
[GRANT syntax](https://mariadb.com/kb/en/library/grant/).
|
||||
The attributes are used as `GRANT ''${attrName} ON ''${attrValue}`.
|
||||
'';
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
"database.*" = "ALL PRIVILEGES";
|
||||
"*.*" = "SELECT, LOCK TABLES";
|
||||
}
|
||||
'';
|
||||
For more information on how to specify the target
|
||||
and on which privileges exist, see the
|
||||
[GRANT syntax](https://mariadb.com/kb/en/library/grant/).
|
||||
The attributes are used as `GRANT ''${attrName} ON ''${attrValue}`.
|
||||
'';
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
"database.*" = "ALL PRIVILEGES";
|
||||
"*.*" = "SELECT, LOCK TABLES";
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
});
|
||||
default = [];
|
||||
}
|
||||
);
|
||||
default = [ ];
|
||||
description = ''
|
||||
Ensures that the specified users exist and have at least the ensured permissions.
|
||||
The MySQL users will be identified using Unix socket authentication. This authenticates the Unix user with the
|
||||
|
@ -251,7 +279,11 @@ in
|
|||
|
||||
replication = {
|
||||
role = lib.mkOption {
|
||||
type = lib.types.enum [ "master" "slave" "none" ];
|
||||
type = lib.types.enum [
|
||||
"master"
|
||||
"slave"
|
||||
"none"
|
||||
];
|
||||
default = "none";
|
||||
description = "Role of the MySQL server instance.";
|
||||
};
|
||||
|
@ -292,14 +324,13 @@ in
|
|||
|
||||
};
|
||||
|
||||
|
||||
###### implementation
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
services.mysql.dataDir =
|
||||
lib.mkDefault (if lib.versionAtLeast config.system.stateVersion "17.09" then "/var/lib/mysql"
|
||||
else "/var/mysql");
|
||||
services.mysql.dataDir = lib.mkDefault (
|
||||
if lib.versionAtLeast config.system.stateVersion "17.09" then "/var/lib/mysql" else "/var/mysql"
|
||||
);
|
||||
|
||||
services.mysql.settings.mysqld = lib.mkMerge [
|
||||
{
|
||||
|
@ -311,7 +342,11 @@ in
|
|||
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" ];
|
||||
binlog-ignore-db = [
|
||||
"information_schema"
|
||||
"performance_schema"
|
||||
"mysql"
|
||||
];
|
||||
})
|
||||
(lib.mkIf (!isMariaDB) {
|
||||
plugin-load-add = [ "auth_socket.so" ];
|
||||
|
@ -355,17 +390,21 @@ in
|
|||
pkgs.nettools
|
||||
];
|
||||
|
||||
preStart = if isMariaDB then ''
|
||||
if ! test -e ${cfg.dataDir}/mysql; then
|
||||
${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
|
||||
${cfg.package}/bin/mysqld --defaults-file=/etc/my.cnf ${mysqldOptions} --initialize-insecure
|
||||
touch ${cfg.dataDir}/mysql_init
|
||||
fi
|
||||
'';
|
||||
preStart =
|
||||
if isMariaDB then
|
||||
''
|
||||
if ! test -e ${cfg.dataDir}/mysql; then
|
||||
${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
|
||||
${cfg.package}/bin/mysqld --defaults-file=/etc/my.cnf ${mysqldOptions} --initialize-insecure
|
||||
touch ${cfg.dataDir}/mysql_init
|
||||
fi
|
||||
'';
|
||||
|
||||
script = ''
|
||||
# https://mariadb.com/kb/en/getting-started-with-mariadb-galera-cluster/#systemd-and-galera-recovery
|
||||
|
@ -379,52 +418,55 @@ in
|
|||
exec ${cfg.package}/bin/mysqld --defaults-file=/etc/my.cnf ${mysqldOptions} $_WSREP_NEW_CLUSTER $_WSREP_START_POSITION
|
||||
'';
|
||||
|
||||
postStart = let
|
||||
# The super user account to use on *first* run of MySQL server
|
||||
superUser = if isMariaDB then cfg.user else "root";
|
||||
in ''
|
||||
${lib.optionalString (!hasNotify) ''
|
||||
# Wait until the MySQL server is available for use
|
||||
while [ ! -e /run/mysqld/mysqld.sock ]
|
||||
do
|
||||
echo "MySQL daemon not yet started. Waiting for 1 second..."
|
||||
sleep 1
|
||||
done
|
||||
''}
|
||||
postStart =
|
||||
let
|
||||
# The super user account to use on *first* run of MySQL server
|
||||
superUser = if isMariaDB then cfg.user else "root";
|
||||
in
|
||||
''
|
||||
${lib.optionalString (!hasNotify) ''
|
||||
# Wait until the MySQL server is available for use
|
||||
while [ ! -e /run/mysqld/mysqld.sock ]
|
||||
do
|
||||
echo "MySQL daemon not yet started. Waiting for 1 second..."
|
||||
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
|
||||
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
|
||||
|
||||
${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}`;'
|
||||
${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}`;'
|
||||
|
||||
${lib.optionalString (database.schema != null) ''
|
||||
echo 'use `${database.name}`;'
|
||||
${lib.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}
|
||||
# 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}
|
||||
|
||||
${lib.optionalString (cfg.replication.role == "master")
|
||||
''
|
||||
${lib.optionalString (cfg.replication.role == "master") ''
|
||||
# Set up the replication master
|
||||
|
||||
( echo "use mysql;"
|
||||
|
@ -434,8 +476,7 @@ in
|
|||
) | ${cfg.package}/bin/mysql -u ${superUser} -N
|
||||
''}
|
||||
|
||||
${lib.optionalString (cfg.replication.role == "slave")
|
||||
''
|
||||
${lib.optionalString (cfg.replication.role == "slave") ''
|
||||
# Set up the replication slave
|
||||
|
||||
( echo "stop slave;"
|
||||
|
@ -444,34 +485,36 @@ in
|
|||
) | ${cfg.package}/bin/mysql -u ${superUser} -N
|
||||
''}
|
||||
|
||||
${lib.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,
|
||||
# as it might contain credentials
|
||||
cat ${toString cfg.initialScript} | ${cfg.package}/bin/mysql -u ${superUser} -N
|
||||
''}
|
||||
|
||||
rm ${cfg.dataDir}/mysql_init
|
||||
fi
|
||||
rm ${cfg.dataDir}/mysql_init
|
||||
fi
|
||||
|
||||
${lib.optionalString (cfg.ensureDatabases != []) ''
|
||||
(
|
||||
${lib.concatMapStrings (database: ''
|
||||
echo "CREATE DATABASE IF NOT EXISTS \`${database}\`;"
|
||||
'') cfg.ensureDatabases}
|
||||
) | ${cfg.package}/bin/mysql -N
|
||||
''}
|
||||
${lib.optionalString (cfg.ensureDatabases != [ ]) ''
|
||||
(
|
||||
${lib.concatMapStrings (database: ''
|
||||
echo "CREATE DATABASE IF NOT EXISTS \`${database}\`;"
|
||||
'') cfg.ensureDatabases}
|
||||
) | ${cfg.package}/bin/mysql -N
|
||||
''}
|
||||
|
||||
${lib.concatMapStrings (user:
|
||||
''
|
||||
( echo "CREATE USER IF NOT EXISTS '${user.name}'@'localhost' IDENTIFIED WITH ${if isMariaDB then "unix_socket" else "auth_socket"};"
|
||||
${lib.concatStringsSep "\n" (lib.mapAttrsToList (database: permission: ''
|
||||
echo "GRANT ${permission} ON ${database} TO '${user.name}'@'localhost';"
|
||||
'') user.ensurePermissions)}
|
||||
${lib.concatMapStrings (user: ''
|
||||
( echo "CREATE USER IF NOT EXISTS '${user.name}'@'localhost' IDENTIFIED WITH ${
|
||||
if isMariaDB then "unix_socket" else "auth_socket"
|
||||
};"
|
||||
${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 = lib.mkMerge [
|
||||
{
|
||||
|
@ -500,7 +543,11 @@ in
|
|||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
|
||||
RestrictAddressFamilies = [
|
||||
"AF_UNIX"
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
];
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
RestrictRealtime = true;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue