mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-07-14 06:00:33 +03:00
nixos/keycloak: keycloak.database* -> keycloak.database.*
Move all database options to their own group / attribute. This makes the configuration clearer and brings it in line with most other modern modules.
This commit is contained in:
parent
83e406e97a
commit
dbf91bc2f1
3 changed files with 121 additions and 116 deletions
|
@ -98,98 +98,100 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
databaseType = lib.mkOption {
|
database = {
|
||||||
type = lib.types.enum [ "mysql" "postgresql" ];
|
type = lib.mkOption {
|
||||||
default = "postgresql";
|
type = lib.types.enum [ "mysql" "postgresql" ];
|
||||||
example = "mysql";
|
default = "postgresql";
|
||||||
description = ''
|
example = "mysql";
|
||||||
The type of database Keycloak should connect to.
|
description = ''
|
||||||
'';
|
The type of database Keycloak should connect to.
|
||||||
};
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
databaseHost = lib.mkOption {
|
host = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
default = "localhost";
|
default = "localhost";
|
||||||
description = ''
|
description = ''
|
||||||
Hostname of the database to connect to.
|
Hostname of the database to connect to.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
databasePort =
|
port =
|
||||||
let
|
let
|
||||||
dbPorts = {
|
dbPorts = {
|
||||||
postgresql = 5432;
|
postgresql = 5432;
|
||||||
mysql = 3306;
|
mysql = 3306;
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
lib.mkOption {
|
lib.mkOption {
|
||||||
type = lib.types.port;
|
type = lib.types.port;
|
||||||
default = dbPorts.${cfg.databaseType};
|
default = dbPorts.${cfg.database.type};
|
||||||
description = ''
|
description = ''
|
||||||
Port of the database to connect to.
|
Port of the database to connect to.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
databaseUseSSL = lib.mkOption {
|
useSSL = lib.mkOption {
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
default = cfg.databaseHost != "localhost";
|
default = cfg.database.host != "localhost";
|
||||||
description = ''
|
description = ''
|
||||||
Whether the database connection should be secured by SSL /
|
Whether the database connection should be secured by SSL /
|
||||||
TLS.
|
TLS.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
databaseCaCert = lib.mkOption {
|
caCert = lib.mkOption {
|
||||||
type = lib.types.nullOr lib.types.path;
|
type = lib.types.nullOr lib.types.path;
|
||||||
default = null;
|
default = null;
|
||||||
description = ''
|
description = ''
|
||||||
The SSL / TLS CA certificate that verifies the identity of the
|
The SSL / TLS CA certificate that verifies the identity of the
|
||||||
database server.
|
database server.
|
||||||
|
|
||||||
Required when PostgreSQL is used and SSL is turned on.
|
Required when PostgreSQL is used and SSL is turned on.
|
||||||
|
|
||||||
For MySQL, if left at <literal>null</literal>, the default
|
For MySQL, if left at <literal>null</literal>, the default
|
||||||
Java keystore is used, which should suffice if the server
|
Java keystore is used, which should suffice if the server
|
||||||
certificate is issued by an official CA.
|
certificate is issued by an official CA.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
databaseCreateLocally = lib.mkOption {
|
createLocally = lib.mkOption {
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
default = true;
|
default = true;
|
||||||
description = ''
|
description = ''
|
||||||
Whether a database should be automatically created on the
|
Whether a database should be automatically created on the
|
||||||
local host. Set this to false if you plan on provisioning a
|
local host. Set this to false if you plan on provisioning a
|
||||||
local database yourself. This has no effect if
|
local database yourself. This has no effect if
|
||||||
services.keycloak.databaseHost is customized.
|
services.keycloak.database.host is customized.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
databaseUsername = lib.mkOption {
|
username = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
default = "keycloak";
|
default = "keycloak";
|
||||||
description = ''
|
description = ''
|
||||||
Username to use when connecting to an external or manually
|
Username to use when connecting to an external or manually
|
||||||
provisioned database; has no effect when a local database is
|
provisioned database; has no effect when a local database is
|
||||||
automatically provisioned.
|
automatically provisioned.
|
||||||
|
|
||||||
To use this with a local database, set <xref
|
To use this with a local database, set <xref
|
||||||
linkend="opt-services.keycloak.databaseCreateLocally" /> to
|
linkend="opt-services.keycloak.database.createLocally" /> to
|
||||||
<literal>false</literal> and create the database and user
|
<literal>false</literal> and create the database and user
|
||||||
manually. The database should be called
|
manually. The database should be called
|
||||||
<literal>keycloak</literal>.
|
<literal>keycloak</literal>.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
databasePasswordFile = lib.mkOption {
|
passwordFile = lib.mkOption {
|
||||||
type = lib.types.path;
|
type = lib.types.path;
|
||||||
example = "/run/keys/db_password";
|
example = "/run/keys/db_password";
|
||||||
description = ''
|
description = ''
|
||||||
File containing the database password.
|
File containing the database password.
|
||||||
|
|
||||||
This should be a string, not a Nix path, since Nix paths are
|
This should be a string, not a Nix path, since Nix paths are
|
||||||
copied into the world-readable Nix store.
|
copied into the world-readable Nix store.
|
||||||
'';
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
package = lib.mkOption {
|
package = lib.mkOption {
|
||||||
|
@ -262,12 +264,12 @@ in
|
||||||
config =
|
config =
|
||||||
let
|
let
|
||||||
# We only want to create a database if we're actually going to connect to it.
|
# We only want to create a database if we're actually going to connect to it.
|
||||||
databaseActuallyCreateLocally = cfg.databaseCreateLocally && cfg.databaseHost == "localhost";
|
databaseActuallyCreateLocally = cfg.database.createLocally && cfg.database.host == "localhost";
|
||||||
createLocalPostgreSQL = databaseActuallyCreateLocally && cfg.databaseType == "postgresql";
|
createLocalPostgreSQL = databaseActuallyCreateLocally && cfg.database.type == "postgresql";
|
||||||
createLocalMySQL = databaseActuallyCreateLocally && cfg.databaseType == "mysql";
|
createLocalMySQL = databaseActuallyCreateLocally && cfg.database.type == "mysql";
|
||||||
|
|
||||||
mySqlCaKeystore = pkgs.runCommandNoCC "mysql-ca-keystore" {} ''
|
mySqlCaKeystore = pkgs.runCommandNoCC "mysql-ca-keystore" {} ''
|
||||||
${pkgs.jre}/bin/keytool -importcert -trustcacerts -alias MySQLCACert -file ${cfg.databaseCaCert} -keystore $out -storepass notsosecretpassword -noprompt
|
${pkgs.jre}/bin/keytool -importcert -trustcacerts -alias MySQLCACert -file ${cfg.database.caCert} -keystore $out -storepass notsosecretpassword -noprompt
|
||||||
'';
|
'';
|
||||||
|
|
||||||
keycloakConfig' = builtins.foldl' lib.recursiveUpdate {
|
keycloakConfig' = builtins.foldl' lib.recursiveUpdate {
|
||||||
|
@ -283,11 +285,11 @@ in
|
||||||
};
|
};
|
||||||
"subsystem=datasources"."data-source=KeycloakDS" = {
|
"subsystem=datasources"."data-source=KeycloakDS" = {
|
||||||
max-pool-size = "20";
|
max-pool-size = "20";
|
||||||
user-name = if databaseActuallyCreateLocally then "keycloak" else cfg.databaseUsername;
|
user-name = if databaseActuallyCreateLocally then "keycloak" else cfg.database.username;
|
||||||
password = "@db-password@";
|
password = "@db-password@";
|
||||||
};
|
};
|
||||||
} [
|
} [
|
||||||
(lib.optionalAttrs (cfg.databaseType == "postgresql") {
|
(lib.optionalAttrs (cfg.database.type == "postgresql") {
|
||||||
"subsystem=datasources" = {
|
"subsystem=datasources" = {
|
||||||
"jdbc-driver=postgresql" = {
|
"jdbc-driver=postgresql" = {
|
||||||
driver-module-name = "org.postgresql";
|
driver-module-name = "org.postgresql";
|
||||||
|
@ -295,16 +297,16 @@ in
|
||||||
driver-xa-datasource-class-name = "org.postgresql.xa.PGXADataSource";
|
driver-xa-datasource-class-name = "org.postgresql.xa.PGXADataSource";
|
||||||
};
|
};
|
||||||
"data-source=KeycloakDS" = {
|
"data-source=KeycloakDS" = {
|
||||||
connection-url = "jdbc:postgresql://${cfg.databaseHost}:${builtins.toString cfg.databasePort}/keycloak";
|
connection-url = "jdbc:postgresql://${cfg.database.host}:${builtins.toString cfg.database.port}/keycloak";
|
||||||
driver-name = "postgresql";
|
driver-name = "postgresql";
|
||||||
"connection-properties=ssl".value = lib.boolToString cfg.databaseUseSSL;
|
"connection-properties=ssl".value = lib.boolToString cfg.database.useSSL;
|
||||||
} // (lib.optionalAttrs (cfg.databaseCaCert != null) {
|
} // (lib.optionalAttrs (cfg.database.caCert != null) {
|
||||||
"connection-properties=sslrootcert".value = cfg.databaseCaCert;
|
"connection-properties=sslrootcert".value = cfg.database.caCert;
|
||||||
"connection-properties=sslmode".value = "verify-ca";
|
"connection-properties=sslmode".value = "verify-ca";
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
(lib.optionalAttrs (cfg.databaseType == "mysql") {
|
(lib.optionalAttrs (cfg.database.type == "mysql") {
|
||||||
"subsystem=datasources" = {
|
"subsystem=datasources" = {
|
||||||
"jdbc-driver=mysql" = {
|
"jdbc-driver=mysql" = {
|
||||||
driver-module-name = "com.mysql";
|
driver-module-name = "com.mysql";
|
||||||
|
@ -312,16 +314,16 @@ in
|
||||||
driver-class-name = "com.mysql.jdbc.Driver";
|
driver-class-name = "com.mysql.jdbc.Driver";
|
||||||
};
|
};
|
||||||
"data-source=KeycloakDS" = {
|
"data-source=KeycloakDS" = {
|
||||||
connection-url = "jdbc:mysql://${cfg.databaseHost}:${builtins.toString cfg.databasePort}/keycloak";
|
connection-url = "jdbc:mysql://${cfg.database.host}:${builtins.toString cfg.database.port}/keycloak";
|
||||||
driver-name = "mysql";
|
driver-name = "mysql";
|
||||||
"connection-properties=useSSL".value = lib.boolToString cfg.databaseUseSSL;
|
"connection-properties=useSSL".value = lib.boolToString cfg.database.useSSL;
|
||||||
"connection-properties=requireSSL".value = lib.boolToString cfg.databaseUseSSL;
|
"connection-properties=requireSSL".value = lib.boolToString cfg.database.useSSL;
|
||||||
"connection-properties=verifyServerCertificate".value = lib.boolToString cfg.databaseUseSSL;
|
"connection-properties=verifyServerCertificate".value = lib.boolToString cfg.database.useSSL;
|
||||||
"connection-properties=characterEncoding".value = "UTF-8";
|
"connection-properties=characterEncoding".value = "UTF-8";
|
||||||
valid-connection-checker-class-name = "org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker";
|
valid-connection-checker-class-name = "org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker";
|
||||||
validate-on-match = true;
|
validate-on-match = true;
|
||||||
exception-sorter-class-name = "org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLExceptionSorter";
|
exception-sorter-class-name = "org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLExceptionSorter";
|
||||||
} // (lib.optionalAttrs (cfg.databaseCaCert != null) {
|
} // (lib.optionalAttrs (cfg.database.caCert != null) {
|
||||||
"connection-properties=trustCertificateKeyStoreUrl".value = "file:${mySqlCaKeystore}";
|
"connection-properties=trustCertificateKeyStoreUrl".value = "file:${mySqlCaKeystore}";
|
||||||
"connection-properties=trustCertificateKeyStorePassword".value = "notsosecretpassword";
|
"connection-properties=trustCertificateKeyStorePassword".value = "notsosecretpassword";
|
||||||
});
|
});
|
||||||
|
@ -573,8 +575,8 @@ in
|
||||||
|
|
||||||
assertions = [
|
assertions = [
|
||||||
{
|
{
|
||||||
assertion = (cfg.databaseUseSSL && cfg.databaseType == "postgresql") -> (cfg.databaseCaCert != null);
|
assertion = (cfg.database.useSSL && cfg.database.type == "postgresql") -> (cfg.database.caCert != null);
|
||||||
message = "A CA certificate must be specified (in 'services.keycloak.databaseCaCert') when PostgreSQL is used with SSL";
|
message = "A CA certificate must be specified (in 'services.keycloak.database.caCert') when PostgreSQL is used with SSL";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -598,7 +600,7 @@ in
|
||||||
create_role="$(mktemp)"
|
create_role="$(mktemp)"
|
||||||
trap 'rm -f "$create_role"' ERR EXIT
|
trap 'rm -f "$create_role"' ERR EXIT
|
||||||
|
|
||||||
echo "CREATE ROLE keycloak WITH LOGIN PASSWORD '$(<'${cfg.databasePasswordFile}')' CREATEDB" > "$create_role"
|
echo "CREATE ROLE keycloak WITH LOGIN PASSWORD '$(<'${cfg.database.passwordFile}')' CREATEDB" > "$create_role"
|
||||||
psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='keycloak'" | grep -q 1 || psql -tA --file="$create_role"
|
psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='keycloak'" | grep -q 1 || psql -tA --file="$create_role"
|
||||||
psql -tAc "SELECT 1 FROM pg_database WHERE datname = 'keycloak'" | grep -q 1 || psql -tAc 'CREATE DATABASE "keycloak" OWNER "keycloak"'
|
psql -tAc "SELECT 1 FROM pg_database WHERE datname = 'keycloak'" | grep -q 1 || psql -tAc 'CREATE DATABASE "keycloak" OWNER "keycloak"'
|
||||||
'';
|
'';
|
||||||
|
@ -619,7 +621,7 @@ in
|
||||||
set -o errexit -o pipefail -o nounset -o errtrace
|
set -o errexit -o pipefail -o nounset -o errtrace
|
||||||
shopt -s inherit_errexit
|
shopt -s inherit_errexit
|
||||||
|
|
||||||
db_password="$(<'${cfg.databasePasswordFile}')"
|
db_password="$(<'${cfg.database.passwordFile}')"
|
||||||
( echo "CREATE USER IF NOT EXISTS 'keycloak'@'localhost' IDENTIFIED BY '$db_password';"
|
( echo "CREATE USER IF NOT EXISTS 'keycloak'@'localhost' IDENTIFIED BY '$db_password';"
|
||||||
echo "CREATE DATABASE keycloak CHARACTER SET utf8 COLLATE utf8_unicode_ci;"
|
echo "CREATE DATABASE keycloak CHARACTER SET utf8 COLLATE utf8_unicode_ci;"
|
||||||
echo "GRANT ALL PRIVILEGES ON keycloak.* TO 'keycloak'@'localhost';"
|
echo "GRANT ALL PRIVILEGES ON keycloak.* TO 'keycloak'@'localhost';"
|
||||||
|
@ -659,7 +661,7 @@ in
|
||||||
|
|
||||||
umask u=rwx,g=,o=
|
umask u=rwx,g=,o=
|
||||||
|
|
||||||
install -T -m 0400 -o keycloak -g keycloak '${cfg.databasePasswordFile}' /run/keycloak/secrets/db_password
|
install -T -m 0400 -o keycloak -g keycloak '${cfg.database.passwordFile}' /run/keycloak/secrets/db_password
|
||||||
'' + lib.optionalString (cfg.certificatePrivateKeyBundle != null) ''
|
'' + lib.optionalString (cfg.certificatePrivateKeyBundle != null) ''
|
||||||
install -T -m 0400 -o keycloak -g keycloak '${cfg.certificatePrivateKeyBundle}' /run/keycloak/secrets/ssl_cert_pk_bundle
|
install -T -m 0400 -o keycloak -g keycloak '${cfg.certificatePrivateKeyBundle}' /run/keycloak/secrets/ssl_cert_pk_bundle
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -41,31 +41,31 @@
|
||||||
<productname>PostgreSQL</productname> or
|
<productname>PostgreSQL</productname> or
|
||||||
<productname>MySQL</productname>. Which one is used can be
|
<productname>MySQL</productname>. Which one is used can be
|
||||||
configured in <xref
|
configured in <xref
|
||||||
linkend="opt-services.keycloak.databaseType" />. The selected
|
linkend="opt-services.keycloak.database.type" />. The selected
|
||||||
database will automatically be enabled and a database and role
|
database will automatically be enabled and a database and role
|
||||||
created unless <xref
|
created unless <xref
|
||||||
linkend="opt-services.keycloak.databaseHost" /> is changed from
|
linkend="opt-services.keycloak.database.host" /> is changed from
|
||||||
its default of <literal>localhost</literal> or <xref
|
its default of <literal>localhost</literal> or <xref
|
||||||
linkend="opt-services.keycloak.databaseCreateLocally" /> is set
|
linkend="opt-services.keycloak.database.createLocally" /> is set
|
||||||
to <literal>false</literal>.
|
to <literal>false</literal>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
External database access can also be configured by setting
|
External database access can also be configured by setting
|
||||||
<xref linkend="opt-services.keycloak.databaseHost" />, <xref
|
<xref linkend="opt-services.keycloak.database.host" />, <xref
|
||||||
linkend="opt-services.keycloak.databaseUsername" />, <xref
|
linkend="opt-services.keycloak.database.username" />, <xref
|
||||||
linkend="opt-services.keycloak.databaseUseSSL" /> and <xref
|
linkend="opt-services.keycloak.database.useSSL" /> and <xref
|
||||||
linkend="opt-services.keycloak.databaseCaCert" /> as
|
linkend="opt-services.keycloak.database.caCert" /> as
|
||||||
appropriate. Note that you need to manually create a database
|
appropriate. Note that you need to manually create a database
|
||||||
called <literal>keycloak</literal> and allow the configured
|
called <literal>keycloak</literal> and allow the configured
|
||||||
database user full access to it.
|
database user full access to it.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<xref linkend="opt-services.keycloak.databasePasswordFile" />
|
<xref linkend="opt-services.keycloak.database.passwordFile" />
|
||||||
must be set to the path to a file containing the password used
|
must be set to the path to a file containing the password used
|
||||||
to log in to the database. If <xref linkend="opt-services.keycloak.databaseHost" />
|
to log in to the database. If <xref linkend="opt-services.keycloak.database.host" />
|
||||||
and <xref linkend="opt-services.keycloak.databaseCreateLocally" />
|
and <xref linkend="opt-services.keycloak.database.createLocally" />
|
||||||
are kept at their defaults, the database role
|
are kept at their defaults, the database role
|
||||||
<literal>keycloak</literal> with that password is provisioned
|
<literal>keycloak</literal> with that password is provisioned
|
||||||
on the local database instance.
|
on the local database instance.
|
||||||
|
@ -196,7 +196,7 @@ services.keycloak = {
|
||||||
<link linkend="opt-services.keycloak.frontendUrl">frontendUrl</link> = "https://keycloak.example.com/auth";
|
<link linkend="opt-services.keycloak.frontendUrl">frontendUrl</link> = "https://keycloak.example.com/auth";
|
||||||
<link linkend="opt-services.keycloak.forceBackendUrlToFrontendUrl">forceBackendUrlToFrontendUrl</link> = true;
|
<link linkend="opt-services.keycloak.forceBackendUrlToFrontendUrl">forceBackendUrlToFrontendUrl</link> = true;
|
||||||
<link linkend="opt-services.keycloak.certificatePrivateKeyBundle">certificatePrivateKeyBundle</link> = "/run/keys/ssl_cert";
|
<link linkend="opt-services.keycloak.certificatePrivateKeyBundle">certificatePrivateKeyBundle</link> = "/run/keys/ssl_cert";
|
||||||
<link linkend="opt-services.keycloak.databasePasswordFile">databasePasswordFile</link> = "/run/keys/db_password";
|
<link linkend="opt-services.keycloak.database.passwordFile">database.passwordFile</link> = "/run/keys/db_password";
|
||||||
};
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
|
|
@ -19,9 +19,12 @@ let
|
||||||
virtualisation.memorySize = 1024;
|
virtualisation.memorySize = 1024;
|
||||||
services.keycloak = {
|
services.keycloak = {
|
||||||
enable = true;
|
enable = true;
|
||||||
inherit frontendUrl databaseType initialAdminPassword;
|
inherit frontendUrl initialAdminPassword;
|
||||||
databaseUsername = "bogus";
|
database = {
|
||||||
databasePasswordFile = pkgs.writeText "dbPassword" "wzf6vOCbPp6cqTH";
|
type = databaseType;
|
||||||
|
username = "bogus";
|
||||||
|
passwordFile = pkgs.writeText "dbPassword" "wzf6vOCbPp6cqTH";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
xmlstarlet
|
xmlstarlet
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue