<chapter xmlns="http://docbook.org/ns/docbook"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         xmlns:xi="http://www.w3.org/2001/XInclude"
         version="5.0"
         xml:id="module-services-keycloak">
 <title>Keycloak</title>
 <para>
   <link xlink:href="https://www.keycloak.org/">Keycloak</link> is an
   open source identity and access management server with support for
   <link xlink:href="https://openid.net/connect/">OpenID
   Connect</link>, <link xlink:href="https://oauth.net/2/">OAUTH
   2.0</link> and <link
   xlink:href="https://en.wikipedia.org/wiki/SAML_2.0">SAML
   2.0</link>.
 </para>
   <section xml:id="module-services-keycloak-admin">
     <title>Administration</title>
     <para>
       An administrative user with the username
       <literal>admin</literal> is automatically created in the
       <literal>master</literal> realm. Its initial password can be
       configured by setting <xref linkend="opt-services.keycloak.initialAdminPassword" />
       and defaults to <literal>changeme</literal>. The password is
       not stored safely and should be changed immediately in the
       admin panel.
     </para>

     <para>
       Refer to the <link
       xlink:href="https://www.keycloak.org/docs/latest/server_admin/index.html#admin-console">Admin
       Console section of the Keycloak Server Administration Guide</link> for
       information on how to administer your
       <productname>Keycloak</productname> instance.
     </para>
   </section>

   <section xml:id="module-services-keycloak-database">
     <title>Database access</title>
     <para>
       <productname>Keycloak</productname> can be used with either
       <productname>PostgreSQL</productname> or
       <productname>MySQL</productname>. Which one is used can be
       configured in <xref
       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.database.host" /> is changed from
       its default of <literal>localhost</literal> or <xref
       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.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.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.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.
     </para>

     <warning>
       <para>
         The path should be provided as a string, not a Nix path, since Nix
         paths are copied into the world readable Nix store.
       </para>
     </warning>
   </section>

   <section xml:id="module-services-keycloak-frontendurl">
     <title>Frontend URL</title>
     <para>
       The frontend URL is used as base for all frontend requests and
       must be configured through <xref linkend="opt-services.keycloak.frontendUrl" />.
       It should normally include a trailing <literal>/auth</literal>
       (the default web context).
     </para>

     <para>
       <xref linkend="opt-services.keycloak.forceBackendUrlToFrontendUrl" />
       determines whether Keycloak should force all requests to go
       through the frontend URL. By default,
       <productname>Keycloak</productname> allows backend requests to
       instead use its local hostname or IP address and may also
       advertise it to clients through its OpenID Connect Discovery
       endpoint.
     </para>

     <para>
       See the <link
       xlink:href="https://www.keycloak.org/docs/latest/server_installation/#_hostname">Hostname
       section of the Keycloak Server Installation and Configuration
       Guide</link> for more information.
     </para>
   </section>

   <section xml:id="module-services-keycloak-tls">
     <title>Setting up TLS/SSL</title>
     <para>
       By default, <productname>Keycloak</productname> won't accept
       unsecured HTTP connections originating from outside its local
       network.
     </para>

     <para>
       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>. Their paths should be set through <xref
       linkend="opt-services.keycloak.sslCertificate" /> and <xref
       linkend="opt-services.keycloak.sslCertificateKey" />.
     </para>

     <warning>
       <para>
         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>
   </section>

   <section xml:id="module-services-keycloak-extra-config">
     <title>Additional configuration</title>
     <para>
       Additional Keycloak configuration options, for which no
       explicit <productname>NixOS</productname> options are provided,
       can be set in <xref linkend="opt-services.keycloak.extraConfig" />.
     </para>

     <para>
       Options are expressed as a Nix attribute set which matches the
       structure of the jboss-cli configuration. The configuration is
       effectively overlayed on top of the default configuration
       shipped with Keycloak. To remove existing nodes and undefine
       attributes from the default configuration, set them to
       <literal>null</literal>.
     </para>
     <para>
       For example, the following script, which removes the hostname
       provider <literal>default</literal>, adds the deprecated
       hostname provider <literal>fixed</literal> and defines it the
       default:

<programlisting>
/subsystem=keycloak-server/spi=hostname/provider=default:remove()
/subsystem=keycloak-server/spi=hostname/provider=fixed:add(enabled = true, properties = { hostname = "keycloak.example.com" })
/subsystem=keycloak-server/spi=hostname:write-attribute(name=default-provider, value="fixed")
</programlisting>

       would be expressed as

<programlisting>
services.keycloak.extraConfig = {
  "subsystem=keycloak-server" = {
    "spi=hostname" = {
      "provider=default" = null;
      "provider=fixed" = {
        enabled = true;
        properties.hostname = "keycloak.example.com";
      };
      default-provider = "fixed";
    };
  };
};
</programlisting>
     </para>
     <para>
       You can discover available options by using the <link
       xlink:href="http://docs.wildfly.org/21/Admin_Guide.html#Command_Line_Interface">jboss-cli.sh</link>
       program and by referring to the <link
       xlink:href="https://www.keycloak.org/docs/latest/server_installation/index.html">Keycloak
       Server Installation and Configuration Guide</link>.
     </para>
   </section>

   <section xml:id="module-services-keycloak-example-config">
     <title>Example configuration</title>
     <para>
       A basic configuration with some custom settings could look like this:
<programlisting>
services.keycloak = {
  <link linkend="opt-services.keycloak.enable">enable</link> = true;
  <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.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>

   </section>
 </chapter>
