Installing and running Keycloak standalone on Ubuntu 20.04

Install OpenJDK

https://jdk.java.net/17/

Or

https://linoxide.com/install-java-ubuntu-20-04/

sudo apt install openjdk-16-jdk

Install mariadb

c.f. https://www.janua.fr/how-to-install-keycloak-with-mariadb/

sudo apt install mariadb-server mariadb-client

(...)

sudo mysql_secure_installation

Add new database and user for keycloak

create database keycloak;
create user keycloak identified by "PASSWORD";
grant all privileges on keycloak.* to 'keycloak'@'localhost' identified by "PASSWORD";

Download and deploy keycloak

Create keycloak user

sudo useradd -r keycloak

Download keycloak.

https://www.keycloak.org/downloads.html

Download keycloak

wget https://github.com/keycloak/keycloak/releases/download/15.0.2/keycloak-15.0.2.tar.gz

tar zxvf keycloak-15.0.2.tar.gz

mv keycloak-15.0.2 /opt/

sudo chown -R keycloak:keycloak keycloak-15.0.2
sudo ln -s /opt/keycloak-15.0.2 /opt/keycloak

Prepare Keycloak for mariadb

Official manual

https://www.keycloak.org/docs/latest/server_installation/index.html#_database

c.f.
https://devopstales.github.io/sso/keycloak1/

Download JDBC connector

https://downloads.mariadb.org/connector-java/

Put the connector in keycloak modules folder:

sudo -u keycloak mkdir -p /opt/keycloak/modules/system/layers/keycloak/org/mariadb/main/

sudo -u keycloak cp mariadb-java-client-x.x.x.jar /opt/keycloak/modules/system/layers/keycloak/org/mariadb/main/

Create module.xml in the same folder:

sudo -u keycloak vim /opt/keycloak/modules/system/layers/keycloak/org/mariadb/main/module.xml

with the content:

<?xml version="1.0" ?>
<module xmlns="urn:jboss:module:1.3" name="org.mariadb">

    <resources>
        <resource-root path="mariadb-java-client-2.7.3.jar"/>
    </resources>

    <dependencies>
        <module name="javax.api"/>
        <module name="javax.transaction.api"/>
    </dependencies>
</module>

Make sure /opt/keyalock/ is owned by keycloak:keycloak user:

sudo chown -R keycloak:keycloak /opt/keycloak/

Add admin user

sudo -u keycloak /opt/keycloak/bin/add-user.sh

What type of user do you wish to add? 
 a) Management User (mgmt-users.properties) 
 b) Application User (application-users.properties)
(a): 

Enter the details of the new user to add.
Using realm 'ManagementRealm' as discovered from the existing property files.
Username : admin
User 'admin' already exists and is disabled, would you like to... 
 a) Update the existing user password and roles 
 b) Enable the existing user 
 c) Type a new username
(a): c
Username (admin) : admin-user    
Password recommendations are listed below. To modify these restrictions edit the add-user.properties configuration file.
 - The password should be different from the username
 - The password should not be one of the following restricted values {root, admin, administrator}
 - The password should contain at least 8 characters, 1 alphabetic character(s), 1 digit(s), 1 non-alphanumeric symbol(s)
Password : 
Re-enter Password : 
What groups do you want this user to belong to? (Please enter a comma separated list, or leave blank for none)[  ]: admin
About to add user 'admin-user' for realm 'ManagementRealm'
Is this correct yes/no? yes
Added user 'admin-user' to file '/opt/keycloak-15.0.2/standalone/configuration/mgmt-users.properties'
Added user 'admin-user' to file '/opt/keycloak-15.0.2/domain/configuration/mgmt-users.properties'
Added user 'admin-user' with groups admin to file '/opt/keycloak-15.0.2/standalone/configuration/mgmt-groups.properties'
Added user 'admin-user' with groups admin to file '/opt/keycloak-15.0.2/domain/configuration/mgmt-groups.properties'
Is this new user going to be used for one AS process to connect to another AS process? 
e.g. for a slave host controller connecting to the master or for a Remoting connection for server to server Jakarta Enterprise Beans calls.
yes/no? yes
To represent the user add the following to the server-identities definition <secret value="*****SECRET VALUE******" />

Prepare first admin user

sudo -u keycloak /opt/keycloak/bin/add-user-keycloak.sh -u admin

# Configure password for your Keycloak admin user

Configure wildfly for mysql

cd /opt/keycloak/

./bin/jboss-cli.sh -c 'module add --name=org.mysql  --dependencies=javax.api,javax.transaction.api --resources=/opt/mysql-connector-java-5.1.47/mysql-connector-java-5.1.47.jar'

./bin/jboss-cli.sh 'embed-server,/subsystem=datasources/jdbc-driver=org.mysql:add(driver-name=org.mysql,driver-module-name=org.mysql,driver-class-name=com.mysql.jdbc.Driver)'

./bin/jboss-cli.sh 'embed-server,/subsystem=datasources/data-source=KeycloakDS:remove'

./bin/jboss-cli.sh 'embed-server,/subsystem=datasources/data-source=KeycloakDS:add(driver-name=org.mysql,enabled=true,use-java-context=true,connection-url="jdbc:mysql://localhost:3306/keycloak?useSSL=false&useLegacyDatetimeCode=false&serverTimezone=Europe/Budapest&characterEncoding=UTF-8",jndi-name="java:/jboss/datasources/KeycloakDS",user-name=keycloak,password="Password1",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.MySQLValidConnectionChecker)'

./bin/add-user-keycloak.sh -u admin -p Password1 -r master

# for nginx proxy
./bin/jboss-cli.sh 'embed-server,/subsystem=undertow/server=default-server/http-listener=default:write-attribute(name=proxy-address-forwarding,value=true)'

./bin/jboss-cli.sh 'embed-server,/socket-binding-group=standard-sockets/socket-binding=proxy-https:add(port=443)'

./bin/jboss-cli.sh 'embed-server,/subsystem=undertow/server=default-server/http-listener=default:write-attribute(name=redirect-socket,value=proxy-https)'

# disabla color in log
./bin/jboss-cli.sh -c '/subsystem=logging/console-handler=CONSOLE:write-attribute(name=named-formatter, value=PATTERN)'

Launch keycloak

Make sure your server 8443 port is open to internet as the 8443 port is the default port of Keycloak.

sudo -u keycloak /opt/keycloak/bin/standalone.sh -b 0.0.0.0

Launching Keycloak

Put Keycloak behind Nginx reverse proxy

Install nginx

sudo apt install nginx

Configure nginx for Keycloak. First with HTTP config:

server{

    listen 80 default_server;
    listen [::]:80 default_server;

    server_name DOMAIN-NAME-OR-IP-ADDRESS-OF-SERVER;

    location / {
            proxy_pass http://0.0.0.0:8080; # keycloak runs on port 8080 by default
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header X-Forwarded-For $proxy_protocol_addr;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
    }
}

Install certbot and let's encrypt for SSL

YOU NEED DOMAIN TO CONFIGURE SSL. FIRST PREPARE DOMAIN FOR YOUR KEYCLOAK SERVER

Change nginx config (assign domain)

vim /etc/nginx/sites-available/keycloak.conf

server {

        server_name keycloaktest.minamirnd.work;

        location / {
           proxy_http_version 1.1;

           proxy_set_header        Host               $http_host;
           proxy_set_header        X-Forwarded-For    $proxy_add_x_forwarded_for;
           proxy_set_header        X-Real-IP          $remote_addr;
           proxy_set_header        X-Forwarded-Proto  $scheme;
           proxy_set_header        X-Forwarded-Port   8443;
           add_header              Strict-Transport-Security "max-age=15552000";

           proxy_set_header X-NginX-Proxy true;
           proxy_set_header Upgrade $http_upgrade;
           proxy_set_header Connection "upgrade";

           proxy_pass  https://127.0.0.1:8443/;
           proxy_redirect     off;
        }
}
server {
    server_name keycloaktest.minamirnd.work;

    listen [::]:80;
    listen 80;
}

Configure /opt/keycloak/standalone/configuration/standalone.xml so that reverse proxy work.
(c.f. https://gist.github.com/zahash/16405257d1e78ae1435497144eb94333)

# change redirect-socket to "proxy-https" and add proxy-address-forwarding="true"

<http-listener name="default" socket-binding="http" redirect-socket="proxy-https" enable-http2="true" proxy-address-forwarding="true"/>

# add socket-binding "proxy-https"

<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
  (...)
  <socket-binding name="proxy-https" port="443"/>
  (...)

https://certbot.eff.org/

sudo apt install snapd

sudo snap install core; sudo snap refresh core

sudo snap install --classic certbot

Install Let's Encrypt certificate:

minami@ip-10-0-38-61:~$ sudo certbot
Saving debug log to /var/log/letsencrypt/letsencrypt.log

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: your-keycloak.domain.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 
Requesting a certificate for keycloaktest.minamirnd.work

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/your-keycloak.domain.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/your-keycloak.domain.com/privkey.pem
This certificate expires on 2021-12-18.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

Deploying certificate
Successfully deployed certificate for your-keycloak.domain.com to /etc/nginx/sites-enabled/keycloak.conf
Congratulations! You have successfully enabled HTTPS on https://your-keycloak.domain.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le

After successfully configured letsencrypt, re-configure nginx conf file:

server {

        server_name keycloaktest.minamirnd.work;

        location / {
            proxy_pass http://0.0.0.0:8080; # keycloak runs on port 8080 by default
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header X-Forwarded-For $proxy_protocol_addr;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;

        }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/your-keycloak.domain.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/your-keycloak.domain.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {
    if ($host = keycloaktest.minamirnd.work) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    server_name your-keycloak.domain.com;
    listen 80;
    return 404; # managed by Certbot

}

Restart nginx:

# Check conf
sudo nginx -t

# Restart nginx
sudo service nginx restart

Make sure keycloak's standalone.sh is running:

cd /opt/keycloak/
sudo -u keycloak ./bin/standalone.sh -b 0.0.0.0

Access https://your.domain.com/ with no :8443 port specified

Configure Keycloak service

Locate wildfly configuration example files in:

ls -l /opt/keycloak/docs/contrib/scripts/init.d/

# wildfly-init-debian.sh
# wildfly-init-redhat.sh
# wildfly.conf

Copy the files

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

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

Edit the default configuration

sudo vim /etc/default/keycloak.conf

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

## Location of JDK
# JAVA_HOME="/usr/lib/jvm/default-java"
JAVA_HOME="/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.282.b08-1.amzn2.0.1.x86_64/jre"

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

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

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

## Configuration for standalone mode
# JBOSS_CONFIG=standalone.xml
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
STARTUP_WAIT=60

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

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

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

Change "wildfly" in init.d script

sudo vim /etc/init.d/keycloak

# replace "wildfly" to "keycloak"
# e.g.
(...)

# Run as keycloak user
if [ -z "$JBOSS_USER" ]; then
        JBOSS_USER=keycloak
fi

(...)

# Location to set the pid file
if [ -z "$JBOSS_PIDFILE" ]; then
        JBOSS_PIDFILE=/var/run/keycloak/${NAME}.pid
fi
export JBOSS_PIDFILE

Start init.d

sudo /etc/init.d/keycloak start

Access https://your.domain.com/


Links to other documents / blogs:

Leave a Reply

Your email address will not be published. Required fields are marked *