Hello everyone!

In this article, I would like to share how to deploy Keycloak on a VPS using Docker-compose, Nginx, Certbot, and SSL.

Key Points:

- Keycloak v.25.0.1
- SSL protection for Keycloak
- Certbot v.2.11.0 for obtaining and renewing SSL certificates
- Nginx v.1.27.0 as a reverse proxy
- Postgres v.14 to replace the default internal H2 DB of Keycloak
- Automatic realm import during deployment
- Docker-compose for deployment automation
- .env file for managing environment variables

For those who might not be familiar, Keycloak is a powerful access management system with SSO support that can significantly simplify user management and authentication.

The desire to deploy your own Keycloak can arise both for experimenting with your projects and for handling your usual backend tasks. This happened to me as well. I decided to kill two birds with one stone. However, I couldn't find a comprehensive guide. I don't need Keycloak locally, but setting it up on a separate, always-available server with backup and the ability to export/import realms, etc., is excellent. Plus, the deployment process is automated, making it easier to switch to another VPS provider.

Everyone has their own motivation, but let's get to the point.

Introduction


What is Keycloak?

Keycloak is an open-source identity and access management solution. It provides features such as SSO (Single Sign-On), user management, authentication, and authorization.

Why Docker-compose?

Docker-compose makes it easy to manage multi-component applications like Keycloak and simplifies the deployment and scaling process. This guide uses containers for Keycloak, Certbot, Nginx, and the Postgres database.

Why Nginx and Certbot?

Nginx will act as a reverse proxy, ensuring security and performance, while Certbot will help obtain and automatically renew SSL certificates from Let's Encrypt, saving us a couple of thousand rubles on certificates for our domain, which is nice.

Let's get started!

Step 1: Preparing the Environment

Cloning the Repository

First, clone the repository with ready-made configurations to our VPS, which I have carefully prepared for you. It contains docker-compose.yml for managing deployment, nginx configs, and an environment variables file needed for docker-compose.

    git clone git@github.com:s-rb/keycloak-dockerized-ssl-nginx.git
    cd keycloak-dockerized-ssl-nginx

Editing the .env File

Open the .env file and edit the following variables:

- KEYCLOAK_ADMIN_PASSWORD - Admin password for accessing Keycloak
- KC_DB_PASSWORD - Password for Keycloak service access to the Postgres DB (should match `POSTGRES_PASSWORD` if a separate user is not created)
- POSTGRES_PASSWORD - Admin password for Postgres

Replace `password` with your values unless you want anyone to connect to your services ;)

Example of a complete environment variables file:

    KEYCLOAK_ADMIN=admin
    KEYCLOAK_ADMIN_PASSWORD=password
    PROXY_ADDRESS_FORWARDING=true
    KC_PROXY=edge
    
KC_DB=postgres KC_DB_URL=jdbc:postgresql://keycloak-postgres:5432/keycloak KC_DB_USERNAME=keycloak KC_DB_PASSWORD=password POSTGRES_DB=keycloak POSTGRES_USER=keycloak POSTGRES_PASSWORD=password

Step 2: Domain Registration and DNS Setup

This step can be done before the first step - it does not depend on it. In the following instructions, we assume you have registered your domain (e.g., surkoff.com) and we want Keycloak to be accessible at my-keycloak.surkoff.com.

Domain Registration

Register a domain with any registrar, for example, REG.RU.

Creating an A Record for the Subdomain

Create an A record pointing to your server's IP. For example, for the subdomain my-keycloak.surkoff.com, specify your server's IP.



Checking the DNS Record

Ensure the DNS record is correctly configured:

ping my-keycloak.surkoff.com

The response should show your server's IP address.

Step 3: Configuring Nginx

Nginx Configuration

In the nginx configs - `default.conf_with_ssl`, `default.conf_without_ssl` specify your domain:

- In the `server_name` section
- In the path to the certificate `ssl_certificate`
- In the path to the key `ssl_certificate_key`

Example configuration with SSL:
server {
    listen 443 ssl;
    server_name my-keycloak.surkoff.com;

    ssl_certificate /etc/letsencrypt/live/my-keycloak.surkoff.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/my-keycloak.surkoff.com/privkey.pem;

    location / {
        proxy_pass http://keycloak:8080;
        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-Proto $scheme;
    }
}

Step 4: Obtaining an SSL Certificate

Obtaining a Test Certificate

Use the configuration without SSL:
cp nginx/conf.d/default.conf_without_ssl nginx/conf.d/default.conf
docker-compose up -d

Obtain a test certificate (replace the domain and email with your own):
docker exec certbot certbot certonly --webroot --webroot-path=/data/letsencrypt -d my-keycloak.surkoff.com --email your_email@gmail.com --agree-tos --no-eff-email --staging


Checking the Certificate

docker exec certbot certbot certificates

Deleting the Test Certificate (replace the domain with your own)

docker exec certbot certbot delete --cert-name my-keycloak.surkoff.com

Obtaining a Real Certificate (replace email and domain with your own)

docker exec certbot certbot certonly --webroot --webroot-path=/data/letsencrypt -d my-keycloak.surkoff.com --email your_email@gmail.com --agree-tos --no-eff-email

Step 5: Final Configuration and Launch

Updating Nginx Configuration to Use SSL

docker-compose down
cp nginx/conf.d/default.conf_with_ssl nginx/conf.d/default.conf
docker-compose up -d

Checking Access to Keycloak

Open a browser and go to my-keycloak.surkoff.com (your domain).

You should see the admin login page where you can log in using the username and password you specified in the .env file.



For configuring Keycloak, there are interesting articles on other resources, which we won't cover in this publication.

Automatic Certificate Renewal

To automatically renew certificates and restart Nginx, create the `renew_and_reload.sh` script (already available in the repository):
#!/bin/bash
# Renew certificates
docker exec certbot certbot renew --webroot --webroot-path=/data/letsencrypt

# Restart Nginx
docker restart nginx

Make the script executable:
chmod +x renew_and_reload.sh

Add it to crontab for regular execution:
crontab -e

Add a line to crontab, remembering to specify the path to the script:
0 0 1 * * /path/to/renew_and_reload.sh

Importing Realms

If you want to import a realm at startup, you can place it in the `keycloak/config/` folder, and it will be imported when the application starts.

Conclusion

That's it! Now you have a deployed latest Keycloak with SSL on your VPS. I hope this article was helpful! If you have any questions or suggestions, feel free to write to me in private messages.

The source code is available at the link - https://github.com/s-rb/keycloak-dockerized-ssl-nginx.