6 min read

How to install Keycloak on Azure

How to install Keycloak on Azure

Keycloak is an open-source identity and access management (IAM) solution developed by Red Hat. This article covers how to install and configure Keycloak server in Azure.

To accomplish this, let's separate it into the following steps:

  • Create a database
  • Create a virtual machine
  • Install and configure Keycloak on the virtual machine
  • Install and configure Nginx on the virtual machine
  • Cloudflare configuration
The entire process will be done using the Azure CLI. You can click here if you need to install it.

To keep things organized, let's start by creating the resource group where all the created resources (such as virtual machine, database...) will be. To do this, we're going to use the az group create command.

LOCATION=eastus
RESOURCE_GROUP=rg-keycloak
az group create \
  --location $LOCATION \
  --name $RESOURCE_GROUP

Creating a database for Keycloak

The Keycloak server has built-in support for different databases and for this article we have chosen PostgreSQL.

You can click here to check out all the databases that Keycloak supports.

The creation of the database is done in two steps. First, let's create the database server. To do this, use the az postgres flexible-server create command. This may take a few minutes to complete.

The public access argument (0.0.0.0) configures the firewall to allow connections from IP addresses allocated to any Azure service
POSTGRES_SERVER_NAME=pgsql-keycloak
POSTGRES_TIER=Burstable
POSTGRES_SKU=Standard_B1ms
POSTGRES_ADMIN_USER=keycloak
POSTGRES_ADMIN_PASSWORD=keycloak
POSTGRES_STORAGE_SIZE=32
POSTGRES_VERSION=16
POSTGRES_PUBLIC_ACCESS_IP=0.0.0.0 
az postgres flexible-server create \
  --resource-group $RESOURCE_GROUP \
  --name $POSTGRES_SERVER_NAME \
  --tier $POSTGRES_TIER \
  --sku-name $POSTGRES_SKU \
  --admin-user $POSTGRES_ADMIN_USER \
  --admin-password $POSTGRES_ADMIN_PASSWORD \
  --storage-size $POSTGRES_STORAGE_SIZE \
  --version $POSTGRES_VERSION \
  --location $LOCATION \
  --public-access $POSTGRES_PUBLIC_ACCESS_IP

Once the creation of the database server is finished, create the database. Use the az postgres flexible-server db create command for this.

DATABASE_NAME=keycloak
az postgres flexible-server db create \
  --resource-group $RESOURCE_GROUP \
  --server-name $POSTGRES_SERVER_NAME \
  --database-name $DATABASE_NAME

The database setup is complete.

Creating the virtual machine

Now, let's create a virtual machine where Keycloak will be installed. The az vm create command is used for this.

VM_NAME=vm-keycloak
VM_IMAGE=Ubuntu2204
VM_SIZE=Standard_B1s
VM_ADMIN_USERNAME=keycloak
VM_ADMIN_PASSWORD=Keycloak@000
az vm create \
  --resource-group $RESOURCE_GROUP \
  --name $VM_NAME \
  --image $VM_IMAGE \
  --size $VM_SIZE \
  --admin-username $VM_ADMIN_USERNAME \
  --admin-password $VM_ADMIN_PASSWORD

After the virtual machine is created, use the az vm open-port command to open the port 443. This will be required for external access over HTTPS.

az vm open-port \
    --resource-group rg-keycloak \
    --name vm-keycloak \
    --port 443

Now, configure the DNS name of the virtual machine. This will be used to add a CNAME record in Cloudflare later. First, use the az vm list-ip-addresses command to get the public ip name. Next, use the az network public-ip update command to set the DNS name.

PUBLIC_IP_NAME=$(az vm list-ip-addresses \
  --resource-group $RESOURCE_GROUP \
  --name $VM_NAME \
  --query "[].virtualMachine.network.publicIpAddresses[0].name" \
  --output tsv)

PUBLIC_IP_DNS_NAME=vm-keycloak
az network public-ip update \
  --resource-group $RESOURCE_GROUP \
  --name $PUBLIC_IP_NAME \
  --dns-name $PUBLIC_IP_DNS_NAME

The virtual machine setup is complete.

Keycloak installation

Now, connect to the virtual machine using the ssh command and the password Keycloak@000 (previously defined).

VM_DNS_NAME=$(az network public-ip show \
  --resource-group $RESOURCE_GROUP \
  --name $PUBLIC_IP_NAME \
  --query "dnsSettings.fqdn" \
  --output tsv)
ssh $VM_ADMIN_USERNAME@$VM_DNS_NAME

Installing Java is a prerequisite for installing Keycloak. The currently recommended version is Java 17.

JAVA_VERSION=openjdk-17-jdk
sudo apt update
sudo apt install -y $JAVA_VERSION

Now, download and extract the Keycloak files. The latest version currently available is 23.0.2, but you can click here to see if there is a newer version.

KEYCLOAK_VERSION=23.0.2
wget https://github.com/keycloak/keycloak/releases/download/$KEYCLOAK_VERSION/keycloak-$KEYCLOAK_VERSION.tar.gz
tar -xvzf keycloak-$KEYCLOAK_VERSION.tar.gz
sudo mv keycloak-$KEYCLOAK_VERSION /opt/keycloak

Now, edit the Keycloak configuration file.

sudo nano /opt/keycloak/conf/keycloak.conf
  • Configure the database connection
  • Configure the proxy mode
  • Configure the hostname

The configuration should look like the example below:

db=postgres
db-username=keycloak
db-password=keycloak
db-url=jdbc:postgresql://pgsql-keycloak.postgres.database.azure.com/keycloak
proxy=edge
hostname=keycloak.enjoycoding.dev

Save and exit the file.

Now, run the Keycloak build command. This command performs a set of optimizations for the startup and runtime behavior. You can click here for details.

sudo /opt/keycloak/bin/kc.sh build

After the build finishes, start Keycloak to create the admin user using environment variables.

💡
The "-E" argument is required to preserve user environment when running the command
export KEYCLOAK_ADMIN="admin"
export KEYCLOAK_ADMIN_PASSWORD="admin"
sudo -E /opt/keycloak/bin/kc.sh start

You can stop the service (Control + C) when a log like the one below appears.

INFO  [org.keycloak.services] (main) KC-SERVICES0009: Added user 'admin' to realm 'master'

Now, configure Keycloak to run as a service. Create a new service file definition.

sudo nano /etc/systemd/system/keycloak.service

With the content below:

[Unit]
Description=The Keycloak Server
After=syslog.target network.target
Before=httpd.service
[Service]
Environment=LAUNCH_JBOSS_IN_BACKGROUND=1
EnvironmentFile=/opt/keycloak/conf/keycloak.conf
User=keycloak
Group=keycloak
LimitNOFILE=102642
PIDFile=/var/run/keycloak/keycloak.pid
ExecStart=/opt/keycloak/bin/kc.sh start --optimized
StandardOutput=null
[Install]
WantedBy=multi-user.target

Save and exit the file.

Reload systemd manager configuration and enable Keycloak service on system startup.

sudo systemctl daemon-reload
sudo systemctl enable keycloak

Start Keycloak system service.

sudo systemctl start keycloak

Once the service starts, you can check the status by running the command below:

sudo systemctl status keycloak

And the Keycloak configuration is complete.

Cloudflare configuration

Log in to your Cloudflare account and select the domain you want to use with Keycloak. Now, add a CNAME record.

For the CNAME target value, use the DNS name of the virtual machine. You can use the command below to get it.

az network public-ip show \
  --resource-group $RESOURCE_GROUP \
  --name $PUBLIC_IP_NAME \
  --query "dnsSettings.fqdn"

This is how the CNAME record is configured with the DNS name that we used in the virtual machine in the previous steps:
name: keycloak
target: vm-keycloak.eastus.cloudapp.azure.com

You can click here for details about how to add CNAME records.

Now, let's create an Origin Certificate to encrypt traffic between Cloudflare and the origin web server, aka, our virtual machine.

  • In the left menu, expand the "SSL/TLS" option and click the "Origin Server" option
  • Click on "Create Certificate"
  • In the "Hostnames" input, remove the values, type the CNAME name from previous step, and pick the value from the suggestion. With the values used in this article, it looks like this: keycloak.enjoycoding.dev
  • Click "Create"
You can click here for details about how to create Origin Certificates.

Now, let's save the certificate and private key to the virtual machine.

First, create a new file and paste the Origin Certificate from Cloudflare.

sudo nano /etc/ssl/certs/cloudflare_origin.cert

Now, create a new file and paste the Private Key from Cloudflare.

sudo nano /etc/ssl/private/cloudflare_origin.key

And the Cloudflare configuration is complete.

Installing Nginx

And the last step (🙌) is to install and configure Nginx. Use the following command to install it.

sudo apt install -y nginx

Now, open the Nginx configuration file.

sudo nano /etc/nginx/sites-enabled/default 

Here's what the Nginx configuration should look like:

upstream keycloak {
    server localhost:8080;
}

server {
    listen 80;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_certificate /etc/ssl/certs/cloudflare_origin.cert;
    ssl_certificate_key /etc/ssl/private/cloudflare_origin.key;

    proxy_set_header    Host               $host;
    proxy_set_header    X-Real-IP          $remote_addr;
    proxy_set_header    X-Forwarded-For    $proxy_add_x_forwarded_for;
    proxy_set_header    X-Forwarded-Host   $host;
    proxy_set_header    X-Forwarded-Server $host;
    proxy_set_header    X-Forwarded-Port   $server_port;
    proxy_set_header    X-Forwarded-Proto  $scheme;

    location / {
        proxy_pass http://keycloak;
    }
}

Save and exit the file.

Finally, restart the Nginx service.

sudo service nginx restart

And the Nginx configuration is complete.

Conclusion

And that's it.

Now, you should be able to access the Keycloak web interface using the configured hostname (keycloak.enjoycoding.dev, in my case).

If you have any questions, feel free to comment.

For more details, click on the link below to access the official documentation

Documentation - Keycloak
Keycloak is an open source identity and access management solution