Keycloak is an Access Management System which can be used for single sign-on, social login, user federation, etc. In a nutshell, it's a tool that can be used to manage user authentication and authorization for free. It's open source, and the source code can be accessed from its GitHub repository.
Identity Verification with Keycloak
It supports authentication mechanisms like username/password, social login, SAML, etc. When a user signs up for an application with Keycloak integrated, a unique identifier is provided, which can be used to identify our user. Whenever the user logs in, an access token is issued along with a refresh token. The access token contains information about the user, like their ID, permissions, roles, etc.
To administer Keycloak, a web console is provided, which allows managing users and their roles and permissions. It also provides a feature to impersonate the user and access applications. This is especially useful when debugging.
Keycloak can also be configured for users to log in via Google, Facebook, etc. Anything that uses the OpenID protocol is compatible to be used with Keycloak.
Related article: Identity and Access Management for Microservices with Keycloak
Deploying Keycloak
To deploy Keycloak, we will need to do a few things, and they are:
Configure Nginx reverse proxy
Create an Nginx virtual host configuration in the sites-available directory.
server {
proxy_read_timeout 600s;
proxy_connect_timeout 600s;
proxy_send_timeout 600s;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
server_name keycloak.example.com;
listen [::]:443 ssl;
listen 443 ssl;
location / {
proxy_pass http://127.0.0.1:8080; #we'll host keycloak at localhost:8080
include proxy_params;
}
ssl_certificate /home/ubuntu/keycloak/certs/full-chain.crt;
ssl_certificate_key /home/ubuntu/keycloak/certs/privkey.pem;
#These are provided by certbot, if you're sourcing the certificate from sources other than certbot, remove these two lines below.
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
Nginx configuration
Now, symlink this file to the sites-enabled directory using the following command:
ln -s /etc/nginx/sites-available/keycloak.example.com /etc/nginx/sites-enabled
Symlink Keycloak configuration in sites-available to sites-enabled
In the nginx.conf
file, add the following line inside the http block.
include /etc/nginx/sites-enabled/*;
Entry to be added inside http block in nginx.conf
This will make sure that Nginx reads the configuration from the sites-enabled directory, where we have saved the Keycloak hosting config.
Provision SSL certificates
Let's generate SSL certificates for the Keycloak server. I will use Let's Encrypt as my CA and Certbot to generate and manage my certificates.
In the server, install Certbot.
sudo apt update && sudo apt install certbot
Installing Certbot
Make sure you have a domain name pointing towards your server. To verify, you can simply use nslookup
and dig
.
First, check the public IP of your server. Here, I'm using the example.com
domain for reference purposes only. Your domain will be different from mine. We will send an http request to icanhazip.com
to check our public IPV4 address using curl
.
Run the following command from inside the server.
curl icanhazip.com
To check public IPV4 address
Now run the following:
nslookup keycloak.example.com
To check the IPV4 address of the domain name
This will provide the IP address of the domain name.
Finally, we'll generate our SSL certificates.
certbot --nginx --register-unsafely-without-email
Command to generate SSL certificates
You can remove the --register-unsafely-without-email
flag to use an email address. The email address will be used to provide expiry notices and other important information related to your SSL certificates.
The generation command should be interactive enough for you to understand and follow the provided instructions.
Once your certificate is generated, Certbot will automatically edit the Nginx config you used for cert generation purposes with the path to our SSL certificates.
Now, we need to copy the certificate and the private key from the Let's Encrypt directory to the certs directory to mount it inside our Keycloak Docker container for a production-ready deployment.
Create the directory if you have not done yet.
mkdir $PWD/certs .
Generating directory
Copy the certificate using the following command:
sudo cp /etc/ssl/letsencrypt/keycloak.example.com/full-chain.crt /etc/ssl/letsencrypt/keycloak.example.com/privkey.key $PWD/certs/
Copying the certificates from Let's Encrypt directory to the certs directory
We could've just mounted the certificate from the Let's Encrypt directory, but the reason we've copied it is due to our Keycloak container running as the non-root keycloak
user. This means the certificate files should also come under the ownership of Keycloak with full read/write permissions. Otherwise, the Keycloak user will be unable to read our certificate files, and thus the Keycloak container will fail to start in production mode.
Let's change the ownership and modify the permissions of the certificate files.
sudo chown -R keycloak:keycloak $PWD/certs
Changing certificate ownership to Keycloak user
sudo chmod -R 660 $PWD/certs
Changing certificate permissions
Host Keycloak
We're now finally ready to host our Keycloak instance. We will use Docker Compose for this, as it's much easier to set up networking between containers.
Our compose file will consist of two services; One is a Postgres database, and the other is Keycloak, provided by Bitnami.
Copy and paste the contents below to a docker-compose.yml
file.
version: '3.9'
services:
postgres:
image: postgres:15.1-alpine
container_name: postgres-keycloak
restart: always
env_file:
- .env
volumes:
- postgres-kc:/var/lib/postgresql/data
networks:
- keycloak-and-pg-network
keycloak-w:
image: bitnami/keycloak:21.0.2
ports:
- "8080:8080"
restart: unless-stopped
volumes:
- {PWD}/certs:/opt/bitnami/keycloak/certs:ro
env_file:
- .env
depends_on:
- dev-db-kc-prod
networks:
- keycloak-and-pg-network
volumes:
postgres-kc:
name: pg-data-kc
networks:
keycloak-and-pg-network:
name: kc-pg-network
Compose Keycloak file
Certain environment variables need to be provided to our containers, so copy the following contents and paste them into a .env
file.
DB_HOST=postgres
DB_PORT=5432
DB_SCHEMA=public
POSTGRES_DB=keycloak
POSTGRES_USER=yb_keycloak
POSTGRES_PASSWORD=randomlongalphanumericpassword
KEYCLOAK_CREATE_ADMIN_USER=true
KEYCLOAK_ADMIN_USER=keycloak-admin
KEYCLOAK_ADMIN_PASSWORD=randomlongalphanumericpassword
KEYCLOAK_MANAGEMENT_USER=keycloak-manager
KEYCLOAK_MANAGEMENT_PASSWORD=randomlongalphanumericpassword
KEYCLOAK_DATABASE_HOST=${DB_HOST}
KEYCLOAK_DATABASE_PORT=${DB_PORT}
KEYCLOAK_DATABASE_NAME=${POSTGRES_DB}
KEYCLOAK_DATABASE_USER=${POSTGRES_USER}
KEYCLOAK_DATABASE_PASSWORD=${POSTGRES_PASSWORD}
KEYCLOAK_DATABASE_SCHEMA=${DB_SCHEMA}
KEYCLOAK_PRODUCTION=true
KEYCLOAK_JDBC_PARAMS=sslmode=disable&connectTimeout=40000
KEYCLOAK_EXTRA_ARGS="-Dkeycloak.profile.feature.scripts=enabled"
KEYCLOAK_ENABLE_HTTPS=true
KEYCLOAK_HTTPS_USE_PEM=true
KEYCLOAK_HTTPS_CERTIFICATE_FILE=/opt/bitnami/keycloak/certs/fullchain.pem
KEYCLOAK_HTTPS_CERTIFICATE_KEY_FILE=/opt/bitnami/keycloak/certs/privkey.pem
Compose .env
file
Now, from the root of the Keycloak project folder (or wherever you've saved the certs, compose, and env file), run the following command to start the Keycloak and Postgres instance.
docker compose -f docker-compose.yml up -d
Compose command to run Keycloak
To check logs, simply run the following:
docker compose -f docker-compose.yml logs -f
Compose command to view logs
Also read: Load Balancing with Nginx
Frequently Asked Questions (FAQs)
Why are the SSL certificates not being recognized by Keycloak?
Make sure you have changed the SSL certificate file owners to the Keycloak user. If a user is not present, then create a user on the host machine with adduser keycloak
and run the chown keycloak:keycloak
command on the SSL Certificate files.
Also, ensure that read/write permission is provided on the certificate files. Try giving full permission to owner
, groups
and others
if all else fails.
Why should I use Keycloak and not something like Auth0?
You can go with either of those for your authentication and authorization needs. The main difference is that Keycloak is a self-hosted solution, meaning that the data stored is under your control, and you're liable for any leaks. On the other hand, AuthO is a user identity management service provided by Okta, and the data stored is under their control.
In this article,
we learned to set up an Nginx reverse proxy, provision SSL certificates, configure a Postgres database, and host a production-ready Keycloak server.
Please comment below if you have any queries, I try to periodically update my articles to ensure legibility!