This blog covers general Keycloak configuration for a production and non-production environments including architecture, backups, restore and upgrade. As well as an Oracle APEX Authentication scheme.
For a better read… Pretius’ Keycloak development services are second-to-none, including Azure Kubernetes, Keycloak Control, Key Vault and much more. So, if you are considering Keycloak, make sure you contact Pretius.
Considerations & Customization
A Keycloak Instance for Dev & Prod? Or a Dev & Prod Realm on a single Keycloak Instance?
For managing Keycloak environments for development (Dev) and production (prod), it is generally recommended to use two separate Keycloak instances, each with its own realm, rather than using a single instance with two realms.
[Keycloak Instance 1: Development]
|
+-- [Realm: Dev]
|
+-- [APEX Application]
|
+-- [Users]
|
+-- [Roles]
[Keycloak Instance 2: Production]
|
+-- [Realm: Prod]
|
+-- [APEX Application]
|
+-- [Users]
|
+-- [Roles]
Security and Isolation
Using separate instances for Dev and prod provides better security and isolation:
Independent environments: Dev and prod environments remain completely separate, preventing any accidental changes in Dev from affecting prod
Reduced risk: If one instance is compromised, the other remains secure. Users & groups are held separately. E.g Dev has Dev logins, prod has prod Logins.
Performance and Scalability
Separate instances offer better performance and scalability:
Each instance can be optimized for its specific environment's needs
Keycloak can experience performance drops when handling more than hundreds of realms in a single instance.
Maintenance and Updates
Managing updates and configurations becomes easier:
You can test new Keycloak versions in dev without risking prod stability
Each instance can have its own settings tailored to Dev or prod requirements
Changes can be trialed on Dev without affecting prod
Best Practices
Following best practices for Keycloak deployment:
Dev and prod environments often have different security requirements and user bases e.g. prod may have MFA whereas Dev may not.
Realistic testing: A separate Dev instance allows for more accurate testing of your production setup.
Do not use Master Realm for your Users, set up a new Realm. Master Realm has higher privileges, used for Administration & Regular Realms allows for allows for better organization and scalability.
While it's possible to use a single instance with multiple realms, this approach is generally not recommended for separating Dev and prod environments. The benefits of using separate instances outweigh the slight increase in infrastructure complexity.
Keycloak Login Themes
Themes are a set of files in a folder with a custom name
keycloak-root/
└── themes/
└── custom-theme/
└── login/
├── resources/
│ ├── css/
│ └── img/
└── theme.properties
For example: a new background image on the login page:
A new image is placed in img/ representing the background image
A new CSS is placed in css/ to utilize the image as the background image
Theme.properties
is modified to reference the new css file
Keycloak uses a bespoke approach to customizing themes using .ftl
files, so some effort is required to get this just right.
These .ftl
files are Freemarker Template Language files. They are used to define the structure and content of the web pages and emails that Keycloak generates, such as login pages, error pages, and email notifications.
Freemarker is a Java-based templating engine that allows to dynamically generate HTML (or other types of content) by injecting variables and applying logic in your templates - a bit like Template Directives in Oracle APEX.
It is often quicker to copy an existing theme from the keycloak-root/themes/
folder and customize that as a new folder.
Keycloak Email Themes
Emails from a base Keycloak installation are quite bland. Just basic text in a HTML. Here is one such example
This is a test message
Below is a general folder layout.
keycloak-root/
└── themes/
└── custom-theme/
├── email/
│ ├── email-verification.ftl
│ ├── password-reset.ftl
│ └── ... (other templates)
├── resources/
│ └── (images, CSS, etc.)
├── theme.properties
└── (other theme folders if necessary, e.g., login, account)
As you can see the resources folder is shared for emails and login pages, etc.
The theme.properties
file need updating with
emailTheme=custom-theme
Container or Bare Metal Install?
For most modern deployments, using Docker for Keycloak is often the preferred choice due to its flexibility, ease of management, and scalability benefits. Docker allows for:
Simplified deployment and updates
Consistent environments across development, testing, and production
Easy integration with container orchestration platforms like Kubernetes for advanced scaling and management
However, if your organization has specific requirements for bare metal performance or direct hardware access, a bare metal installation might be more suitable.
The best deployment method depends on your specific use case, existing infrastructure, and team expertise. Many organizations successfully run Keycloak in Docker without issues, taking advantage of its portability and ease of management - source
The recommended Keycloak image is quay.io/keycloak/keycloak:latest
. This image is hosted by RedHat and is currently recommended by the Keycloak documentation.
Keycloak DB? or no DB?
For Development, by using the start-dev command, Keycloak uses the H2 database by default. This is a file-based H2 database, which is suitable for development and testing purposes but not recommended for production use.
I quote “Keycloak ships for development purposes with an H2 database driver. As it is intended for development purposes only, it should never be used in a production environment.”
For Production, Keycloak has selected PostgreSQL as a first-class database, meaning it receives better tuning, testing, and documentation support.
Keycloak does not plan on offering any second class databases long term, and will phase out support for MySQL, MariaDB, SQL Server, and Oracle over time.
PostgreSQL is widely used and well-documented, making it suitable for both development and production environments,
For running Keycloak with a free PostgreSQL container using Docker, the official PostgreSQL Docker image is recommended - the blog I linked, also recommends a progress DB version for stability, otherwise :latest can be used.
In addition, ensure both Keycloak and Progress are on the same network for seamless integration.
My other blog post details docker-compose configurations for both Dev and prod
Post-Installation Keycloak Configuration
Following installation, the following configuration is recommended:
Change the Admin password from the default
Configuration access policies so only IP/VPN/Whitelists can access the Admin console
Ensure a DB is connected. This can be configured in the docker compose or through the docker command
Ensure HTTPS is enabled
Create a Realm - do not use Master Realm for anything other than Administration
Configure a Client for your application / Oracle APEX.
Create / Import users from Legacy Authentication
Optional: Enable Optional Identity Providers (e.g., Google, Microsoft, or LDAP)
Customize login flows (e.g., multi-factor authentication)
Configure Email Notifications for user communication (password resets, notifications) - here is a guide for setup of Oracle Email
Email Configuration
To configure Keycloak Email go to Realm Settings > Email
If using Oracle Cloud Email for the first time, read this guide first, and then double check the OCI > Email Delivery > Configuration > SMTP Sending Information settings before imputing SMTP details into Keycloak.
Be sure to use the user/pass for the STMP Credentials of a user (i.e. not their actual user/pass or even the ocid/pass).
For example, these are my Oracle Cloud Email settings.
Use the Test Connection button to receive an email.
Backup & Restore
How to Backup Keycloak in a container
These steps involve Exporting the realm(s) and the PostgresSQL DB.
Important: exporting a Realm using the Partial Export feature on the Admin Console does not export users.
Prior to Exporting a Realm
Ensure you delete any JS Default Policy on the Client (presuming you created a client else you will see this on import.
Could not create realm unknown_error
or
(main) ERROR: Failed to start server in (import_export) mode
(main) ERROR: Script upload is disabled
Just perform this action - see blue box.
Exported already without deleting? just search for "name": "Default Policy"
and chop the highlighted bit out, save, and reload it.
Export a Single Realm
Log on to Keycloak
docker exec -it opc-keycloak-1 /bin/bash
Make an export folder
mkdir /opt/keycloak/data/export/
Export your Realm
/opt/keycloak/bin/kc.sh export --realm LUFPOD --file /opt/keycloak/data/export/realm-export.json
Exit
exit
Copy the export out to your host
docker cp opc-keycloak-1:/opt/keycloak/data/export/realm-export.json .
Export all Realms
Export All Realms
docker exec -it opc-keycloak-1 /opt/keycloak/bin/kc.sh export --file /opt/keycloak/data/export/all-realms-export.json
Copy the export out to your host
docker cp opc-keycloak-1:/opt/keycloak/data/export/all-realms-export.json .
Export PostgresSQL
Use with caution and as per your existing backup methods, for example:
Use pg_dump to export
docker exec -it opc-keycloak-postgres pg_dump -U keycloak -d keycloak > keycloak_db_backup.sql
Copy the export back to local machine
docker cp opc-keycloak-postgres:keycloak_db_backup.sql .
Backup the Docker Volume
For a Keycloak themed guide… see here. This guide also includes a restore guide. This may be your best bet for backup & restore.
Backup any changes files, e.g. Themes, custom providers, Plugins, etc
As per your customization.
Export of Keycloak Users
Export up-to 1000 user per file
/opt/keycloak/bin/kc.sh export --users different_files --users-per-file 1000 --dir /opt/keycloak/data/export
Exit and copy the file back to host
docker cp opc-keycloak-1:/opt/keycloak/data/export/LUFPOD-users-0.json .
How to upgrade Keycloak running in a container
Upgrading Keycloak running in a container involves creating a new container
NOTE: Untested
Confirm you have backed up everything & proved that import works
Find your current version of Keycloak
docker exec -it opc-keycloak-1 /opt/keycloak/bin/kc.sh --version
Keycloak 22.0.4 JVM: 17.0.8 (Red Hat, Inc. OpenJDK 64-Bit Server VM 17.0.8+7-LTS) OS: Linux 5.15.0-301.163.5.2.el8uek.x86_64 amd64
Stop the container.
Caution: thatdocker-compose down
does more than just stop the containers; it removes them completely along with associated networks (but not volumes - source).# Docker Compose # docker-compose -f keycloak-compose.yml down # Docker docker stop opc-keycloak-1
Rename old
docker rename opc-keycloak-1 opc-keycloak-old
Pull the latest (approx 450mb) - although pick a version number from here - Q. why? A. source
docker pull quay.io/keycloak/keycloak:26.0.7
Modify your
keycloak-compose.yml
file to the required verisonimage: quay.io/keycloak/keycloak:26.0.7
Bring it back up
docker-compose -f keycloak-compose.yml up -d
Keycloak will automatically detect the older database version and use Liquibase to perform the necessary database schema updates.
Optional : Remove the old container and dangling image
docker rm opc-keycloak-old docker rmi <image_id>
How to restore from backup
Restoring Realms
Use the Interface or use the command line (instructions below)
Copy the backup to the container
docker cp realm-export.json opc-keycloak-1:.
Import it
docker exec -it opc-keycloak-1 /opt/keycloak/bin/kc.sh import --file realm-export.json
[org.keycloak.exportimport.util.ImportUtils] (main) Realm 'LUFPOD' imported
Can’t see the imported Realm in the console?
Workaround: Just Create a new Realm called
DELETE_ME
and delete it. Your imported Realm should now appear.
Restoring the Database
Stop the container
# Docker Compose (perfered) docker-compose -f keycloak-compose.yml down # Docker docker stop opc-keycloak-1
Restore backup
Note: Precise instructions depend on you recovery method. For example an existing DB may need to be dropped and created, then the script ran with psql. A new DB would require use the script running.
Start the container
docker-compose -f keycloak-compose.yml up -d
Restoring the Docker Volume
For a Keycloak themed guide… see here
Restoring Custom Files
As per your existing method.
Integration
APEX integration with Keycloak
APEX uses an Social Sign in Authentication Scheme to authenticate with iDPs like Keycloak. This is usually a sharing of settings between Keycloak and APEX. See also Configuring APEX with Keycloak.
Keycloak’s discovery URL is saved into the Authentication Scheme of APEX
The Realms’ credentials are saved into a Workspace level Web Credentials with a Prompt on Install enabled
When importing the application to production
The Keycloak’s discovery URL will be automatically set to Production Keycloak via an APEX authentication procedure.
On import the Web Credentials are prompted to the user who must type in the production credentials for the Production Keycloak Realm. This is a one-off action.
For more information, see:
Import of users from Legacy Authentication to a Keycloak Realm
Method 1: Plugin Method
To seamlessly switch over from current/legacy authentication to Keycloak without import of the users, read my guide on this subject.
Method 2: Import Users JSON
For this we will use the Keycloak API to bulk load users from our user table into Keycloak. Whilst loading we can optionally send informative emails to the users. Following loading, the users are required to follow the Forgot Password link. This will email them a one-time link, allowing them to set a password. Please read my guide on this
ENJOY
What’ the picture? Nidd Gorge on Boxing Day 2025. The woodland surrounding Nidd Gorge dates back to at least 1600 and is actually composed of five distinct wood
Sources:
https://stackoverflow.com/questions/70052526/how-to-configure-a-keycloak-server-instance-to-support-both-development-and-uat https://keycloak.discourse.group/t/maximum-limit-of-realms/8189 https://www.reddit.com/r/KeyCloak/comments/y6myk6/what_are_different_realms_intended_for/
https://skycloak.io/blog/unlock-safety-secure-your-keycloaks-master-realm-now/
https://www.reddit.com/r/KeyCloak/comments/10vw94r/how_many_realms_should_i_use/