<!--
  ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
  ~ and other contributors as indicated by the @author tags.
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~ http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  -->

<chapter id="server-installation">
    <title>Installation and Configuration of Keycloak Server</title>

    <section>
        <title>Installation</title>
        <para>
            Keycloak Server has three downloadable distributions. To run the Keycloak server you need to have Java 8 already
            installed.
        </para>
        <para>
            <itemizedlist>
                <listitem>
                    <literal>keycloak-&project.version;.[zip|tar.gz]</literal> - Standalone server
                </listitem>
                <listitem>
                    <literal>keycloak-overlay-&project.version;.[zip|tar.gz]</literal> - Installer for WildFly or JBoss EAP
                </listitem>
                <listitem>
                    <literal>keycloak-demo-&project.version;.[zip|tar.gz]</literal> - Development bundle including WildFly, Keycloak, examples and documentation
                </listitem>
            </itemizedlist>
        </para>
        <section id="server_install">
            <title>Install Standalone Server</title>
            <para>
                For production and for non-JavaEE developers we recommend using the standalone Keycloak server. All you need to
                do is to download <literal>keycloak-&project.version;.zip</literal> or  <literal>keycloak-&project.version;.tar.gz</literal>,
                unpackage and start to have a Keycloak server up and running.
            </para>

            <para>
                To install first download either the zip or tar.gz and extract. Then start by running either:
                <programlisting>keycloak-&project.version;/bin/standalone.sh</programlisting>
                or:
                <programlisting>keycloak-&project.version;/bin/standalone.bat</programlisting>
            </para>
        </section>


        <section id="overlay_install">
            <title>Install on existing WildFly &wildfly.version; or JBoss EAP &eap.version;</title>
            <para>
                Keycloak can be installed into an existing installations of WildFly &wildfly.version; or JBoss EAP &eap.version;.
                To do this download <literal>keycloak-overlay-&project.version;.zip</literal> or <literal>keycloak-overlay-&project.version;.tar.gz</literal>.
                Once downloaded extract into the root directory of your installation.
            </para>
            <para>
                To add Keycloak to existing standalone.xml server config run:
<programlisting>
bin/jboss-cli.sh --file=bin/keycloak-install.cli
</programlisting>
                To add Keycloak to existing standalone-ha.xml server config run:
<programlisting>
bin/jboss-cli.sh --file=bin/keycloak-install-ha.cli
</programlisting>
                If you want to add Keycloak to a different server config edit keycloak-install.cli or keycloak-install-ha.cli
                and change the name of the server config.
            </para>
        </section>
        <section>
            <title id="demo_install">Install Development Bundle</title>
            <para>
                The demo bundle contains everything you need to get started with Keycloak including documentation and examples.
                To install it first download <literal>keycloak-demo-&project.version;.zip</literal> or
                <literal>keycloak-demo-&project.version;.tar.gz</literal>. Once downloaded extract it inside
                <literal>keycloak-demo-&project.version;</literal> you'll find <literal>keycloak</literal> which contains
                a full WildFly &wildfly.version; server with Keycloak Server and Adapters included. You'll also find <literal>docs</literal>
                and <literal>examples</literal> which contains everything you need to get started developing applications that use Keycloak.
            </para>
            <para>
                To start WildFly with Keycloak run:
                <programlisting>keycloak-&project.version;/bin/standalone.sh</programlisting>
                or:
                <programlisting>keycloak-&project.version;/bin/standalone.bat</programlisting>
            </para>
        </section>
    </section>

    <section>
        <title id="configure-server">Configuring the Server</title>
        <para>
            Although the Keycloak Server is designed to run out of the box, there's some things you'll need
            to configure before you go into production.  Specifically:
            <itemizedlist>
                <listitem>
                    Configuring Keycloak to use a production database
                </listitem>

                <listitem>
                    Setting up SSL/HTTPS
                </listitem>

                <listitem>
                    Enforcing HTTPS connections
                </listitem>
            </itemizedlist>
        </para>
        <section>
            <title id="create-admin-user">Admin User</title>
            <para>
                To access the admin console to configure Keycloak you need an account to login. There is no built in user,
                instead you have to first create an admin account. This can done either by opening <ulink url="http://localhost:8080/auth">http://localhost:8080/auth</ulink>
                (creating a user through the browser can only be done through localhost) or you can use the add-user-keycloak script from
                the command-line.
            </para>
            <para>
                The <literal>add-user-keycloak</literal> script creates a temporary file with the details of the user,
                which are imported at startup. To add a user with this script run:
<programlisting><![CDATA[
bin/add-user-keycloak.[sh|bat] -r master -u <username> -p <password>
]]></programlisting>
                Then restart the server.
            </para>
            </section>

        <section>
            <title>Relational Database Configuration</title>
            <para>
                You might want to use a better relational database for Keycloak like PostgreSQL or MySQL.  You might also
                want to tweak the configuration settings of the datasource.  Please see the <ulink url="https://docs.jboss.org/author/display/WFLY8/DataSource+configuration">Wildfly</ulink>
                documentation on how to do this.
            </para>
            <para>
                Keycloak runs on a Hibernate/JPA backend which is configured in the
                <literal>standalone/configuration/keycloak-server.json</literal>.
                By default the setting is like this:
                <programlisting><![CDATA[
"connectionsJpa": {
    "default": {
        "dataSource": "java:jboss/datasources/KeycloakDS",
        "databaseSchema": "update"
    }
},
]]></programlisting>
                Possible configuration options are:
                <variablelist>
                    <varlistentry>
                        <term>dataSource</term>
                        <listitem>
                            <para>
                                JNDI name of the dataSource
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>jta</term>
                        <listitem>
                            <para>
                                boolean property to specify if datasource is JTA capable
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>driverDialect</term>
                        <listitem>
                            <para>
                                Value of Hibernate dialect. In most cases you don't need to specify this property as dialect will be
                                autodetected by Hibernate.
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>databaseSchema</term>
                        <listitem>
                            <para>
                                Specify if schema should be updated or validated. Valid values are <literal>update</literal> and <literal>validate</literal>.
                                Value <literal>update</literal> is default and means that DB schema will be updated to latest version.
                                Value <literal>validate</literal> won't touch database schema, but it will fail to start if schema is not updated to latest version.
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>showSql</term>
                        <listitem>
                            <para>
                                Specify whether Hibernate should show all SQL commands in the console (false by default)
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>formatSql</term>
                        <listitem>
                            <para>
                                Specify whether Hibernate should format SQL commands (true by default)
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>globalStatsInterval</term>
                        <listitem>
                            <para>
                                Will log global statistics from Hibernate about executed DB queries and other things. Statistics are always reported
                                to server log at specified interval (in seconds) and are cleared after each report.
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>schema</term>
                        <listitem>
                            <para>
                                Specify the database schema to use
                            </para>
                        </listitem>
                    </varlistentry>
                </variablelist>
            </para>
            <section>
                <title>Tested databases</title>
                <para>
                    Here is list of RDBMS databases and corresponding JDBC drivers, which were tested with Keycloak. Note that Hibernate dialect
                    is usually set automatically according to your database, but you have possibility to override if default dialect doesn't work correctly.
                    You can setup dialect by adding property <literal>driverDialect</literal>
                    to the <literal>keycloak-server.json</literal> into <literal>connectionsJpa</literal> section (see above).
                    <table frame='all'><title>Tested databases</title>
                        <tgroup cols='3' align='left' colsep='1' rowsep='1'>
                            <thead>
                                <row>
                                    <entry>Database</entry>
                                    <entry>JDBC driver</entry>
                                    <entry>Hibernate Dialect</entry>
                                </row>
                            </thead>
                            <tbody>
                                <row>
                                    <entry>H2 1.3.161</entry>
                                    <entry>H2 1.3.161</entry>
                                    <entry>auto</entry>
                                </row>
                                <row>
                                    <entry>MySQL 5.5</entry>
                                    <entry>MySQL Connector/J 5.1.25</entry>
                                    <entry>auto</entry>
                                </row>
                                <row>
                                    <entry>PostgreSQL 9.2</entry>
                                    <entry>JDBC4 Postgresql Driver, Version 9.3-1100</entry>
                                    <entry>auto</entry>
                                </row>
                                <row>
                                    <entry>PostgresPlus 9.4</entry>
                                    <entry>edb-jdbc17-4.0</entry>
                                    <entry>auto</entry>
                                </row>
                                <row>
                                    <entry>Oracle 11g R1</entry>
                                    <entry>Oracle JDBC Driver v11.1.0.7</entry>
                                    <entry>auto</entry>
                                </row>
                                <row>
                                    <entry>Microsoft SQL Server 2012</entry>
                                    <entry>Microsoft SQL Server JDBC Driver 4.0.2206.100</entry>
                                    <entry>auto</entry>
                                </row>
                                <row>
                                    <entry>IBM DB2 10.5</entry>
                                    <entry>JDBC 4.0 Driver (db2jcc4.jar) 4.19.26</entry>
                                    <entry>auto</entry>
                                </row>
                            </tbody>
                        </tgroup>
                    </table>
                </para>
            </section>
        </section>
        <section>
            <title>MongoDB based model</title>
            <para>
                Keycloak provides <ulink url="http://www.mongodb.com">MongoDB</ulink> based model implementation, which means that your identity data will be saved
                in MongoDB instead of traditional RDBMS. To configure Keycloak to use Mongo open <literal>standalone/configuration/keycloak-server.json</literal>
                in your favourite editor, then change:

<programlisting><![CDATA[
"eventsStore": {
    "provider": "jpa",
    "jpa": {
        "exclude-events": [ "REFRESH_TOKEN" ]
    }
},

"realm": {
    "provider": "jpa"
},

"user": {
    "provider": "jpa"
},

"userSessionPersister": {
    "provider": "jpa"
},
]]></programlisting>

                to:

                <programlisting><![CDATA[
"eventsStore": {
    "provider": "mongo",
    "mongo": {
        "exclude-events": [ "REFRESH_TOKEN" ]
    }
},

"realm": {
    "provider": "mongo"
},

"user": {
    "provider": "mongo"
},

"userSessionPersister": {
    "provider": "mongo"
},
]]></programlisting>

                And at the end of the file add the snippet like this where you can configure details about your Mongo database:
                <programlisting><![CDATA[
"connectionsMongo": {
    "default": {
        "host": "127.0.0.1",
        "port": "27017",
        "db": "keycloak",
        "connectionsPerHost": 100,
        "databaseSchema": "update"
    }
}
]]></programlisting>

                All configuration options are optional. Default values for host and port are localhost and 27017. Default name of database
                is <literal>keycloak</literal> . You can also specify properties <literal>user</literal> and <literal>password</literal>
                if you want authenticate against your MongoDB. If user and password are not specified, Keycloak will connect
                unauthenticated to your MongoDB.
            </para>
            <para>
                Option <literal>databaseSchema</literal> specify if mongo database "schema" should be updated or validated. Valid values are <literal>update</literal> and <literal>validate</literal>.
                Value <literal>update</literal> means that DB schema will be updated to latest version.
                Value <literal>validate</literal> won't touch database schema, but it will fail to start if schema is not updated to latest version.
            </para>
            <note>
                Mongo doesn't have real database schema, but 'schema' in this case means to which Keycloak version the data in the Mongo database corresponds.
            </note>
            <para>Finally there is set of optional configuration options, which can be used to specify connection-pooling capabilities of Mongo client. Supported int options are:
                <literal>connectionsPerHost</literal>, <literal>threadsAllowedToBlockForConnectionMultiplier</literal>, <literal>maxWaitTime</literal>, <literal>connectTimeout</literal>
                <literal>socketTimeout</literal>. Supported boolean options are: <literal>socketKeepAlive</literal>, <literal>autoConnectRetry</literal>.
                Supported long option is <literal>maxAutoConnectRetryTime</literal>. See <ulink url="http://api.mongodb.org/java/2.11.4/com/mongodb/MongoClientOptions.html">Mongo documentation</ulink>
                for details about those options and their default values.
            </para>
            <para>
                Alternatively, you can configure MongoDB using a MongoDB <ulink url="http://docs.mongodb.org/manual/reference/connection-string/">connection URI</ulink>.
                In this case, you define all information concerning the connection and authentication within the URI, as described in the MongoDB documentation.
                Please note that the database specified within the URI is only used for authentication. To change the database used by keycloak you have to set
                <literal>db</literal> property as before. Therefore, a configuration like the
                following
                <programlisting><![CDATA[
"connectionsMongo": {
    "default": {
        "uri": "mongodb://user:password@127.0.0.1/authentication",
        "db": "keycloak",
        "databaseSchema": "update"
    }
}
]]></programlisting>
                will authenticate the user against the authentication database, but store all keycloak related data in the keycloak database.

            </para>
            <section>
                <title>MongoDB Replica Sets</title>
                <para>
                    In order to use a mongo replica set for Keycloak, one has to use URI based configuration, which supports the
                    definition of replica sets out of the box: <literal>mongodb://host1:27017,host2:27017,host3:27017/</literal>.
                </para>
            </section>
        </section>

        <section>
            <title>Outgoing Server HTTP Requests</title>
            <para>
                Keycloak server needs to invoke on remote HTTP endpoints to do things like backchannel logouts and other
                management functions.  Keycloak maintains a HTTP client connection pool which has various configuration
                settings you can specify before boot time.  This is configured in the
                <literal>standalone/configuration/keycloak-server.json</literal>.
                By default the setting is like this:
<programlisting><![CDATA[
"connectionsHttpClient": {
    "default": {}
},
]]></programlisting>
                Possible configuration options are:
                <variablelist>
                    <varlistentry>
                        <term>establish-connection-timeout-millis</term>
                        <listitem>
                            <para>
                                Timeout for establishing a socket connection.
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>socket-timeout-millis</term>
                        <listitem>
                            <para>
                                If an outgoing request does not receive data for this amount of time, timeout the connection.
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>connection-pool-size</term>
                        <listitem>
                            <para>
                                How many connections can be in the pool (128 by default).
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>max-pooled-per-route</term>
                        <listitem>
                            <para>
                                How many connections can be pooled per host (64 by default).
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>connection-ttl-millis</term>
                        <listitem>
                            <para>
                                Maximum connection time to live in milliseconds. Not set by default.
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>max-connection-idle-time-millis</term>
                        <listitem>
                            <para>
                                Maximum time the connection might stay idle in the connection pool (900 seconds by default). Will start background cleaner thread of Apache HTTP client.
                                Set to -1 to disable this checking and the background thread.
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>disable-cookies</term>
                        <listitem>
                            <para>
                                <literal>true</literal> by default.  When set to true, this will disable any cookie
                                caching.
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>client-keystore</term>
                        <listitem>
                            <para>
                                This is the file path to a Java keystore file.
                                This keystore contains client certificate for two-way SSL.
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>client-keystore-password</term>
                        <listitem>
                            <para>
                                Password for the client keystore.
                                This is
                                <emphasis>REQUIRED</emphasis>
                                if
                                <literal>client-keystore</literal>
                                is set.
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>client-key-password</term>
                        <listitem>
                            <para>
                                <emphasis>Not supported yet, but we will support in future versions.</emphasis>
                                Password for the client's key.
                                This is
                                <emphasis>REQUIRED</emphasis>
                                if
                                <literal>client-keystore</literal>
                                is set.
                            </para>
                        </listitem>
                    </varlistentry>
                </variablelist>
            </para>
        </section>
        <section id="truststore">
            <title>Securing Outgoing Server HTTP Requests</title>
            <para>
            When Keycloak connects out to remote HTTP endpoints over secure https connection, it has to validate the other
            server's certificate in order to ensure it is connecting to a trusted server. That is necessary in order to
            prevent man-in-the-middle attacks.
            </para>
            <para>
            How certificates are validated is configured in the <literal>standalone/configuration/keycloak-server.json</literal>.
            By default truststore provider is not configured, and any https connections fall back to standard java truststore
            configuration as described in <ulink url="https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html">
            Java's JSSE Reference Guide</ulink> - using <literal>javax.net.ssl.trustStore system property</literal>,
            otherwise <literal>cacerts</literal> file that comes with java is used.
            </para>
            <para>
                Truststore is used when connecting securely to identity brokers, LDAP federation providers, when sending emails,
                and for backchannel communication with client applications.

                Some of these facilities may - in case when no trusted certificate is found in your configured truststore -
                fallback to using the JSSE provided truststore.

                The default JavaMail API implementation used to send out emails behaves in this way, for example.
            </para>
            <para>
            You can add your truststore configuration by using the following template:

            <programlisting><![CDATA[
"truststore": {
    "file": {
        "file": "path to your .jks file containing public certificates",
        "password": "password",
        "hostname-verification-policy": "WILDCARD",
        "disabled": false
    }
}
]]></programlisting>

            </para>
            <para>
            Possible configuration options are:

                <variablelist>
                    <varlistentry>
                        <term>file</term>
                        <listitem>
                            <para>
                                The value is the file path to a Java keystore file.
                                HTTPS requests need a way to verify the host of the server they are talking to. This is
                                what the trustore does. The keystore contains one or more trusted host certificates or
                                certificate authorities. Truststore file should only contain public certificates of your secured hosts.

                                This is
                                <emphasis>REQUIRED</emphasis>
                                if <literal>disabled</literal> is not true.
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>password</term>
                        <listitem>
                            <para>
                                Password for the truststore.
                                This is
                                <emphasis>REQUIRED</emphasis>
                                if <literal>disabled</literal> is not true.
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>hostname-verification-policy</term>
                        <listitem>
                            <para>
                                <literal>WILDCARD</literal> by default.  For HTTPS requests, this verifies the hostname
                                of the server's certificate.  <literal>ANY</literal> means that the hostname is not verified.
                                <literal>WILDCARD</literal> Allows wildcards in subdomain names i.e. *.foo.com.
                                <literal>STRICT</literal> CN must match hostname exactly.
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>disabled</term>
                        <listitem>
                            <para>
                                If true (default value), truststore configuration will be ignored, and certificate checking will
                                fall back to JSSE configuration as described. If set to false, you must
                                configure <literal>file</literal>, and <literal>password</literal> for the truststore.
                            </para>
                        </listitem>
                    </varlistentry>
                </variablelist>
            </para>
            <para>
            You can use <emphasis>keytool</emphasis> to create a new truststore file and add trusted host certificates to it:

                <programlisting>
$ keytool -import -alias HOSTDOMAIN -keystore truststore.jks -file host-certificate.cer
                </programlisting>
            </para>
        </section>
        <section id="ssl_modes">
            <title>SSL/HTTPS Requirement/Modes</title>
            <warning>
                <para>
                    Keycloak is not set up by default to handle SSL/HTTPS. It is highly recommended that you either enable SSL
                    on the Keycloak server itself or on a reverse proxy in front of the Keycloak server.
                </para>
            </warning>
            <para>
                Keycloak can run out of the box without SSL so long as you stick to private IP addresses like
                localhost, 127.0.0.1, 10.0.x.x, 192.168.x.x, and 172..16.x.x.  If you try to access Keycloak from a
                non-IP adress you will get an error.
            </para>
            <para>
                Keycloak has 3 SSL/HTTPS modes which you can set up in the admin console under the Settings->Login page
                and the <literal>Require SSL</literal> select box.  Each adapter config should mirror this server-side
                setting.  See adapter config section for more details.
                <variablelist>
                    <varlistentry>
                        <term>external</term>
                        <listitem>
                            <para>
                                Keycloak can run out of the box without SSL so long as you stick to private IP addresses like
                                localhost, 127.0.0.1, 10.0.x.x, 192.168.x.x, and 172..16.x.x.  If you try to access Keycloak from a
                                non-IP adress you will get an error.
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>none</term>
                        <listitem>
                            <para>
                                Keycloak does not require SSL.
                            </para>
                        </listitem>
                    </varlistentry>
                    <varlistentry>
                        <term>all</term>
                        <listitem>
                            <para>
                                Keycloak requires SSL for all IP addresses.
                            </para>
                        </listitem>
                    </varlistentry>
                </variablelist>
            </para>
        </section>
        <section>
            <title>SSL/HTTPS Setup</title>

            <para>
                First enable SSL on Keycloak or on a reverse proxy in front of Keycloak. Then configure the Keycloak Server to enforce HTTPS connections.
            </para>

            <section>
                <title>Enable SSL on Keycloak</title>
                <para>
                    The following things need to be done
                    <itemizedlist>

                        <listitem>
                            Generate a self signed or third-party signed certificate and import it into a Java keystore
                            using <literal>keytool</literal>.
                        </listitem>

                        <listitem>
                            Enable Wildfly to use this certificate and turn on SSL/HTTPS.
                        </listitem>
                    </itemizedlist>
                </para>
                <section>
                    <title>Creating the Certificate and Java Keystore</title>
                    <para>
                        In order to allow HTTPS connections, you need to obtain a self signed or third-party signed certificate
                        and import it into a Java keystore before you can enable HTTPS in the web container you are deploying
                        the Keycloak Server to.
                    </para>
                    <section>
                        <title>Self Signed Certificate</title>
                        <para>
                            In development, you will probably not have a third party signed certificate available to test
                            a Keycloak deployment so you'll need to generate a self-signed on.  Generate one is very easy
                            to do with the <literal>keytool</literal> utility that comes with the Java jdk.
                        </para>
                        <para>
<programlisting>
$ keytool -genkey -alias localhost -keyalg RSA -keystore keycloak.jks -validity 10950
    Enter keystore password: secret
    Re-enter new password: secret
    What is your first and last name?
    [Unknown]:  localhost
    What is the name of your organizational unit?
    [Unknown]:  Keycloak
    What is the name of your organization?
    [Unknown]:  Red Hat
    What is the name of your City or Locality?
    [Unknown]:  Westford
    What is the name of your State or Province?
    [Unknown]:  MA
    What is the two-letter country code for this unit?
    [Unknown]:  US
    Is CN=localhost, OU=Keycloak, O=Test, L=Westford, ST=MA, C=US correct?
    [no]:  yes
</programlisting>
                        </para>
                        <para>
                            You should answer <literal>What is your first and last name ?</literal> question with
                            the DNS name of the machine you're installing the server on.  For testing purposes,
                            <literal>localhost</literal> should be used.  After executing this command, the
                            <literal>keycloak.jks</literal> file will be generated in the same directory as you executed
                            the <literal>keytool</literal> command in.
                        </para>
                        <para>
                            If you want a third-party signed certificate, but don't have one, you can obtain one for free
                            at <ulink url="http://cacert.org">cacert.org</ulink>.  You'll have to do a little set up first
                            before doing this though.
                        </para>
                        <para>
                            The first thing to do is generate a Certificate Request:
<programlisting>
$ keytool -certreq -alias yourdomain -keystore keycloak.jks > keycloak.careq
</programlisting>
                        </para>
                        <para>
                             Where <literal>yourdomain</literal> is a DNS name for which this certificate is generated for.
                             Keytool generates the request:
<programlisting>
-----BEGIN NEW CERTIFICATE REQUEST-----
MIIC2jCCAcICAQAwZTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk1BMREwDwYDVQQHEwhXZXN0Zm9y
ZDEQMA4GA1UEChMHUmVkIEhhdDEQMA4GA1UECxMHUmVkIEhhdDESMBAGA1UEAxMJbG9jYWxob3N0
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr7kck2TaavlEOGbcpi9c0rncY4HhdzmY
Ax2nZfq1eZEaIPqI5aTxwQZzzLDK9qbeAd8Ji79HzSqnRDxNYaZu7mAYhFKHgixsolE3o5Yfzbw1
29Rvy+eUVe+WZxv5oo9wolVVpdSINIMEL2LaFhtX/c1dqiqYVpfnvFshZQaIg2nL8juzZcBjj4as
H98gIS7khql/dkZKsw9NLvyxgJvp7PaXurX29fNf3ihG+oFrL22oFyV54BWWxXCKU/GPn61EGZGw
Ft2qSIGLdctpMD1aJR2bcnlhEjZKDksjQZoQ5YMXaAGkcYkG6QkgrocDE2YXDbi7GIdf9MegVJ35
2DQMpwIDAQABoDAwLgYJKoZIhvcNAQkOMSEwHzAdBgNVHQ4EFgQUQwlZJBA+fjiDdiVzaO9vrE/i
n2swDQYJKoZIhvcNAQELBQADggEBAC5FRvMkhal3q86tHPBYWBuTtmcSjs4qUm6V6f63frhveWHf
PzRrI1xH272XUIeBk0gtzWo0nNZnf0mMCtUBbHhhDcG82xolikfqibZijoQZCiGiedVjHJFtniDQ
9bMDUOXEMQ7gHZg5q6mJfNG9MbMpQaUVEEFvfGEQQxbiFK7hRWU8S23/d80e8nExgQxdJWJ6vd0X
MzzFK6j4Dj55bJVuM7GFmfdNC52pNOD5vYe47Aqh8oajHX9XTycVtPXl45rrWAH33ftbrS8SrZ2S
vqIFQeuLL3BaHwpl3t7j2lMWcK1p80laAxEASib/fAwrRHpLHBXRcq6uALUOZl4Alt8=
-----END NEW CERTIFICATE REQUEST-----
</programlisting>
                        </para>
                        <para>
                            Send this ca request to your CA.  The CA will issue you a signed certificate and send it to you.
                            Before you import your new cert, you must obtain and import the root certificate of the CA.
                            You can download the cert from CA (ie.: root.crt) and import as follows:
<programlisting>
$ keytool -import -keystore keycloak.jks -file root.crt -alias root
</programlisting>
                        </para>
                        <para>
                            Last step is import your new CA generated certificate to your keystore:
<programlisting>
$ keytool -import -alias yourdomain -keystore keycloak.jks -file your-certificate.cer
</programlisting>
                        </para>
                    </section>
                </section>
                <section>
                    <title>Installing the keystore to WildFly</title>
                    <para>
                        Now that you have a Java keystore with the appropriate certificates, you need to configure your
                        Wildfly installation to use it.  First step is to move the keystore file to a directory
                        you can reference in configuration.  I like to put it in <literal>standalone/configuration</literal>.
                        Then you need to edit <literal>standalone/configuration/standalone.xml</literal> to enable SSL/HTTPS.
                    </para>
                    <para>
                        To the <literal>security-realms</literal> element add:
<programlisting><![CDATA[
<security-realm name="UndertowRealm">
    <server-identities>
        <ssl>
            <keystore path="keycloak.jks" relative-to="jboss.server.config.dir" keystore-password="secret" />
        </ssl>
    </server-identities>
</security-realm>
]]></programlisting>
                    </para>
                    <para>
                        Find the element <literal>&lt;server name="default-server"&gt;</literal> (it's a child element of <literal>&lt;subsystem xmlns="urn:jboss:domain:undertow:1.0"&gt;</literal>) and add:
                        <programlisting><![CDATA[<https-listener name="https" socket-binding="https" security-realm="UndertowRealm"/>]]></programlisting>
                    </para>
                    <para>
                        Check the <ulink url="https://docs.jboss.org/author/display/WFLY10/Undertow+subsystem+configuration">Wildfly Undertow</ulink> documentation for more information on fine tuning the socket connections.
                    </para>
                </section>
            </section>

            <section>
                <title>Enable SSL on a Reverse Proxy</title>
                <para>
                    Follow the documentation for your web server to enable SSL and configure reverse proxy for Keycloak.
                    It is important that you make sure the web server sets the <literal>X-Forwarded-For</literal> and
                    <literal>X-Forwarded-Proto</literal> headers on the requests made to Keycloak and you enable
                    <literal>proxy-address-forwarding</literal> on the Keycloak http connector. This is described in <link linkend="proxy-address-forwarding">next section</link>, so
                    here we will focus just on SSL setup.
                </para>
                <para>
                    Assuming that your reverse proxy doesn't use port 8443 for SSL you also need to configure what port http traffic is redirected to.
                </para>

                <section>
                    <title>Configure WildFly</title>

                    <para>
                        Open <literal>standalone/configuration/standalone.xml</literal> in your favorite editor.
                    </para>

                    <para>
                        First add <literal>redirect-socket</literal> to
                        the <literal>http-listener</literal> element:
<programlisting><![CDATA[<subsystem xmlns="urn:jboss:domain:undertow:1.1">
    ...
    <http-listener name="default" socket-binding="http" redirect-socket="proxy-https"/>
    ...
</subsystem>
]]></programlisting>
                    </para>
                    <para>
                        Then add a new <literal>socket-binding</literal> element to the <literal>socket-binding-group</literal> element:
<programlisting><![CDATA[
<socket-binding-group name="standard-sockets" default-interface="public"
    port-offset="${jboss.socket.binding.port-offset:0}">
    ...
    <socket-binding name="proxy-https" port="443"/>
    ...
</socket-binding-group>
]]></programlisting>
                    </para>
                    <para>
                        Check the <ulink url="https://docs.jboss.org/author/display/WFLY10/Undertow+subsystem+configuration">WildFly</ulink> documentation for more information.
                    </para>
                </section>
            </section>

        </section>

        <section id="proxy-address-forwarding">
            <title>Configure reverse proxy for address forwarding</title>
            <para>
                Keycloak has some functionalities (for example <link linkend='events'>Events</link> or <link linkend="brute-force-attacks">Brute Force protector</link>)
                that relies on the fact, that remote address of the HTTP connection is the real IP address of the client machine. This may be a bit tricky when you have setup
                with reverse proxy or loadbalancer.
            </para>
            <para>
                Assume you have setup when users send requests to the "Frontend" server (reverse proxy), which then forwards them to the
                "backend" server (Keycloak) on private network. Then with default setup of Wildfly Undertow subsystem, Keycloak will see <literal>request.getRemoteAddress()</literal> to be
                resolved to the IP address of reverse proxy instead of real IP of client.
            </para>
            <para>
                To address this issue and see the real IP address of client, you need 2 things:
                <itemizedlist>
                    <listitem>
                        <para>Configure your reverse proxy (loadbalancer) to properly set <literal>X-Forwarded-For</literal> and <literal>X-Forwarded-Proto</literal> HTTP headers.</para>
                    </listitem>
                    <listitem>
                        <para>Configure Wildfly undertow subsystem on Keycloak server's side to read the client's IP address from <literal>X-Forwarded-For</literal> header.</para>
                    </listitem>
                </itemizedlist>
                More details for setup both things.
            </para>
            <section>
                <title>Configure your reverse proxy to set X-Forwarded-For</title>
                <para>
                    Consult the documentation of your reverse proxy implementation on how to do it.
                </para>
                <para>
                    Note that when your reverse proxy receives requests from the users on public network, you also need to ensure that <literal>X-Forwarded-For</literal>
                    is always overwritten by proxy with the IP address of client machine. If it's not overwritten, but just forwarded, the
                    "evil" user can manually set the <literal>X-Forwarded-For</literal> header to the false IP address to trick Keycloak.
                </para>
                <para>
                    For example imagine that evil user connects from IP address <literal>20.20.20.20</literal> but he manually sets the <literal>X-Forwarded-For</literal> header to
                    value <literal>30.30.30.30</literal>. If reverse proxy "forwards" the header, it will append the old value set by evil user with the IP address user connected from.
                    So <literal>X-Forwarded-For</literal> header will be incorrectly set to <literal>30.30.30.30 , 20.20.20.20</literal>. Then Keycloak will see incorrect IP
                    address <literal>30.30.30.30</literal>. So in this case, reverse proxy must overwrite the old value of header and just set the real IP
                    of the user machine to <literal>20.20.20.20</literal>. On the other hand, when you have more reverse proxies chained together, you need to configure
                    "overwriting" just for the first proxy in the chain.
                </para>
                <para>
                    Some example setups:
                    <variablelist>
                        <varlistentry>
                            <term>user (IP address: 20.20.20.20) -> load balancer (IP Address: 30.30.30.30 ) -> Keycloak</term>
                            <listitem>
                                <para>
                                    For this setup, loadbalancer receives the IP from the end user, so it must overwrite the header. So Keycloak will correctly see
                                    <literal>X-Forwarded-For: 20.20.20.20</literal> .
                                </para>
                            </listitem>
                        </varlistentry>
                        <varlistentry>
                            <term>internet (IP address: 20.20.20.20) -> reverse proxy (IP Address: 30.30.30.30 ) -> load balancer (IP Address: 40.40.40.40 ) -> keycloak</term>
                            <listitem>
                                <para>
                                    For this setup, just the first reverse proxy is supposed to overwrite <literal>X-Forwarded-For</literal> but second (load balancer) should just forwards it.
                                    So Keycloak will correctly see <literal>X-Forwarded-For: 20.20.20.20,30.30.30.30</literal>, hence in the second step, it will be able to correctly see
                                    client's remote IP address <literal>20.20.20.20</literal>.
                                </para>
                            </listitem>
                        </varlistentry>
                    </variablelist>
                </para>
            </section>
            <section>
                <title>Configure Wildfly undertow subsystem</title>
                <para>
                    This is needed, so the wildfly undertow subsystem will read the client's IP address from the <literal>X-Forwarded-For</literal> header rather than from the IP of network packet, which
                    came from loadbalancer and hence it's set to the IP of loadbalancer.
                </para>
                <para>
                    If your proxy sends requests to the HTTP connector, it can be configured easily by add attribute <literal>proxy-address-forwarding</literal> to the
                    <literal>http-listener</literal> subelement of undertow subsystem.
                    For example:
                    <programlisting><![CDATA[
<http-listener name="default" socket-binding="http"
    redirect-socket="https" proxy-address-forwarding="true" />
]]></programlisting>
                </para>
                <para>
                    If you use AJP connector, which is common setup for loadbalancers, the proxy-address-forwarding is not available, hence you need to do slightly more configurations.
                    First add <literal>filter</literal> subelement of <literal>filters</literal> element with the value like this:
                    <programlisting><![CDATA[
<filter name="proxy-peer"
    class-name="io.undertow.server.handlers.ProxyPeerAddressHandler"
    module="io.undertow.core" />
]]></programlisting>
                    Then reference it from the <literal>host</literal> element:
                    <programlisting><![CDATA[
<filter-ref name="proxy-peer"/>
]]></programlisting>
                    If you want to check address is correctly set, you can enable <link linkend="events">events</link> and verify the IP address really points to the IP address of client machine.
                </para>
                <para>
                    Check the <ulink url="https://docs.jboss.org/author/display/WFLY10/Undertow+subsystem+configuration">WildFly</ulink> documentation for more information.
                </para>
            </section>
        </section>

    </section>

    <section>
        <title>Keycloak server in Domain Mode</title>
        <para>
            In domain mode, you start the server with the "domain" command instead of the "standalone" command.  In this case, the Keycloak subsystem is
            defined in domain/configuration/domain.xml instead of standalone/configuration.standalone.xml.  Inside domain.xml, you will see more than one
            profile.  The Keycloak subsystem is defined for all initial profiles.
        </para>
        <para>
            THe server is also added to server profiles. By default two servers are started
            in the main-server-group which uses the full profile.
        </para>
        <para>
            You need to make sure <literal>domain/servers/&lt;SERVER NAME&gt;/configuration</literal> is identical
            for all servers in a group.
        </para>
        <para>
            To deploy custom providers and themes you should deploys these as modules and make sure the modules are
            available to all servers in the group. See <link linkend='providers'>Providers</link> and
            <link linkend='themes'>Themes</link> sections for more information on how to do this.
        </para>
    </section>

    <section>
        <title>Installing Keycloak Server as Root Context</title>
        <para>
            The Keycloak server can be installed as the default web application.  In doing so, the server can be referenced at <literal>http://mydomain.com/</literal> instead of <literal>http://mydomain.com/auth</literal>.
        </para>
        <para>
            To do this, add the <literal>default-web-module</literal> attribute in the Undertow subystem in standalone.xml.
<programlisting><![CDATA[
<subsystem xmlns="urn:jboss:domain:undertow:2.0">
    <server name="default-server">
        <host name="default-host" alias="localhost" default-web-module="keycloak-server.war">
            <location name="/" handler="welcome-content"/>
        </host>
]]></programlisting>
        </para>
        <para>
            <literal>keycloak-server.war</literal> is the runtime name of the Keycloak server application. Note that the WAR file does not exist as a file. If its name changes (ie. <literal>keycloak-server.war</literal>) in the future, find its new name from the Keycloak log entry with <literal>runtime-name:</literal>.
        </para>
        <para>
             <note>
                 If you have run your server before altering the root context, your database
                 will contain references to the old /auth context. Your clients may also have incorrect
                 references.  To fix this on the server side, you will need to <link linkend="export-import">export
                 your database to json, make corrections, and then import.</link>  Client-side keycloak.json
                 files will need to be updated manually as well.
             </note>
        </para>

    </section>
</chapter>
