Production ready Keycloak Checklist for Oracle APEX

Production ready Keycloak Checklist for Oracle APEX

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:

  1. Independent environments: Dev and prod environments remain completely separate, preventing any accidental changes in Dev from affecting prod

  2. 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:

  1. Each instance can be optimized for its specific environment's needs

  2. 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:

  1. You can test new Keycloak versions in dev without risking prod stability

  2. Each instance can have its own settings tailored to Dev or prod requirements

  3. Changes can be trialed on Dev without affecting prod

Best Practices

Following best practices for Keycloak deployment:

  1. Dev and prod environments often have different security requirements and user bases e.g. prod may have MFA whereas Dev may not.

  2. Realistic testing: A separate Dev instance allows for more accurate testing of your production setup.

  3. 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:

  1. Simplified deployment and updates

  2. Consistent environments across development, testing, and production

  3. 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 quoteKeycloak 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

  1. Log on to Keycloak

     docker exec -it opc-keycloak-1 /bin/bash
    
  2. Make an export folder

     mkdir /opt/keycloak/data/export/
    
  3. Export your Realm

     /opt/keycloak/bin/kc.sh export --realm LUFPOD --file /opt/keycloak/data/export/realm-export.json
    

  4. Exit

     exit
    
  5. Copy the export out to your host

     docker cp opc-keycloak-1:/opt/keycloak/data/export/realm-export.json .
    

Export all Realms

  1. Export All Realms

     docker exec -it opc-keycloak-1 /opt/keycloak/bin/kc.sh export --file /opt/keycloak/data/export/all-realms-export.json
    
  2. 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:

  1. Use pg_dump to export

     docker exec -it opc-keycloak-postgres pg_dump -U keycloak -d keycloak > keycloak_db_backup.sql
    
  2. 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

  1. 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
    
  2. 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

  1. Confirm you have backed up everything & proved that import works

  2. 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
    
  3. Stop the container.
    Caution: that docker-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
    
  4. Rename old

     docker rename opc-keycloak-1 opc-keycloak-old
    
  5. 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
    
  6. Modify your keycloak-compose.yml file to the required verison

      image: quay.io/keycloak/keycloak:26.0.7
    
  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.

  8. 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)

  1. Copy the backup to the container

     docker cp realm-export.json opc-keycloak-1:.
    
  2. 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
    
  3. 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

  1. Stop the container

     # Docker Compose (perfered)
      docker-compose -f keycloak-compose.yml down
    
     # Docker
     docker stop opc-keycloak-1
    
  2. 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.

  1. 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: