Merge pull request #121778 from talyz/keycloak-security
nixos/keycloak: Security fixes + misc
This commit is contained in:
commit
e9cca93bf9
3 changed files with 205 additions and 152 deletions
|
@ -54,6 +54,7 @@ in
|
|||
|
||||
frontendUrl = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
apply = x: if lib.hasSuffix "/" x then x else x + "/";
|
||||
example = "keycloak.example.com/auth";
|
||||
description = ''
|
||||
The public URL used as base for all frontend requests. Should
|
||||
|
@ -84,20 +85,34 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
certificatePrivateKeyBundle = lib.mkOption {
|
||||
sslCertificate = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
example = "/run/keys/ssl_cert";
|
||||
description = ''
|
||||
The path to a PEM formatted bundle of the private key and
|
||||
certificate to use for TLS connections.
|
||||
The path to a PEM formatted certificate to use for TLS/SSL
|
||||
connections.
|
||||
|
||||
This should be a string, not a Nix path, since Nix paths are
|
||||
copied into the world-readable Nix store.
|
||||
'';
|
||||
};
|
||||
|
||||
databaseType = lib.mkOption {
|
||||
sslCertificateKey = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
example = "/run/keys/ssl_key";
|
||||
description = ''
|
||||
The path to a PEM formatted private key to use for TLS/SSL
|
||||
connections.
|
||||
|
||||
This should be a string, not a Nix path, since Nix paths are
|
||||
copied into the world-readable Nix store.
|
||||
'';
|
||||
};
|
||||
|
||||
database = {
|
||||
type = lib.mkOption {
|
||||
type = lib.types.enum [ "mysql" "postgresql" ];
|
||||
default = "postgresql";
|
||||
example = "mysql";
|
||||
|
@ -106,7 +121,7 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
databaseHost = lib.mkOption {
|
||||
host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "localhost";
|
||||
description = ''
|
||||
|
@ -114,7 +129,7 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
databasePort =
|
||||
port =
|
||||
let
|
||||
dbPorts = {
|
||||
postgresql = 5432;
|
||||
|
@ -123,22 +138,22 @@ in
|
|||
in
|
||||
lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = dbPorts.${cfg.databaseType};
|
||||
default = dbPorts.${cfg.database.type};
|
||||
description = ''
|
||||
Port of the database to connect to.
|
||||
'';
|
||||
};
|
||||
|
||||
databaseUseSSL = lib.mkOption {
|
||||
useSSL = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = cfg.databaseHost != "localhost";
|
||||
default = cfg.database.host != "localhost";
|
||||
description = ''
|
||||
Whether the database connection should be secured by SSL /
|
||||
TLS.
|
||||
'';
|
||||
};
|
||||
|
||||
databaseCaCert = lib.mkOption {
|
||||
caCert = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
description = ''
|
||||
|
@ -153,18 +168,18 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
databaseCreateLocally = lib.mkOption {
|
||||
createLocally = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether a database should be automatically created on the
|
||||
local host. Set this to false if you plan on provisioning a
|
||||
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;
|
||||
default = "keycloak";
|
||||
description = ''
|
||||
|
@ -173,14 +188,14 @@ in
|
|||
automatically provisioned.
|
||||
|
||||
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
|
||||
manually. The database should be called
|
||||
<literal>keycloak</literal>.
|
||||
'';
|
||||
};
|
||||
|
||||
databasePasswordFile = lib.mkOption {
|
||||
passwordFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
example = "/run/keys/db_password";
|
||||
description = ''
|
||||
|
@ -190,6 +205,7 @@ in
|
|||
copied into the world-readable Nix store.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
package = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
|
@ -261,12 +277,12 @@ in
|
|||
config =
|
||||
let
|
||||
# We only want to create a database if we're actually going to connect to it.
|
||||
databaseActuallyCreateLocally = cfg.databaseCreateLocally && cfg.databaseHost == "localhost";
|
||||
createLocalPostgreSQL = databaseActuallyCreateLocally && cfg.databaseType == "postgresql";
|
||||
createLocalMySQL = databaseActuallyCreateLocally && cfg.databaseType == "mysql";
|
||||
databaseActuallyCreateLocally = cfg.database.createLocally && cfg.database.host == "localhost";
|
||||
createLocalPostgreSQL = databaseActuallyCreateLocally && cfg.database.type == "postgresql";
|
||||
createLocalMySQL = databaseActuallyCreateLocally && cfg.database.type == "mysql";
|
||||
|
||||
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 {
|
||||
|
@ -282,11 +298,11 @@ in
|
|||
};
|
||||
"subsystem=datasources"."data-source=KeycloakDS" = {
|
||||
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@";
|
||||
};
|
||||
} [
|
||||
(lib.optionalAttrs (cfg.databaseType == "postgresql") {
|
||||
(lib.optionalAttrs (cfg.database.type == "postgresql") {
|
||||
"subsystem=datasources" = {
|
||||
"jdbc-driver=postgresql" = {
|
||||
driver-module-name = "org.postgresql";
|
||||
|
@ -294,16 +310,16 @@ in
|
|||
driver-xa-datasource-class-name = "org.postgresql.xa.PGXADataSource";
|
||||
};
|
||||
"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";
|
||||
"connection-properties=ssl".value = lib.boolToString cfg.databaseUseSSL;
|
||||
} // (lib.optionalAttrs (cfg.databaseCaCert != null) {
|
||||
"connection-properties=sslrootcert".value = cfg.databaseCaCert;
|
||||
"connection-properties=ssl".value = lib.boolToString cfg.database.useSSL;
|
||||
} // (lib.optionalAttrs (cfg.database.caCert != null) {
|
||||
"connection-properties=sslrootcert".value = cfg.database.caCert;
|
||||
"connection-properties=sslmode".value = "verify-ca";
|
||||
});
|
||||
};
|
||||
})
|
||||
(lib.optionalAttrs (cfg.databaseType == "mysql") {
|
||||
(lib.optionalAttrs (cfg.database.type == "mysql") {
|
||||
"subsystem=datasources" = {
|
||||
"jdbc-driver=mysql" = {
|
||||
driver-module-name = "com.mysql";
|
||||
|
@ -311,22 +327,22 @@ in
|
|||
driver-class-name = "com.mysql.jdbc.Driver";
|
||||
};
|
||||
"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";
|
||||
"connection-properties=useSSL".value = lib.boolToString cfg.databaseUseSSL;
|
||||
"connection-properties=requireSSL".value = lib.boolToString cfg.databaseUseSSL;
|
||||
"connection-properties=verifyServerCertificate".value = lib.boolToString cfg.databaseUseSSL;
|
||||
"connection-properties=useSSL".value = lib.boolToString cfg.database.useSSL;
|
||||
"connection-properties=requireSSL".value = lib.boolToString cfg.database.useSSL;
|
||||
"connection-properties=verifyServerCertificate".value = lib.boolToString cfg.database.useSSL;
|
||||
"connection-properties=characterEncoding".value = "UTF-8";
|
||||
valid-connection-checker-class-name = "org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker";
|
||||
validate-on-match = true;
|
||||
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=trustCertificateKeyStorePassword".value = "notsosecretpassword";
|
||||
});
|
||||
};
|
||||
})
|
||||
(lib.optionalAttrs (cfg.certificatePrivateKeyBundle != null) {
|
||||
(lib.optionalAttrs (cfg.sslCertificate != null && cfg.sslCertificateKey != null) {
|
||||
"socket-binding-group=standard-sockets"."socket-binding=https".port = cfg.httpsPort;
|
||||
"core-service=management"."security-realm=UndertowRealm"."server-identity=ssl" = {
|
||||
keystore-path = "/run/keycloak/ssl/certificate_private_key_bundle.p12";
|
||||
|
@ -537,7 +553,9 @@ in
|
|||
|
||||
jbossCliScript = pkgs.writeText "jboss-cli-script" (mkJbossScript keycloakConfig');
|
||||
|
||||
keycloakConfig = pkgs.runCommandNoCC "keycloak-config" {} ''
|
||||
keycloakConfig = pkgs.runCommandNoCC "keycloak-config" {
|
||||
nativeBuildInputs = [ cfg.package ];
|
||||
} ''
|
||||
export JBOSS_BASE_DIR="$(pwd -P)";
|
||||
export JBOSS_MODULEPATH="${cfg.package}/modules";
|
||||
export JBOSS_LOG_DIR="$JBOSS_BASE_DIR/log";
|
||||
|
@ -547,11 +565,11 @@ in
|
|||
|
||||
mkdir -p {deployments,ssl}
|
||||
|
||||
"${cfg.package}/bin/standalone.sh"&
|
||||
standalone.sh&
|
||||
|
||||
attempt=1
|
||||
max_attempts=30
|
||||
while ! ${cfg.package}/bin/jboss-cli.sh --connect ':read-attribute(name=server-state)'; do
|
||||
while ! jboss-cli.sh --connect ':read-attribute(name=server-state)'; do
|
||||
if [[ "$attempt" == "$max_attempts" ]]; then
|
||||
echo "ERROR: Could not connect to Keycloak after $attempt attempts! Failing.." >&2
|
||||
exit 1
|
||||
|
@ -561,7 +579,7 @@ in
|
|||
(( attempt++ ))
|
||||
done
|
||||
|
||||
${cfg.package}/bin/jboss-cli.sh --connect --file=${jbossCliScript} --echo-command
|
||||
jboss-cli.sh --connect --file=${jbossCliScript} --echo-command
|
||||
|
||||
cp configuration/standalone.xml $out
|
||||
'';
|
||||
|
@ -570,8 +588,8 @@ in
|
|||
|
||||
assertions = [
|
||||
{
|
||||
assertion = (cfg.databaseUseSSL && cfg.databaseType == "postgresql") -> (cfg.databaseCaCert != null);
|
||||
message = "A CA certificate must be specified (in 'services.keycloak.databaseCaCert') when PostgreSQL is used with SSL";
|
||||
assertion = (cfg.database.useSSL && cfg.database.type == "postgresql") -> (cfg.database.caCert != null);
|
||||
message = "A CA certificate must be specified (in 'services.keycloak.database.caCert') when PostgreSQL is used with SSL";
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -581,6 +599,7 @@ in
|
|||
after = [ "postgresql.service" ];
|
||||
before = [ "keycloak.service" ];
|
||||
bindsTo = [ "postgresql.service" ];
|
||||
path = [ config.services.postgresql.package ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
|
@ -588,13 +607,15 @@ in
|
|||
Group = "postgres";
|
||||
};
|
||||
script = ''
|
||||
set -eu
|
||||
set -o errexit -o pipefail -o nounset -o errtrace
|
||||
shopt -s inherit_errexit
|
||||
|
||||
PSQL=${config.services.postgresql.package}/bin/psql
|
||||
create_role="$(mktemp)"
|
||||
trap 'rm -f "$create_role"' ERR EXIT
|
||||
|
||||
db_password="$(<'${cfg.databasePasswordFile}')"
|
||||
$PSQL -tAc "SELECT 1 FROM pg_roles WHERE rolname='keycloak'" | grep -q 1 || $PSQL -tAc "CREATE ROLE keycloak WITH LOGIN PASSWORD '$db_password' CREATEDB"
|
||||
$PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = 'keycloak'" | grep -q 1 || $PSQL -tAc 'CREATE DATABASE "keycloak" OWNER "keycloak"'
|
||||
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_database WHERE datname = 'keycloak'" | grep -q 1 || psql -tAc 'CREATE DATABASE "keycloak" OWNER "keycloak"'
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -602,6 +623,7 @@ in
|
|||
after = [ "mysql.service" ];
|
||||
before = [ "keycloak.service" ];
|
||||
bindsTo = [ "mysql.service" ];
|
||||
path = [ config.services.mysql.package ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
|
@ -609,13 +631,14 @@ in
|
|||
Group = config.services.mysql.group;
|
||||
};
|
||||
script = ''
|
||||
set -eu
|
||||
set -o errexit -o pipefail -o nounset -o errtrace
|
||||
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 DATABASE keycloak CHARACTER SET utf8 COLLATE utf8_unicode_ci;"
|
||||
echo "GRANT ALL PRIVILEGES ON keycloak.* TO 'keycloak'@'localhost';"
|
||||
) | ${config.services.mysql.package}/bin/mysql -N
|
||||
) | mysql -N
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -634,6 +657,8 @@ in
|
|||
bindsTo = databaseServices;
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = with pkgs; [
|
||||
cfg.package
|
||||
openssl
|
||||
replace-secret
|
||||
];
|
||||
environment = {
|
||||
|
@ -644,14 +669,21 @@ in
|
|||
serviceConfig = {
|
||||
ExecStartPre = let
|
||||
startPreFullPrivileges = ''
|
||||
set -eu
|
||||
set -o errexit -o pipefail -o nounset -o errtrace
|
||||
shopt -s inherit_errexit
|
||||
|
||||
install -T -m 0400 -o keycloak -g keycloak '${cfg.databasePasswordFile}' /run/keycloak/secrets/db_password
|
||||
'' + lib.optionalString (cfg.certificatePrivateKeyBundle != null) ''
|
||||
install -T -m 0400 -o keycloak -g keycloak '${cfg.certificatePrivateKeyBundle}' /run/keycloak/secrets/ssl_cert_pk_bundle
|
||||
umask u=rwx,g=,o=
|
||||
|
||||
install -T -m 0400 -o keycloak -g keycloak '${cfg.database.passwordFile}' /run/keycloak/secrets/db_password
|
||||
'' + lib.optionalString (cfg.sslCertificate != null && cfg.sslCertificateKey != null) ''
|
||||
install -T -m 0400 -o keycloak -g keycloak '${cfg.sslCertificate}' /run/keycloak/secrets/ssl_cert
|
||||
install -T -m 0400 -o keycloak -g keycloak '${cfg.sslCertificateKey}' /run/keycloak/secrets/ssl_key
|
||||
'';
|
||||
startPre = ''
|
||||
set -eu
|
||||
set -o errexit -o pipefail -o nounset -o errtrace
|
||||
shopt -s inherit_errexit
|
||||
|
||||
umask u=rwx,g=,o=
|
||||
|
||||
install -m 0600 ${cfg.package}/standalone/configuration/*.properties /run/keycloak/configuration
|
||||
install -T -m 0600 ${keycloakConfig} /run/keycloak/configuration/standalone.xml
|
||||
|
@ -659,11 +691,14 @@ in
|
|||
replace-secret '@db-password@' '/run/keycloak/secrets/db_password' /run/keycloak/configuration/standalone.xml
|
||||
|
||||
export JAVA_OPTS=-Djboss.server.config.user.dir=/run/keycloak/configuration
|
||||
${cfg.package}/bin/add-user-keycloak.sh -u admin -p '${cfg.initialAdminPassword}'
|
||||
'' + lib.optionalString (cfg.certificatePrivateKeyBundle != null) ''
|
||||
add-user-keycloak.sh -u admin -p '${cfg.initialAdminPassword}'
|
||||
'' + lib.optionalString (cfg.sslCertificate != null && cfg.sslCertificateKey != null) ''
|
||||
pushd /run/keycloak/ssl/
|
||||
cat /run/keycloak/secrets/ssl_cert_pk_bundle <(echo) /etc/ssl/certs/ca-certificates.crt > allcerts.pem
|
||||
${pkgs.openssl}/bin/openssl pkcs12 -export -in /run/keycloak/secrets/ssl_cert_pk_bundle -chain \
|
||||
cat /run/keycloak/secrets/ssl_cert <(echo) \
|
||||
/run/keycloak/secrets/ssl_key <(echo) \
|
||||
/etc/ssl/certs/ca-certificates.crt \
|
||||
> allcerts.pem
|
||||
openssl pkcs12 -export -in /run/keycloak/secrets/ssl_cert -inkey /run/keycloak/secrets/ssl_key -chain \
|
||||
-name "${cfg.frontendUrl}" -out certificate_private_key_bundle.p12 \
|
||||
-CAfile allcerts.pem -passout pass:notsosecretpassword
|
||||
popd
|
||||
|
@ -697,4 +732,5 @@ in
|
|||
};
|
||||
|
||||
meta.doc = ./keycloak.xml;
|
||||
meta.maintainers = [ lib.maintainers.talyz ];
|
||||
}
|
||||
|
|
|
@ -41,31 +41,31 @@
|
|||
<productname>PostgreSQL</productname> or
|
||||
<productname>MySQL</productname>. Which one is used can be
|
||||
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
|
||||
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
|
||||
linkend="opt-services.keycloak.databaseCreateLocally" /> is set
|
||||
linkend="opt-services.keycloak.database.createLocally" /> is set
|
||||
to <literal>false</literal>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
External database access can also be configured by setting
|
||||
<xref linkend="opt-services.keycloak.databaseHost" />, <xref
|
||||
linkend="opt-services.keycloak.databaseUsername" />, <xref
|
||||
linkend="opt-services.keycloak.databaseUseSSL" /> and <xref
|
||||
linkend="opt-services.keycloak.databaseCaCert" /> as
|
||||
<xref linkend="opt-services.keycloak.database.host" />, <xref
|
||||
linkend="opt-services.keycloak.database.username" />, <xref
|
||||
linkend="opt-services.keycloak.database.useSSL" /> and <xref
|
||||
linkend="opt-services.keycloak.database.caCert" /> as
|
||||
appropriate. Note that you need to manually create a database
|
||||
called <literal>keycloak</literal> and allow the configured
|
||||
database user full access to it.
|
||||
</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
|
||||
to log in to the database. If <xref linkend="opt-services.keycloak.databaseHost" />
|
||||
and <xref linkend="opt-services.keycloak.databaseCreateLocally" />
|
||||
to log in to the database. If <xref linkend="opt-services.keycloak.database.host" />
|
||||
and <xref linkend="opt-services.keycloak.database.createLocally" />
|
||||
are kept at their defaults, the database role
|
||||
<literal>keycloak</literal> with that password is provisioned
|
||||
on the local database instance.
|
||||
|
@ -115,17 +115,17 @@
|
|||
</para>
|
||||
|
||||
<para>
|
||||
For HTTPS support, a TLS certificate and private key is
|
||||
required. They should be <link
|
||||
HTTPS support requires a TLS/SSL certificate and a private key,
|
||||
both <link
|
||||
xlink:href="https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail">PEM
|
||||
formatted</link> and concatenated into a single file. The path
|
||||
to this file should be configured in
|
||||
<xref linkend="opt-services.keycloak.certificatePrivateKeyBundle" />.
|
||||
formatted</link>. Their paths should be set through <xref
|
||||
linkend="opt-services.keycloak.sslCertificate" /> and <xref
|
||||
linkend="opt-services.keycloak.sslCertificateKey" />.
|
||||
</para>
|
||||
|
||||
<warning>
|
||||
<para>
|
||||
The path should be provided as a string, not a Nix path,
|
||||
The paths should be provided as a strings, not a Nix paths,
|
||||
since Nix paths are copied into the world readable Nix store.
|
||||
</para>
|
||||
</warning>
|
||||
|
@ -195,8 +195,9 @@ services.keycloak = {
|
|||
<link linkend="opt-services.keycloak.initialAdminPassword">initialAdminPassword</link> = "e6Wcm0RrtegMEHl"; # change on first login
|
||||
<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.certificatePrivateKeyBundle">certificatePrivateKeyBundle</link> = "/run/keys/ssl_cert";
|
||||
<link linkend="opt-services.keycloak.databasePasswordFile">databasePasswordFile</link> = "/run/keys/db_password";
|
||||
<link linkend="opt-services.keycloak.sslCertificate">sslCertificate</link> = "/run/keys/ssl_cert";
|
||||
<link linkend="opt-services.keycloak.sslCertificateKey">sslCertificateKey</link> = "/run/keys/ssl_key";
|
||||
<link linkend="opt-services.keycloak.database.passwordFile">database.passwordFile</link> = "/run/keys/db_password";
|
||||
};
|
||||
</programlisting>
|
||||
</para>
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
# client using their Keycloak login.
|
||||
|
||||
let
|
||||
frontendUrl = "http://keycloak/auth";
|
||||
certs = import ./common/acme/server/snakeoil-certs.nix;
|
||||
frontendUrl = "https://${certs.domain}/auth";
|
||||
initialAdminPassword = "h4IhoJFnt2iQIR9";
|
||||
|
||||
keycloakTest = import ./make-test-python.nix (
|
||||
|
@ -17,12 +18,27 @@ let
|
|||
nodes = {
|
||||
keycloak = { ... }: {
|
||||
virtualisation.memorySize = 1024;
|
||||
|
||||
security.pki.certificateFiles = [
|
||||
certs.ca.cert
|
||||
];
|
||||
|
||||
networking.extraHosts = ''
|
||||
127.0.0.1 ${certs.domain}
|
||||
'';
|
||||
|
||||
services.keycloak = {
|
||||
enable = true;
|
||||
inherit frontendUrl databaseType initialAdminPassword;
|
||||
databaseUsername = "bogus";
|
||||
databasePasswordFile = pkgs.writeText "dbPassword" "wzf6vOCbPp6cqTH";
|
||||
inherit frontendUrl initialAdminPassword;
|
||||
sslCertificate = certs.${certs.domain}.cert;
|
||||
sslCertificateKey = certs.${certs.domain}.key;
|
||||
database = {
|
||||
type = databaseType;
|
||||
username = "bogus";
|
||||
passwordFile = pkgs.writeText "dbPassword" "wzf6vOCbPp6cqTH";
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
xmlstarlet
|
||||
libtidy
|
||||
|
|
Loading…
Reference in a new issue