How To Run Keycloak in Docker or Podman With SSL

Keycloak is a powerful open source Identity and Access Management (IAM) solution used to manage access to modern infrastructure, applications, and services. It gives you advanced authentication and authorization mechanism for your services, enabling developers to better secure applications without coding custom authentication modules.

Features of Keycloak (Benefits)?

Here are some key benefits and uses of Keycloak:

  • Centralized Access Management: You get a unified interface from where you can administer user identities, permissions, access roles, across various services and applications.
  • Management of user accounts: Keycloak enables users to manage their own accounts information, including password changes and account linking.
  • Single Sign-On (SSO) and Single Log-Out: Single authentication for multiple applications, and logout once from all apps.
  • Keycloak as Identity Broker / Social Login: It can be integrated with third party identity providers like Google, Github, Facebook, and other OpenID Connect or SAML-based identity providers.
  • Use for User Federation: Keycloak can Integrate with existing user databases in corporate environments such as Active Directory or LDAP.
  • Multi-Factor Authentication (MFA): You can introduce an extra layer of security by enforcing multiple forms of verification to gain access to systems and applications.
  • API Access Management: Easily secure application APIs using tokens (JWT tokens or SAML assertions).
  • Keycloak support multiple protocols like OAuth2, SAML, and OpenID Connect (OIDC).

In this article we will take you through the process of installing and running Keycloak in Docker or Podman. Two options will be considered:

  • Running Keycloak in a container without SSL (HTTP)
  • Running Keycloak in container with SSL (HTTPs)

All configurations used in this guide are available in our Docker Compose templates Github repository. You can click on the link to learn more.

Let’s begin with the first option.

Running Keycloak in a container without SSL (HTTP) – Not Recommended

We will use domain name as follows, with an IP address:

  • IP 192.168.1.20 mapped to domain iam.cloudspinx.com

Let’s begin by installing Docker and Podman in the system:

  • Install Docker Container Engine:
curl -fsSL get.docker.com -o get-docker.sh
sudo sh get-docker.sh
  • Installing Podman container runtime:
# RHEL based systems
sudo dnf -y install podman
sudo dnf install -y python3-pip
sudo pip3 install podman-compose

# Debian based systems
sudo apt update && sudo apt install podman
sudo apt install python3-pip
sudo pip3 install podman-compose

Create a directory what will host the project code.

mkdir ~/keycloak && cd ~/keycloak 

Create an environment file with configuration properties.

$ vim .env
KC_DB_PASSWORD=StrongDBPassword
KC_HOSTNAME=iam.cloudspinx.com
KEYCLOAK_ADMIN=admin
KEYCLOAK_ADMIN_PASSWORD=Str0ngAdminPassw0rD
  • StrongDBPassword should be replaced with your desired Keycloak admin user password
  • admin is the default privileged user for Keycloak
  • Str0ngAdminPassw0rD is the password for the admin user
  • iam.cloudspinx.com with your server hostname is configured in DNS or /etc/hosts file

Create docker-compose.yaml file with contents required to run keycloak in container.

vim docker-compose.yaml

Then update your docker compose yaml file like below.

services:
  keycloak:
      container_name: keycloak
      image: quay.io/keycloak/keycloak:latest
      environment:
        KC_DB: postgres
        KC_DB_URL: jdbc:postgresql://postgres_db:5432/keycloak
        KC_DB_USER: keycloak
        KC_DB_SCHEMA: public
        KC_DB_PASSWORD: ${KC_DB_PASSWORD}
        KC_HOSTNAME: ${KC_HOSTNAME}
        KC_HOSTNAME_PORT: 8080
        KC_HOSTNAME_STRICT_BACKCHANNEL: false
        KC_HTTP_ENABLED: true
        KC_HOSTNAME_STRICT_HTTPS: false
        KC_HEALTH_ENABLED: true
        KEYCLOAK_ADMIN: ${KEYCLOAK_ADMIN}
        KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD}
      ports:
        - 8080:8080
      restart: always
      command: start
      depends_on:
        - postgres_db
      networks:
        - keycloak

  postgres_db:
      container_name: postgres-db
      image: postgres
      restart: always
      volumes:
        - ./data/db:/var/lib/postgresql/data
        - /etc/localtime:/etc/localtime:ro
      environment:
        POSTGRES_DB: keycloak
        POSTGRES_USER: keycloak
        POSTGRES_PASSWORD: ${KC_DB_PASSWORD}
      ports:
        - 5432:5432
      networks:
        - keycloak
networks:
  keycloak:
    external: true

Manually create keycloak network

docker network create keycloak

To start the containers, run the following commands:

docker compose up -d

Expected output once the command is executed:

[+] Running 20/20
 ✔ keycloak Pulled                                                                                                                                                                                                                                                           14.1s
   ✔ a04e04efb6ef Pull complete                                                                                                                                                                                                                                               3.4s
   ✔ 41df698d6f61 Pull complete                                                                                                                                                                                                                                               8.8s
   ✔ 15c52560d256 Pull complete                                                                                                                                                                                                                                              11.9s
   ✔ 844215b13393 Pull complete                                                                                                                                                                                                                                              11.9s
 ✔ postgres_db Pulled                                                                                                                                                                                                                                                        14.4s
   ✔ efc2b5ad9eec Pull complete                                                                                                                                                                                                                                               3.9s
   ✔ c1fb352e1bee Pull complete                                                                                                                                                                                                                                               3.9s
   ✔ 64bfb99d167c Pull complete                                                                                                                                                                                                                                               4.4s
   ✔ 111153255129 Pull complete                                                                                                                                                                                                                                               4.6s
   ✔ f319b93a653f Pull complete                                                                                                                                                                                                                                               5.3s
   ✔ c52a8331fefe Pull complete                                                                                                                                                                                                                                               5.4s
   ✔ eede18b3a95f Pull complete                                                                                                                                                                                                                                               5.4s
   ✔ 8ecfa78d0b10 Pull complete                                                                                                                                                                                                                                               5.4s
   ✔ 1d8a72096603 Pull complete                                                                                                                                                                                                                                              12.6s
   ✔ 74799cfc006f Pull complete                                                                                                                                                                                                                                              12.6s
   ✔ ca3e3ab274d4 Pull complete                                                                                                                                                                                                                                              12.7s
   ✔ 17b5d00a7c44 Pull complete                                                                                                                                                                                                                                              12.7s
   ✔ 86ed78b05f10 Pull complete                                                                                                                                                                                                                                              12.7s
   ✔ 786a87677547 Pull complete                                                                                                                                                                                                                                              12.7s
[+] Running 2/2
 ✔ Container postgres-db  Started                                                                                                                                                                                                                                             0.5s
 ✔ Container keycloak     Started       

Container status can be checked by running:

$ docker compose ps
NAME          IMAGE                              COMMAND                  SERVICE       CREATED          STATUS          PORTS
keycloak      quay.io/keycloak/keycloak:latest   "/opt/keycloak/bin/k…"   keycloak      26 seconds ago   Up 26 seconds   8443/tcp, 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 9000/tcp
postgres-db   postgres                           "docker-entrypoint.s…"   postgres_db   26 seconds ago   Up 26 seconds   0.0.0.0:5432->5432/tcp, :::5432->5432/tcp

Watch for any startup errors using docker logs command:

docker logs postgres-db
docker logs keycloak

Access Keycloak admin dashboard at http://your_domain:8080

Login with values set for KEYCLOAK_ADMIN and KEYCLOAK_ADMIN_PASSWORD.

Running Keycloak in container with SSL (HTTPS) – Let’s Encypt

Two options are viable for this:

Option 1) Using Self-signed certificates

Create a directory called ssl.

mkdir ssl && cd ssl

You can use OpenSSL to generate self-signed certificates.

Generate private key.

openssl genrsa -out keycloak.key

Generate CSR and private key files by running the following commands.

openssl req -new -key keycloak.key -out keycloak.csr

Sign the certificate using a private key and CSR:

openssl x509 -req -in keycloak.csr -signkey keycloak.key -days 3650 -out keycloak.crt

Set ssl directory permissions to allow container to read SSL files.

cd ..
chmod -R 0644 ssl

Open the compose file for update

vim docker-compose.yaml

Modify the contents to include mounting of SSL certificate and key and setting environment variables in the container.

services:
  keycloak:
      container_name: keycloak
      image: quay.io/keycloak/keycloak:latest
      environment:
        KC_DB: postgres
        KC_DB_URL: jdbc:postgresql://postgres_db:5432/keycloak
        KC_DB_USER: keycloak
        KC_DB_SCHEMA: public
        KC_DB_PASSWORD: ${KC_DB_PASSWORD}
        KC_HOSTNAME: ${KC_HOSTNAME}
        KC_HEALTH_ENABLED: true
        KEYCLOAK_ADMIN: ${KEYCLOAK_ADMIN}
        KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD}
        KC_HTTPS_CERTIFICATE_FILE: /opt/keycloak/conf/server.crt
        KC_HTTPS_CERTIFICATE_KEY_FILE: /opt/keycloak/conf/server.key
      ports:
        - 8443:8443
      restart: always
      volumes:
        - ./ssl/keycloak.crt:/opt/keycloak/conf/server.crt
        - ./ssl/keycloak.key:/opt/keycloak/conf/server.key
      command: start
      depends_on:
        - postgres_db
      networks:
        - keycloak

  postgres_db:
      container_name: postgres-db
      image: postgres
      restart: always
      volumes:
        - ./data/db:/var/lib/postgresql/data
        - /etc/localtime:/etc/localtime:ro
      environment:
        POSTGRES_DB: keycloak
        POSTGRES_USER: keycloak
        POSTGRES_PASSWORD: ${KC_DB_PASSWORD}
      ports:
        - 5432:5432
      networks:
        - keycloak
networks:
  keycloak:
    external: true

Take down the services.

docker compose down

Bring up the containers with the new configurations.

docker compose up -d

Monitor logs to see if it can start successfully.

docker logs keycloak

Option 2) Using Let’s Encrypt SSL

We can can create a directory that will contain SSL files.

mkdir ~/keycloak/certbot && cd ~/keycloak/certbot

Create docker compose file for generating Let’s Encrypt SSL certificates.

vim docker-compose.yaml

Here are the contents to use for the file.

services:
  webserver:
    image: nginx:latest
    ports:
      - 80:80
      - 443:443
    restart: always
    volumes:
      - ${WEBROOT_PATH}:/var/www/certbot/
      - ${LETSENCRYPT_PATH}:/etc/letsencrypt
      - ${NGINX_CONF_PATH}:/etc/nginx/nginx.conf
  certbot:
    image: certbot/certbot:latest
    entrypoint: ""
    command: sh -c "trap exit TERM; while :; do certbot certonly --webroot --webroot-path=/var/www/certbot --email ${EMAIL} --agree-tos --no-eff-email -d ${DOMAIN}; sleep 12h & wait $${!}; done;"

    volumes:
      - ./www/:/var/www/certbot/
      - ./letsencrypt:/etc/letsencrypt

Create .env file with email address, domain, and other required params.

$ vim .env
EMAIL=[email protected]
DOMAIN=iam.cloudspinx.com
WEBROOT_PATH=./www/
LETSENCRYPT_PATH=./letsencrypt
NGINX_CONF_PATH=./nginx.conf

Create necessary directories.

source .env
mkdir -p $LETSENCRYPT_PATH $WEBROOT_PATH
chmod 0777 $LETSENCRYPT_PATH $WEBROOT_PATH

Create nginx configuration file:

vim ./nginx.conf

Add the contents below into the file. Don’t forget to use your valid domain in place of iam.cloudspinx.com.

events {
  worker_connections 1024;
}

http {
  server {
    listen 80;
    server_name iam.cloudspinx.com;

    location /.well-known/acme-challenge/ {
      root /var/www/certbot;
    }

    location / {
      return 301 https://$host$request_uri;
    }
  }
}

Run the docker compose up to request for SSL.

$ docker compose up
[+] Running 2/0
 ✔ Container letsencrypt-certbot-1    Created                                                                                                                                                                                                                                 0.1s
 ✔ Container letsencrypt-webserver-1  Created                                                                                                                                                                                                                                 0.1s
Attaching to certbot-1, webserver-1
webserver-1  | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
webserver-1  | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
webserver-1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
webserver-1  | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
webserver-1  | 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
webserver-1  | /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
webserver-1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
webserver-1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
webserver-1  | /docker-entrypoint.sh: Configuration complete; ready for start up
certbot-1    | Saving debug log to /var/log/letsencrypt/letsencrypt.log
certbot-1    | Requesting a certificate for iam.cloudspinx.com
webserver-1  | 23.178.112.106 - - [13/Aug/2024:09:51:10 +0000] "GET /.well-known/acme-challenge/QswDZWRIvZn4ZkvPJ_hugHhAQ6j6M6sWL3uOfwEYcx4 HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"
webserver-1  | 13.51.177.57 - - [13/Aug/2024:09:51:10 +0000] "GET /.well-known/acme-challenge/QswDZWRIvZn4ZkvPJ_hugHhAQ6j6M6sWL3uOfwEYcx4 HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"
webserver-1  | 18.117.224.42 - - [13/Aug/2024:09:51:10 +0000] "GET /.well-known/acme-challenge/QswDZWRIvZn4ZkvPJ_hugHhAQ6j6M6sWL3uOfwEYcx4 HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"
webserver-1  | 52.10.95.25 - - [13/Aug/2024:09:51:10 +0000] "GET /.well-known/acme-challenge/QswDZWRIvZn4ZkvPJ_hugHhAQ6j6M6sWL3uOfwEYcx4 HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"
webserver-1  | 18.143.65.27 - - [13/Aug/2024:09:51:10 +0000] "GET /.well-known/acme-challenge/QswDZWRIvZn4ZkvPJ_hugHhAQ6j6M6sWL3uOfwEYcx4 HTTP/1.1" 200 87 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"
certbot-1    |
certbot-1    | Successfully received certificate.
certbot-1    | Certificate is saved at: /etc/letsencrypt/live/iam.cloudspinx.com/fullchain.pem
certbot-1    | Key is saved at:         /etc/letsencrypt/live/iam.cloudspinx.com/privkey.pem
certbot-1    | This certificate expires on 2024-11-11.
certbot-1    | These files will be updated when the certificate renews.
certbot-1    | NEXT STEPS:
certbot-1    | - The certificate will need to be renewed before it expires. Certbot can automatically renew the certificate in the background, but you may need to take steps to enable that functionality. See https://certbot.org/renewal-setup for instructions.
certbot-1    |
certbot-1    | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
certbot-1    | If you like Certbot, please consider supporting our work by:
certbot-1    |  * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
certbot-1    |  * Donating to EFF:                    https://eff.org/donate-le
certbot-1    | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
webserver-1  | 164.92.244.132 - - [13/Aug/2024:09:51:23 +0000] "\x16\x03\x01\x01\x05\x01\x00\x01\x01\x03\x03\x9B\xA1\xD8\xBB\xC8\x1DJ\x89\x18\xAF1\xEA\x17\xBCT>:^\xD7\x02\xAB\xC2\xAF\x18\x5C\xFAh8\x84\xB2\xC2p \xA9\xD7\xE8\xAA\xD5" 400 157 "-" "-"
webserver-1  | 164.92.244.132 - - [13/Aug/2024:09:51:23 +0000] "GET / HTTP/1.1" 301 169 "-" "-"
webserver-1  | 164.92.244.132 - - [13/Aug/2024:09:51:23 +0000] "GET / HTTP/1.1" 301 169 "-" "Mozilla/5.0 (Linux; Android 6.0; HTC One M9 Build/MRA523394) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.1959.98 Mobile Safari/537.3"
webserver-1  | 164.92.244.132 - - [13/Aug/2024:09:51:23 +0000] "GET /server HTTP/1.1" 301 169 "-" "Go-http-client/1.1"
webserver-1  | 164.92.244.132 - - [13/Aug/2024:09:51:23 +0000] "GET /.vscode/sftp.json HTTP/1.1" 301 169 "-" "Go-http-client/1.1"
webserver-1  | 164.92.244.132 - - [13/Aug/2024:09:51:23 +0000] "GET /about HTTP/1.1" 301 169 "-" "Go-http-client/1.1"
webserver-1  | 164.92.244.132 - - [13/Aug/2024:09:51:23 +0000] "GET /debug/default/view?panel=config HTTP/1.1" 301 169 "-" "Go-http-client/1.1"
webserver-1  | 164.92.244.132 - - [13/Aug/2024:09:51:23 +0000] "GET /v2/_catalog HTTP/1.1" 301 169 "-" "Go-http-client/1.1"
webserver-1  | 164.92.244.132 - - [13/Aug/2024:09:51:23 +0000] "GET /ecp/Current/exporttool/microsoft.exchange.ediscovery.exporttool.application HTTP/1.1" 301 169 "-" "Go-http-client/1.1"
webserver-1  | 164.92.244.132 - - [13/Aug/2024:09:51:23 +0000] "GET /server-status HTTP/1.1" 301 169 "-" "Go-http-client/1.1"
webserver-1  | 164.92.244.132 - - [13/Aug/2024:09:51:23 +0000] "GET /login.action HTTP/1.1" 301 169 "-" "Go-http-client/1.1"
webserver-1  | 164.92.244.132 - - [13/Aug/2024:09:51:23 +0000] "GET /_all_dbs HTTP/1.1" 301 169 "-" "Mozilla/5.0 (l9scan/2.0.631323e2033323e2330323e2631313; +https://leakix.net)"
webserver-1  | 164.92.244.132 - - [13/Aug/2024:09:51:23 +0000] "GET /.DS_Store HTTP/1.1" 301 169 "-" "Go-http-client/1.1"
webserver-1  | 164.92.244.132 - - [13/Aug/2024:09:51:23 +0000] "GET /.env HTTP/1.1" 301 169 "-" "Go-http-client/1.1"
webserver-1  | 164.92.244.132 - - [13/Aug/2024:09:51:23 +0000] "GET /.git/config HTTP/1.1" 301 169 "-" "Go-http-client/1.1"
webserver-1  | 164.92.244.132 - - [13/Aug/2024:09:51:23 +0000] "GET /s/631323e2033323e2330323e2631313/_/;/META-INF/maven/com.atlassian.jira/jira-webapp-dist/pom.properties HTTP/1.1" 301 169 "-" "Go-http-client/1.1"
webserver-1  | 164.92.244.132 - - [13/Aug/2024:09:51:23 +0000] "GET /config.json HTTP/1.1" 301 169 "-" "Go-http-client/1.1"
webserver-1  | 164.92.244.132 - - [13/Aug/2024:09:51:23 +0000] "GET /telescope/requests HTTP/1.1" 301 169 "-" "Go-http-client/1.1"
webserver-1  | 164.92.244.132 - - [13/Aug/2024:09:51:23 +0000] "GET /?rest_route=/wp/v2/users/ HTTP/1.1" 301 169 "-" "Go-http-client/1.1"

You can also run it in the background.

docker compose up -d

Verify that Nginx is serving the challenge files correctly and that Certbot is able to retrieve the certificate.

docker compose logs -f webserver
docker compose logs -f certbot

Once the key and certificate is generated you can cancel or stop the container services for certbot.

source .env
ls -1 ssl-certs/letsencrypt/live/$DOMAIN/*

Create a different directory and copy cert and key files over.

cd ../
mkdir ./keycloak-certs
cp letsencrypt/live/$DOMAIN/fullchain.pem ./keycloak-certs
cp letsencrypt/live/$DOMAIN/privkey.pem ./keycloak-certs
chmod -R 0644 ./keycloak-certs

Update your Compose file:

services:
  keycloak:
      container_name: keycloak
      image: quay.io/keycloak/keycloak:latest
      privileged: true
      environment:
        KC_DB: postgres
        KC_DB_URL: jdbc:postgresql://postgres_db:5432/keycloak
        KC_DB_USER: keycloak
        KC_DB_SCHEMA: public
        KC_DB_PASSWORD: ${KC_DB_PASSWORD}
        KC_HOSTNAME: ${KC_HOSTNAME}
        KC_HEALTH_ENABLED: true
        KEYCLOAK_ADMIN: ${KEYCLOAK_ADMIN}
        KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD}
        KC_HTTPS_CERTIFICATE_FILE: ${KC_HTTPS_CERTIFICATE_FILE}
        KC_HTTPS_CERTIFICATE_KEY_FILE: ${KC_HTTPS_CERTIFICATE_KEY_FILE}
      ports:
        - 8443:8443
      restart: always
      volumes:
        - ${LOCAL_CERT}:${KC_HTTPS_CERTIFICATE_FILE}
        - ${LOCAL_KEY}:${KC_HTTPS_CERTIFICATE_KEY_FILE}
      command: start
      depends_on:
        - postgres_db
      networks:
        - keycloak

  postgres_db:
      container_name: postgres-db
      image: postgres
      restart: always
      volumes:
        - ./data/db:/var/lib/postgresql/data
        - /etc/localtime:/etc/localtime:ro
      environment:
        POSTGRES_DB: keycloak
        POSTGRES_USER: keycloak
        POSTGRES_PASSWORD: ${KC_DB_PASSWORD}
      ports:
        - 5432:5432
      networks:
        - keycloak
networks:
  keycloak:
    external: true

Update environment configurations:

KC_DB_PASSWORD=StrongDBPassword
KC_HOSTNAME=iam.cloudspinx.com
KEYCLOAK_ADMIN=admin
KEYCLOAK_ADMIN_PASSWORD=Str0ngAdminPassw0rD
KC_HTTPS_CERTIFICATE_FILE=/opt/keycloak/conf/fullchain.pem
KC_HTTPS_CERTIFICATE_KEY_FILE=/opt/keycloak/conf/privkey.pem
LOCAL_CERT=./keycloak-certs/fullchain.pem
LOCAL_KEY=./keycloak-certs/privkey.pem

Stop and start the services.

docker compose down && docker compose up -d

Access your Keycloak server web console on https://yourdomain:8443.

Let’s Encrypt renewal script

Create renewal script.

#!/bin/bash

# Load environment variables
source .env

# Stop containers
docker compose stop

# Run certbot renewal
docker compose run --rm certbot sh -c "certbot renew --webroot --webroot-path=/var/www/certbot"

# Check if certbot renewal was successful
if [ $? -eq 0 ]; then
	cd ../
	mkdir -p ./keycloak-certs
	# Copy the renewed certificates to the keycloak-certs directory
	mkdir -p ./keycloak-certs
	cp -f certbot/letsencrypt/live/$DOMAIN/fullchain.pem ./keycloak-certs
	cp -f certbot/letsencrypt/live/$DOMAIN/privkey.pem ./keycloak-certs
	chmod -R 0644 ./keycloak-certs
	echo "Certificates renewed and copied successfully."
else
	echo "Certificate renewal failed."
fi

Make it executable

chmox +x ssl_renew.sh

Execute the script to renew the certificates:

bash ssl_renew.sh

You can have cron job to check every 4am.

$ crontab -e
0 04 * * * /path/to/your/renew_certificates.sh >> /var/log/certbot-renew.log 2>&1

Enjoy using Keycloak as your identity manager for better access control to systems and applications. You can access all configs used in our github repository. If you need any help CloudSpinx Engineers are available 24/7.

Your IT Journey Starts Here!

Ready to level up your IT skills? Our new eLearning platform is coming soon to help you master the latest technologies.

Be the first to know when we launch! Join our waitlist now.

Join our Linux and open source community. Subscribe to our newsletter for tips, tricks, and collaboration opportunities!

Recent Post

Leave a Comment

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

Related Post

Let’s clarify the differences between merge requests (commonly called pull requests in GitHub), releases, release candidates (RCs), tags, and branches […]

Kind (which in full means “Kubernetes IN Docker”), is a command line tool that enables you to run Kubernetes clusters […]

Are you looking for an easy way to migrate packages from one cPanel server to a new cPanel server? In […]

Let's Connect

Unleash the full potential of your business with CloudSpinx. Our expert solutions specialists are standing by to answer your questions and tailor a plan that perfectly aligns with your unique needs.
You will get a response from our solutions specialist within 12 hours
We understand emergencies can be stressful. For immediate assistance, chat with us now

Contact CloudSpinx today!

Download CloudSpinx Profile

Discover the full spectrum of our expertise and services by downloading our detailed Company Profile. Simply enter your first name, last name, and email address.