Skip to content

Keycloak Setup for Production

Adrian Matei edited this page Jun 1, 2020 · 6 revisions

In this guide I present the extra steps I had to take to prepare Keycloak to run in production and support https://www.bookmarks.dev Single-Sign On.

Before reading this guide it is recommended your read the wiki entry Keycloak MySQL Setup


Ok, now that we have Keycloak installed and running on top of MySQL, we would like also to:

  1. Enable HTTPS/SSL with a Reverse Proxy
  2. Run Keycloak as a service

Setting up a Proxy

To set up the proxy please see the sister wiki page - Nginx Setup in Production

Beyond the proxy itself, there are a few things we need to configure on the Keycloak side of things. Our proxy is forwarding requests via the HTTP protocol, so we need to configure Keycloak to pull the client’s IP address from the X-Forwarded-For header rather than from the network packet. To do this, we open up the profile configuration file standalone.xml and look for the urn:jboss:domain:undertow:3.0 XML block. It should now look like the following:

<subsystem xmlns="urn:jboss:domain:undertow:3.0">
   <buffer-cache name="default"/>
   <server name="default-server">
      <ajp-listener name="ajp" socket-binding="ajp"/>
      <http-listener name="default" socket-binding="http" redirect-socket="https"
          proxy-address-forwarding="true"/>
      ...
   </server>
   ...
</subsystem>

We've added the proxy-address-forwarding attribute to the http-listener element and set its value to true.

Enable HTTPS/SSL with a Reverse Proxy

Assuming that your reverse proxy doesn’t use port 8443 for SSL you also need to configure what port HTTPS traffic is redirected to.

<subsystem xmlns="urn:jboss:domain:undertow:3.0">
    ...
    <http-listener name="default" socket-binding="http"
        proxy-address-forwarding="true" redirect-socket="proxy-https"/>
    ...
</subsystem>

Add the redirect-socket attribute to the http-listener element. The value should be proxy-https which points to a socket binding you also need to define.

Then add a new socket-binding element to the socket-binding-group element:

<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>

Start Keycloak/Wildfly as a service

Keycloak/Wildfly comes with different **user contributed scripts & services ** for running WildFly as a service on various operating systems:

In the v3.1.0 distribution you can find them at KEYCLOAK_HOME/docs/contrib/scripts:

$ ls -lrt /opt/keycloak/docs/contrib/scripts
total 16
drwxr-xr-x 2 wildfly wildfly 4096 May  3 06:10 systemd
drwxr-xr-x 3 wildfly wildfly 4096 May  3 06:10 service
-rw-r--r-- 1 wildfly wildfly 1446 May  3 06:10 README.md
drwxr-xr-x 2 wildfly wildfly 4096 May  3 06:10 init.d

In this guide we use the init.d variant.

$ ls -lrt /opt/keycloak/docs/contrib/scripts/init.d
total 20
-rwxr-xr-x 1 wildfly wildfly 4681 May  3 06:10 wildfly-init-redhat.sh
-rwxr-xr-x 1 wildfly wildfly 7122 May  3 06:10 wildfly-init-debian.sh
-rw-r--r-- 1 wildfly wildfly  854 May  3 06:10 wildfly.conf

We will copy the wildfly.conf file to the default location - /etc/default/wildfly and edit with our own configuration data:

$ sudo cp /opt/keycloak/docs/contrib/scripts/init.d/wildfly.conf /etc/default/wildfly
$ sudo vim /etc/default/wildfly

We will have the following content:

# General configuration for the init.d scripts,
# not necessarily for JBoss AS itself.
# default location: /etc/default/wildfly

## Location of JDK
 JAVA_HOME="/usr/lib/jvm/java-8-oracle"

## Location of WildFly
JBOSS_HOME="/opt/keycloak"

## The username who should own the process.
JBOSS_USER=wildfly

## The mode WildFly should start, standalone or domain
JBOSS_MODE=standalone

## Configuration for standalone mode
JBOSS_CONFIG=standalone.xml

## Configuration for domain mode
# JBOSS_DOMAIN_CONFIG=domain.xml
# JBOSS_HOST_CONFIG=host-master.xml

## The amount of time to wait for startup
STARTUP_WAIT=60

## The amount of time to wait for shutdown
SHUTDOWN_WAIT=60

## Location to keep the console log
JBOSS_CONSOLE_LOG="/var/log/wildfly/console.log"

## Additionals args to include in startup
# JBOSS_OPTS="--admin-only -b 127.0.0.1"

Then we need to provide an init script to the init.d system. We take the debian version since our server is running on Ubuntu:

$ sudo cp /opt/keycloak/docs/contrib/scripts/init.d/wildfly-init-debian.sh /etc/init.d/wildfly

We are now going to create an user account for keycloak/wildfly. We name it wildfly - we have enough Keycloak users already :).

You can see we had already made up our mind in the /etc/default/wildfly file - JBOSS_USER=wildfly

Ok, so now let's add the user:

$ sudo adduser --system --group --no-create-home --disabled-password --disabled-login wildfly 

We now run update-rc.d to ensure wildfly starts on reboot:

$ sudo update-rc.d wildfly defaults

Finally we change the owner of keycloak/jboss home folder and log directory:

$ sudo chown -R wildfly:wildfly /var/log/wildfly/
$ sudo chown -R wildfly:wildfly /opt/keycloak-3.1.0.Final/

We can now also start and stop the Keycloak Server with the following commands:

$ sudo service wildfly start
$ sudo service wildfly stop

I defined two aliases for these commands and some other. See below an extract from my ~/.bash_aliases file with Keycloak related aliases:

alias keycloak-cd-home='cd /opt/keycloak/'
alias keycloak-start='sudo service wildfly start'
alias keycloak-stop='sudo service wildfly stop'
alias keycloak-tail-server.log='sudo tail -f -n900 /opt/keycloak/standalone/log/server.log'
alias keycloak-vim-standalone.xml='sudo vim /opt/keycloak/standalone/configuration/standalone.xml'
alias mysql-backup-keycloak-prod='mysqldump keycloak -u keycloak -p -h 127.0.0.1 --port 3306 --single-transaction > ~/backup/db/keycloak_db_prod_$(date "+%Y-%m-%d_%H:%M").sql'

Check out my post - A developer's guide to using aliases, to learn more about my philosophy of using aliases.

In this guide we've seen how to configure Keycloak to accept requests from an SSL enabled reverse proxy and how to run Keycloak as a service via init.d.

References