Keycloak is a comprehensive and free open source identity provider. It is also offered in numerous Docker variants, which makes deployment very easy.

Access to the shell is necessary for the configuration, e.g. if the first user has to be created or the backend and frontend have to use the same URL. If the container is executed in an Azure Container Instance, shell access is not a problem. But with an Azure App Service, an installed and configured SSH server on port 2222 is expected.

Install SSH

The installation of an SSH server is a bit challenging. On the one hand, the standard Red Hat package provider microdnf does not provide all packages; on the other hand, Keycloak should run under a Keycloak user, but the SSH server must run with root permission.

The following lines of the Dockerfile installs the package manager YUM and installs the SSH Server and configure some file and folder access. The SSH configuration file is copied into the container a few lines before.

ENV SSH_PASSWD "root:Docker!"
RUN microdnf -y install yum && yum install -y procps && yum install -y openssh && yum install -y wget \
      && cd /tmp/setup/ssh/ && wget https://rpmfind.net/linux/centos/8/BaseOS/x86_64/os/Packages/openssh-server-8.0p1-10.el8.x86_64.rpm \
      && yum install -y openssh-server-8.0p1-10.el8.x86_64.rpm \
      && cp /tmp/setup/ssh/sshd_config /etc/ssh/ \
      && echo "$SSH_PASSWD" | chpasswd \
      && cd /etc/ssh/ && ssh-keygen -A \
      && chmod 600 /etc/ssh/* \
      && chmod 644 /etc/ssh/*.pub \
      && chmod 700 /etc/ssh

The SSH Server is started in the entrypoint.sh file at line 12. It using the su command and providing the configured root password to run SSH in line 14 as root:

# start ssh as root
su - root <<!
Docker!
/usr/sbin/sshd
!

Configure Frontend-URL at Runtime

After the deployment within the App Service, the container listens to http://localhost:8080 by default and tries to resolve links there as well. The path must be adapted to the URL of the App Service (or maybe to an Azure Application Gateway).

The configuration in the portal can be carried out directly via the SSH shell in the browser:

/opt/jboss/keycloak/bin/jboss-cli.sh --connect
/subsystem=keycloak-server/spi=hostname/provider=default:write-attribute(name=properties.frontendUrl,value="https://<YOUR-APP-SERVICE-NAME>.azurewebsites.net/auth/")
/subsystem=keycloak-server/spi=hostname/provider=default:write-attribute(name=properties.forceBackendUrlToFrontendUrl,value="true")
:reload

Line 2 configures the frontend URL and Line 3 forces that frontend and backend are using the same URL.

Configure Frontend-URL at Docker-Build-Time

In many cases the URL should be configured in the container during the build. The URL can be set as an environment variable in the container (line 8) and the usage can be activated in line 7:

ENV PROXY_ADDRESS_FORWARDING=false
ENV FRONTEND_URL=https://<YOUR-APP-SERVICE-NAME>.azurewebsites.net/auth/

This sets the environment variable for the frontend URL in line 5 in entrypoint.sh, which Keycloak evaluates when it starts. if the frontend and backend should use the same URL, it needs to be adjusted in the standalone.xml (see line 6). Unfortunately, this property can only be defined in the standalone.xml, as Keycloak cannot evaluate it as an environment variable:

if [ ${PROXY_ADDRESS_FORWARDING} = true ];
then
    export JAVA_OPTS_APPEND="-Dkeycloak.frontendUrl=${FRONTEND_URL}" 
    sed -i 's/name="forceBackendUrlToFrontendUrl" value="false"/name="forceBackendUrlToFrontendUrl" value="true"/' /opt/jboss/keycloak/standalone/configuration/standalone.xml
fi;

Creating the first User and Master-Realm

If there is not yet a database with existing data or the conatiner uses the in-memory database and is empty again after a restart, the first user and the master realm must be created. The SSH shell in the browser can also be used for this:

/opt/jboss/keycloak/bin/add-user-keycloak.sh -u 'myadmin' -p 'P@ssw0rd'
/opt/jboss/keycloak/bin/jboss-cli.sh --connect command=:reload