<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Roman Surkoff</title>
    <description>The latest articles on DEV Community by Roman Surkoff (@surkoff).</description>
    <link>https://dev.to/surkoff</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1738455%2Fe5e357a7-06cb-43ec-8ef9-56be45abd5c7.jpeg</url>
      <title>DEV Community: Roman Surkoff</title>
      <link>https://dev.to/surkoff</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/surkoff"/>
    <language>en</language>
    <item>
      <title>Deploying Keycloak to a VPS Using Docker-compose, Nginx, Certbot, and SSL</title>
      <dc:creator>Roman Surkoff</dc:creator>
      <pubDate>Sat, 06 Jul 2024 12:21:23 +0000</pubDate>
      <link>https://dev.to/surkoff/deploying-keycloak-on-a-vps-using-docker-compose-nginx-certbot-and-ssl-1pa8</link>
      <guid>https://dev.to/surkoff/deploying-keycloak-on-a-vps-using-docker-compose-nginx-certbot-and-ssl-1pa8</guid>
      <description>&lt;p&gt;In this article, I would like to share how to deploy Keycloak to a VPS using Docker-compose, Nginx, Certbot, and SSL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key points:
&lt;/h2&gt;

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

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Everyone has their own motivation, but let's get to the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;h4&gt;
  
  
  What is Keycloak?
&lt;/h4&gt;

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

&lt;h4&gt;
  
  
  Why Docker-compose?
&lt;/h4&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why Nginx and Certbot?
&lt;/h4&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Preparing the Environment
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Cloning the Repository
&lt;/h4&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

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


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Editing the .env File
&lt;/h4&gt;

&lt;p&gt;Open the .env file and edit the following variables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;KEYCLOAK_ADMIN_PASSWORD&lt;/code&gt; - Admin password for accessing Keycloak&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;KC_DB_PASSWORD&lt;/code&gt; - Password for Keycloak service access to the Postgres DB (should match &lt;code&gt;POSTGRES_PASSWORD&lt;/code&gt; if a separate user is not created)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POSTGRES_PASSWORD&lt;/code&gt; - Admin password for Postgres&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Replace &lt;code&gt;password&lt;/code&gt; with your values unless you want anyone to connect to your services ;)&lt;/p&gt;

&lt;p&gt;Example of a complete environment variables file:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

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


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Step 2: Domain Registration and DNS Setup
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;
&lt;h4&gt;
  
  
  Domain Registration
&lt;/h4&gt;

&lt;p&gt;Register a domain with any registrar, for example, REG.RU.&lt;/p&gt;
&lt;h4&gt;
  
  
  Creating an &lt;code&gt;A&lt;/code&gt; Record for the Subdomain
&lt;/h4&gt;

&lt;p&gt;Create an &lt;code&gt;A&lt;/code&gt; record pointing to your server's IP. For example, for the subdomain my-keycloak.surkoff.com, specify your server's IP.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo1lyc4qyari5zoxfdqac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo1lyc4qyari5zoxfdqac.png" alt="Creating subdomain"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Checking the DNS Record
&lt;/h4&gt;

&lt;p&gt;Ensure the DNS record is correctly configured:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

ping my-keycloak.surkoff.com


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The response should show your server's IP address.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Configuring Nginx
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Nginx Configuration
&lt;/h4&gt;

&lt;p&gt;In the nginx configs - &lt;code&gt;default.conf_with_ssl&lt;/code&gt;, &lt;code&gt;default.conf_without_ssl&lt;/code&gt; edit and specify your domain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;server_name&lt;/code&gt; section&lt;/li&gt;
&lt;li&gt;path to the certificate &lt;code&gt;ssl_certificate&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;path to the key &lt;code&gt;ssl_certificate_key&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example configuration with SSL:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

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;
    }
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Step 4: Obtaining an SSL Certificate
&lt;/h2&gt;
&lt;h4&gt;
  
  
  Obtaining a Test Certificate
&lt;/h4&gt;

&lt;p&gt;Use the configuration without SSL:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

cp nginx/conf.d/default.conf_without_ssl nginx/conf.d/default.conf
docker-compose up -d


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Obtain a test certificate (replace the domain and email with your own):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

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


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsi62vmnbk48zdryoy3d8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsi62vmnbk48zdryoy3d8.png" alt="Obtain test SSL certificate"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Checking the Certificate
&lt;/h4&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

docker exec certbot certbot certificates


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnv3692ihg02bqz9c9ihi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnv3692ihg02bqz9c9ihi.png" alt="Check if certificate exists"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Deleting the Test Certificate (replace the domain with your own)
&lt;/h4&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

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


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Obtaining a Real Certificate (replace email and domain with your own)
&lt;/h4&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

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


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Step 5: Final Configuration and Launch
&lt;/h2&gt;
&lt;h4&gt;
  
  
  Updating Nginx Configuration to Use SSL
&lt;/h4&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

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


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Checking Access to Keycloak
&lt;/h4&gt;

&lt;p&gt;Open a browser and go to my-keycloak.surkoff.com (your domain).&lt;/p&gt;

&lt;p&gt;You should see the admin login page where you can log in using the username and password you specified in the .env file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcg2twvbvn7kr3z1hxcot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcg2twvbvn7kr3z1hxcot.png" alt="Keycloak admin page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For configuring Keycloak, there are interesting articles on other resources, which we won't cover in this publication.&lt;/p&gt;
&lt;h2&gt;
  
  
  Automatic Certificate Renewal
&lt;/h2&gt;

&lt;p&gt;To automatically renew certificates and restart Nginx, create the &lt;code&gt;renew_and_reload.sh&lt;/code&gt; script (already available in the repository):&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

#!/bin/bash
# Renew certificates
docker exec certbot certbot renew --webroot --webroot-path=/data/letsencrypt

# Restart Nginx
docker restart nginx


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Make the script executable:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

chmod +x renew_and_reload.sh


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Add it to crontab for regular execution:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

crontab -e


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Add a line to crontab, remembering to specify the path to the script:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;0 0 1 * * /path/to/renew_and_reload.sh&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Importing Realms&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;If you want to import a realm at startup, you can place it in the &lt;code&gt;keycloak/config/&lt;/code&gt; folder, and it will be imported when the application starts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The source code is available at &lt;a href="https://github.com/s-rb/keycloak-dockerized-ssl-nginx" rel="noopener noreferrer"&gt;the link here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>keycloak</category>
      <category>vps</category>
      <category>ssl</category>
      <category>certbot</category>
    </item>
  </channel>
</rss>
