Deployment guide

Keycloak with OpenLDAP 26.8.1

Overview

Keycloak is an open source identity and access management server. It provides single sign-on for your applications over OpenID Connect, OAuth 2.0 and SAML 2.0, with an admin console, an account console for users, and user federation. OpenLDAP is the reference open source LDAP directory server (slapd).

This guide covers launching and using the Keycloak with OpenLDAP 26.8.1 on Ubuntu 24.04 AMI from SecureAnyCloud on Amazon EC2. It is one version of the SecureAnyCloud identity, secrets and PKI listing on AWS Marketplace.

In this image, Keycloak's realm SecureAnyCloud reads its users from the local OpenLDAP directory. A person you add to the directory can sign in through Keycloak straight away, with their password checked by the directory.

What you get:

  • The upstream Keycloak 26.8.1 release. This is the community distribution from the Keycloak project, checked at build time against pinned SHA-256 and SHA-512 hashes and the Keycloak release signing key. It runs in production mode (kc.sh start --optimized) with PostgreSQL 16. It is not a vendor build, and no file is changed.
  • HTTPS from the first boot. nginx is the only public listener (ports 80 and 443). It serves a certificate generated on your instance, an end-entity certificate rather than a certificate authority, and port 80 redirects to HTTPS. Keycloak itself listens on 127.0.0.1 only.
  • No default password anywhere. First boot generates the Keycloak bootstrap administrator, the directory's cn=admin and cn=config passwords, the read-only account Keycloak binds with, and the database password. It writes them to a root-only file. Nothing secret is baked into the image.
  • A locked-down directory. OpenLDAP listens on the loopback address and its local socket only. Ports 389 and 636 are not reachable from the network until you choose to expose LDAPS (Step 13). Anonymous binds and searches are refused, and passwords are stored as Argon2 hashes. Keycloak binds with a least-privilege service account that can read users but cannot write anything or read password hashes.
  • A proxy that cannot be fooled. nginx hands Keycloak the real client address and the configured host name, overwriting any X-Forwarded-* header a client sends. Keycloak trusts those headers only from 127.0.0.1. Requests with path tricks (; parameters, //, encoded slashes) are refused before routing, so the optional source-address list for the admin console (Step 9) cannot be sidestepped.
  • Metadata access blocked. Keycloak can fetch URLs you configure, such as identity-provider discovery, JWKS and LDAP connections. Every service is blocked from the instance metadata service, and the AMI requires IMDSv2.
  • Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.

What is on the image: Keycloak 26.8.1 (/opt/keycloak), OpenLDAP 2.6 (slapd, ldap-utils), PostgreSQL 16, nginx, OpenJDK 21, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent.

Default user: ubuntu. Architecture: x86_64. Recommended instance type: m5.large.

Prerequisites

  • An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet.
  • A security group that allows TCP 22 (SSH) from your own networks only. It must also allow TCP 443 (Keycloak) and TCP 80 (redirects to HTTPS) from the people and applications that sign in. Do not open 389, 636, 5432, 8080 or 9000, because nothing listens on them from the network.
  • For production, a DNS name you control (for example id.example.com) and a certificate from a certificate authority for that name. With it, browsers and applications trust the sign-in pages without a warning.
1

Launch the instance

In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Pick Keycloak with OpenLDAP 26.8.1 on Ubuntu 24.04 as the software version, select your Region, and choose Launch through EC2. Choose m5.large, your key pair and a security group as described above.

To launch with the AWS CLI instead, replace the values in angle brackets:

aws ec2 run-instances --image-id <ami-id-from-the-listing> --instance-type m5.large \
  --key-name <your-key-pair> --security-group-ids <your-security-group> --subnet-id <your-subnet> \
  --metadata-options HttpTokens=required,HttpEndpoint=enabled \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=keycloak-openldap}]'

First boot takes about a minute and a half after cloud-init has run.

To set your own name or directory base DN from the start, put them in /etc/sac/keycloak-openldap-domain.preset and /etc/sac/keycloak-openldap-basedn.preset with user data, for example cloud-init write_files entries.

Otherwise, first boot uses the instance's public DNS name (or its private name) and the base DN dc=example,dc=com. You can change both later (Steps 10 and 11).

2

Connect to your instance

Connect over SSH with your key pair. For Ubuntu 24.04, the SSH user is ubuntu.

ssh -i <your-key.pem> ubuntu@<public-ip>
3

Check the services

systemctl is-active keycloak-openldap-firstboot postgresql@16-main slapd keycloak nginx
active active active active active

Only SSH, HTTP and HTTPS are public. Keycloak (8080), its management interface (9000, health checks), OpenLDAP (389) and PostgreSQL (5432) listen on the loopback address only. Java lists its loopback sockets as [::ffff:127.0.0.1]:

sudo ss -tln | awk '{print $4}' | grep -E ':(22|80|389|443|636|5432|8080|9000)$' | sort -u
0.0.0.0:22 0.0.0.0:443 0.0.0.0:80 127.0.0.1:389 127.0.0.1:5432 [::]:22 [::]:443 [::]:80 [::ffff:127.0.0.1]:8080 [::ffff:127.0.0.1]:9000

A health endpoint for monitoring agents on the instance itself:

curl -s http://127.0.0.1:9000/health/ready; echo
{ "status": "UP", "checks": [ { "name": "Graceful Shutdown", "status": "UP" }, { "name": "Keycloak Initialized", "status": "UP" } ] }
4

Your addresses and credentials

Everything that first boot generated is in a root-only file (mode 0600). Show it without the password lines first:

sudo grep -v PASSWORD /root/keycloak-openldap-credentials.txt
# Keycloak 26.8.1 with OpenLDAP - written on first boot by keycloak-openldap-firstboot.service. Unique to this instance. KEYCLOAK_URL=https://ec2-3-88-34-254.compute-1.amazonaws.com/ KEYCLOAK_CONSOLE_URL=https://ec2-3-88-34-254.compute-1.amazonaws.com/admin/ KEYCLOAK_ACCOUNT_CONSOLE=https://ec2-3-88-34-254.compute-1.amazonaws.com/realms/sac/account/ KEYCLOAK_BOOTSTRAP_ADMIN_USER=bootstrap-admin KEYCLOAK_REALM=sac LDAP_URL=ldap://127.0.0.1:389 LDAP_BASE_DN=dc=example,dc=com LDAP_PEOPLE_DN=ou=people,dc=example,dc=com LDAP_ADMIN_DN=cn=admin,dc=example,dc=com LDAP_CONFIG_DN=cn=admin,cn=config LDAP_KEYCLOAK_BIND_DN=cn=keycloak,ou=services,dc=example,dc=com TLS_SHA256=59:5E:FC:03:8E:CD:B3:3A:9D:C3:CB:84:80:FA:52:FD:82:86:A1:51:8B:51:5B:3D:4C:99:B4:04:9C:43:23:A2 TLS_SPKI_SHA256=KCVGumS779UZ4MBUK5iZKpsuCLOkucf4jr71nagPCxY=
#
# Keycloak: sign in to the admin console at KEYCLOAK_CONSOLE_URL as KEYCLOAK_BOOTSTRAP_ADMIN_USER. It is a TEMPORARY bootstrap
# admin: create your own permanent admin in the master realm, then delete bootstrap-admin (see the guide).
# Directory users live under LDAP_PEOPLE_DN and sign in to realm "sac" (KEYCLOAK_ACCOUNT_CONSOLE) through the LDAP
# federation. Add one:
sudo sac-ldap ldapadd -f user.ldif (binds as LDAP_ADMIN_DN; no password on the command line)
# OpenLDAP and PostgreSQL listen on 127.0.0.1 only; the Keycloak database password is in /etc/keycloak/keycloak.conf.
# The HTTPS certificate is self-signed and unique to this instance: compare its SHA-256 fingerprint (TLS_SHA256), or
# replace it with a CA-issued certificate for your own name. Your own name:
sudo keycloak-openldap-set-domain id.example.com
# Your own base DN (while the directory has no users):
sudo keycloak-openldap-set-basedn dc=corp,dc=example,dc=com
# User guide: https://secureanycloud.com/stacks/keycloak-with-openldap-26-8-1/

The file also holds KEYCLOAK_BOOTSTRAP_ADMIN_PASSWORD, LDAP_ADMIN_PASSWORD, LDAP_CONFIG_PASSWORD and LDAP_KEYCLOAK_BIND_PASSWORD. Read the one you need when you need it, for example sudo grep '^KEYCLOAK_BOOTSTRAP_ADMIN_PASSWORD=' /root/keycloak-openldap-credentials.txt.

The database password is only in /etc/keycloak/keycloak.conf, which is readable by root and the keycloak service account.

The certificate is self-signed and unique to your instance. Do not add it to a trust store. Instead, compare its fingerprint (TLS_SHA256) with the one your browser shows, or replace it with a CA-issued certificate (Step 10).

5

Run the self-test

sudo keycloak-openldap-selftest

The self-test runs these checks in order:

  • An anonymous LDAP bind and search are refused.
  • It adds a throwaway user to the directory as the directory administrator. The password is stored as an Argon2 hash.
  • It signs that user in to realm SecureAnyCloud over HTTPS through the LDAP federation.
  • It verifies the access token's signature against the realm's published keys. A tampered token fails.
  • A wrong password is refused.
  • It removes the user from the directory and from Keycloak.
round trip OK: anonymous LDAP refused; ldapadd as admin ({ARGON2} stored); LDAP user -> realm sac token, RS256 verified against the JWKS (tampered token refused); wrong password refused; user removed KEYCLOAK_OPENLDAP_SELFTEST_OK
6

Sign in to the admin console

Open KEYCLOAK_CONSOLE_URL (https://<your-name>/admin/) in a browser. Accept the certificate after comparing its fingerprint, and sign in as bootstrap-admin with KEYCLOAK_BOOTSTRAP_ADMIN_PASSWORD.

Keycloak marks this account as a temporary admin. Create your own permanent administrator now, then delete bootstrap-admin:

  • In the master realm, open Users and select Add user. Set a username.
  • On the user's Credentials tab, set a password.
  • On Role mapping, assign the realm role admin.
  • Sign out, then sign in as your new administrator.
  • Delete bootstrap-admin under Users.

The helper keycloak-openldap-set-basedn and the self-test sign in with the KEYCLOAK_BOOTSTRAP_ADMIN_* lines of the credentials file. Put your own administrator there if you want to keep using them.

Switch to realm SecureAnyCloud and open User federation. The provider openldap reads users from ou=people,<base DN> on ldap://127.0.0.1:389, in READ_ONLY edit mode, bound as cn=keycloak,ou=services,<base DN>.

7

Add a directory user and sign in with it

sac-ldap runs any ldap* tool against the local directory, bound as the directory administrator (LDAP_ADMIN_DN). The password goes to the tool in a root-only temporary file, never on the command line.

Users go under ou=people with the inetOrgPerson object class. The server hashes a clear-text password (Argon2) before it stores it.

B=$(sudo sed -n 's/^LDAP_BASE_DN=//p' /root/keycloak-openldap-credentials.txt)
PW=$(openssl rand -base64 18) printf 'dn: uid=alice,ou=people,%s\nobjectClass: inetOrgPerson\nuid: alice\ncn: Alice Example\nsn: Example\ngivenName: Alice\nmail: alice@example.com\nuserPassword: %s\n' "$B" "$PW" > /tmp/alice.ldif
sudo sac-ldap ldapadd -f /tmp/alice.ldif shred -u /tmp/alice.ldif printf '%s' "$PW" > /tmp/alice.pw && chmod 600 /tmp/alice.pw echo "alice's password is in /tmp/alice.pw"
adding new entry "uid=alice,ou=people,dc=example,dc=com" alice's password is in /tmp/alice.pw

Alice can now sign in to realm SecureAnyCloud. In a browser, open KEYCLOAK_ACCOUNT_CONSOLE (https://<your-name>/realms/sac/account/) and sign in as alice.

The following commands run the same sign-in from the command line. They check the ID token's signature against the realm's public keys, and the token itself is never printed:

D=$(head -1 /etc/sac/keycloak-openldap-domain)
curl -s --cacert /etc/ssl/keycloak-openldap/server.crt --resolve "$D:443:127.0.0.1" \
  -d grant_type=password -d client_id=admin-cli -d 'scope=openid profile' -d username=alice \
  --data-urlencode "password@/tmp/alice.pw" "https://$D/realms/sac/protocol/openid-connect/token" \
  | jq -r .id_token > /tmp/alice.jwt curl -s --cacert /etc/ssl/keycloak-openldap/server.crt --resolve "$D:443:127.0.0.1" \
  "https://$D/realms/sac/protocol/openid-connect/certs" > /tmp/realm-jwks.json
V=$(python3 /usr/local/lib/sac/keycloak-openldap/jwt-verify.py /tmp/alice.jwt /tmp/realm-jwks.json "https://$D/realms/sac") shred -u /tmp/alice.jwt; echo "$V" [[ "$V" == "JWT_VERIFY OK"* ]]
JWT_VERIFY OK kid=QvhElW9h iss=https://ec2-3-88-34-254.compute-1.amazonaws.com/realms/sac user=alice

The admin-cli client and the password grant are used here only to show the flow from a shell. Your applications should register their own client in realm SecureAnyCloud (Clients, Create client) and use the authorization code flow with PKCE. The realm's discovery document is at https://<your-name>/realms/sac/.well-known/openid-configuration.

To remove a user, delete the directory entry and Keycloak's imported copy of it. Keycloak keeps the imported copy, which is linked to the old entry's entryUUID, until it next looks the user up. A new directory entry with the same username cannot sign in while that copy exists.

The block below does both. It signs in to Keycloak's admin API with the credentials file's admin account, passing the password through a root-only file and never the command line:

B=$(sudo sed -n 's/^LDAP_BASE_DN=//p' /root/keycloak-openldap-credentials.txt)
sudo sac-ldap ldapdelete "uid=alice,ou=people,$B"
sudo bash -c 'umask 077; sed -n "s/^KEYCLOAK_BOOTSTRAP_ADMIN_PASSWORD=//p" /root/keycloak-openldap-credentials.txt | tr -d "\n" > /run/kc-admin.pw'
TOK=$(sudo curl -s http://127.0.0.1:8080/realms/master/protocol/openid-connect/token -d grant_type=password -d client_id=admin-cli \
  -d username=bootstrap-admin --data-urlencode "password@/run/kc-admin.pw" | jq -r .access_token)
sudo shred -u /run/kc-admin.pw U="http://127.0.0.1:8080/admin/realms/sac/users?username=alice&exact=true" curl -s -o /dev/null -H "Authorization: Bearer $TOK" "$U"
# the lookup itself drops a copy whose entry is gone
ID=$(curl -s -H "Authorization: Bearer $TOK" "$U" | jq -r '.[0].id // empty') [ -n "$ID" ] && curl -s -o /dev/null -X DELETE -H "Authorization: Bearer $TOK" "http://127.0.0.1:8080/admin/realms/sac/users/$ID" echo "alice in Keycloak: $(curl -s -H "Authorization: Bearer $TOK" "$U" | jq length)" unset TOK; shred -u /tmp/alice.pw /tmp/realm-jwks.json 2>/dev/null; rm -f /tmp/realm-jwks.json; true

If you replaced bootstrap-admin with your own administrator, use that account. Alternatively, delete the user under Users in realm SecureAnyCloud in the admin console.

8

Working with the directory

Search the people branch as the directory administrator. Password hashes are never shown to anyone but root over the local socket:

B=$(sudo sed -n 's/^LDAP_BASE_DN=//p' /root/keycloak-openldap-credentials.txt)
sudo sac-ldap ldapsearch -LLL -b "$B" -s one dn
dn: ou=groups,dc=example,dc=com dn: ou=people,dc=example,dc=com dn: ou=services,dc=example,dc=com

Anonymous access is refused:

ldapsearch -x -H ldap://127.0.0.1:389 -b "dc=example,dc=com" -s base dn 2>&1 | head -2 || true
ldap_bind: Inappropriate authentication (48) additional info: anonymous bind disallowed

root can also manage the directory and its configuration without a password over the local socket, for example sudo ldapsearch -Q -Y EXTERNAL -H ldapi:/// -b cn=config dn.

To change a user's password, run sudo sac-ldap ldappasswd -S "uid=alice,ou=people,<base DN>", which prompts for the new password.

Group entries (groupOfNames) go under ou=groups. To map them to Keycloak groups, add a group-ldap-mapper to the openldap provider in the admin console.

9

Restrict the admin console to your own networks

Everyone who can reach port 443 can see the admin sign-in page. To limit the admin console (/admin) and the master realm (/realms/master, where administrators sign in) to your own addresses, edit the access list and reload nginx:

sudo cat /etc/nginx/sac/keycloak-admin-access.conf
# sac: who may reach the Keycloak admin console (/admin) and the master realm (/realms/master: admin sign-in and
# admin tokens). Default: everyone (the admin password is the control). To restrict, replace "allow all;" with your
# networks, then:
sudo nginx -t && sudo systemctl reload nginx
# allow 203.0.113.0/24;
# allow 198.51.100.7;
# deny all; allow all;

Replace allow all; with lines such as allow 203.0.113.0/24; followed by deny all;, then run sudo nginx -t && sudo systemctl reload nginx.

Realm SecureAnyCloud, which serves your users' sign-in pages and your applications' endpoints, stays reachable. The list is matched on the decoded, case-insensitive path. Paths with ;, // or encoded slashes are refused before routing, so spellings such as /realms/MASTER/ or /realms/master;x=1/ cannot get round it.

10

Use your own domain and certificate

Point a DNS name at the instance. An Elastic IP is a good idea. Then run:

sudo keycloak-openldap-set-domain id.example.com

This command sets Keycloak's host name (hostname=https://id.example.com in /etc/keycloak/keycloak.conf) and nginx's server names, and unknown host names are dropped. It also makes a new per-instance certificate for the name, then restarts Keycloak and nginx. Update the redirect URIs of any clients you registered under the old name.

To use a certificate from a certificate authority, replace /etc/ssl/keycloak-openldap/server.crt and server.key, keeping the key at mode 0600 and owned by root. Then run sudo nginx -t && sudo systemctl reload nginx.

11

Use your own directory base DN

The directory starts as dc=example,dc=com. While it holds no users or groups, you can move it to your own base DN in one step. Every password stays the same, and Keycloak's federation follows:

sudo keycloak-openldap-set-basedn dc=corp,dc=example,dc=com

The command refuses when ou=people or ou=groups already holds entries, or when Keycloak holds users imported from the directory. In that case, export your entries (sudo slapcat -n 1), rewrite the DNs, and import them into a directory created with the new base DN.

12

Check the security posture

Every service is blocked from the instance metadata service, and core dumps are off:

systemctl show -p IPAddressDeny -p LimitCORE keycloak slapd nginx postgresql@16-main keycloak-openldap-firstboot
IPAddressDeny=fd00:ec2::254/128 ::ffff:169.254.169.254/128 168.63.129.16/32 169.254.169.254/32 LimitCORE=0 IPAddressDeny=fd00:ec2::254/128 ::ffff:169.254.169.254/128 168.63.129.16/32 169.254.169.254/32 LimitCORE=0 IPAddressDeny=fd00:ec2::254/128 ::ffff:169.254.169.254/128 168.63.129.16/32 169.254.169.254/32 LimitCORE=0 IPAddressDeny=fd00:ec2::254/128 ::ffff:169.254.169.254/128 168.63.129.16/32 169.254.169.254/32 LimitCORE=0 IPAddressDeny=fd00:ec2::254/128 ::ffff:169.254.169.254/128 168.63.129.16/32 169.254.169.254/32 LimitCORE=0

PostgreSQL listens on 127.0.0.1 only, and only the keycloak role has a password. The postgres superuser is reachable only as the local postgres account:

sudo -u postgres psql -X -tA -c "SHOW listen_addresses" -c "SELECT rolname FROM pg_authid WHERE rolpassword IS NOT NULL"
127.0.0.1 keycloak

The directory refuses anonymous binds and stores passwords as Argon2 hashes. The service account Keycloak uses can read users but not write:

sudo ldapsearch -Q -LLL -o ldif-wrap=no -Y EXTERNAL -H ldapi:/// -b cn=config '(objectClass=olcGlobal)' olcDisallows olcRequires
sudo ldapsearch -Q -LLL -o ldif-wrap=no -Y EXTERNAL -H ldapi:/// -b 'olcDatabase={1}mdb,cn=config' olcAccess
dn: cn=config olcDisallows: bind_anon olcRequires: authc dn: olcDatabase={1}mdb,cn=config olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break olcAccess: {1}to attrs=userPassword,shadowLastChange by self =wx by anonymous auth by * none olcAccess: {2}to dn.subtree="dc=example,dc=com" by dn.exact="cn=keycloak,ou=services,dc=example,dc=com" read by self read by * none dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config
13

Expose LDAPS to your own networks (optional)

By default, no LDAP port is reachable from the network, and applications sign users in through Keycloak. If systems elsewhere must query the directory directly, serve LDAPS (636) with a certificate. Open 636 in the security group to those systems only.

The following sketch uses the instance's own certificate. Replace it with a CA-issued certificate for production:

sudo install -d -o openldap -g openldap -m 0750 /etc/ldap/tls
sudo install -o openldap -g openldap -m 0600 /etc/ssl/keycloak-openldap/server.key /etc/ldap/tls/ldap.key
sudo install -o openldap -g openldap -m 0644 /etc/ssl/keycloak-openldap/server.crt /etc/ldap/tls/ldap.crt printf 'dn: cn=config\nchangetype: modify\nreplace: olcTLSCertificateFile\nolcTLSCertificateFile: /etc/ldap/tls/ldap.crt\n-\nreplace: olcTLSCertificateKeyFile\nolcTLSCertificateKeyFile: /etc/ldap/tls/ldap.key\n' | sudo ldapmodify -Q -Y EXTERNAL -H ldapi:///
sudo sed -i 's#ldap://127.0.0.1:389/#ldap://127.0.0.1:389/ ldaps:///#' /etc/systemd/system/slapd.service
sudo systemctl daemon-reload && sudo systemctl restart slapd

Clients then use ldaps://<your-name> and must bind as a user, because anonymous binds stay refused. Create a separate read-only service account for each consuming system rather than sharing Keycloak's.

14

Your data and backups

  • Keycloak keeps realms, clients, users imported from the directory and sessions in PostgreSQL: sudo -u postgres pg_dump -Fc keycloak > keycloak-$(date +%F).dump.
  • The directory is in /var/lib/ldap and its configuration in /etc/ldap/slapd.d: sudo slapcat -n 1 > directory-$(date +%F).ldif and sudo slapcat -n 0 > config-$(date +%F).ldif. The exports contain password hashes, so store them like secrets.
  • Keep /root/keycloak-openldap-credentials.txt and /etc/keycloak/keycloak.conf with the backups. For a larger directory, move /var/lib/ldap to its own EBS volume.
15

Licences and source

Keycloak is licensed under the Apache License 2.0. The image runs the unmodified upstream distribution:

cat /usr/share/doc/sac-keycloak-openldap/SOURCE.txt
cat /opt/keycloak/version.txt
Keycloak 26.8.1 (Apache License 2.0, https://www.keycloak.org/) - the upstream community distribution: https://github.com/keycloak/keycloak/releases/download/26.8.1/keycloak-26.8.1.tar.gz sha256 4e2740b181faa2ea623a1c2ecf00855935311e546046e2f857615a47ed24cbe8 sha512 b891ae56095dd8536547668b839ff2f63971ed402a976b6be4db2f83cb3f9dd709a321c99b2d92030c81588ec8e1842813e219c5ba3a7ea2f059e98176abe7df signed by the Keycloak release key 861AB50E8CC6611FB6BC01A6B8F12EA26FD6EEBA (verified at build) No file is changed; "kc.sh build" (db=postgres, health-enabled=true) generated lib/quarkus. keycloak-tree.sha256 lists every file of /opt/keycloak (except data/) as built. Source: https://github.com/keycloak/keycloak/tree/26.8.1 OpenLDAP 2.6 (slapd, ldap-utils), PostgreSQL 16, nginx and OpenJDK 21 are Ubuntu 24.04 packages (main); their licences are in /usr/share/doc/<package>/copyright (OpenLDAP: The OpenLDAP Public License 2.8). Keycloak - Version 26.8.1

OpenLDAP is distributed under The OpenLDAP Public License 2.8 (/usr/share/doc/slapd/copyright). PostgreSQL, nginx and OpenJDK are Ubuntu packages under their own licences (/usr/share/doc/<package>/copyright).

16

Security notes

  • Advisories. No published Keycloak advisory affects 26.8.1, and Ubuntu's OpenLDAP 2.6.10 package has no open advisory. A dependency scan of the Keycloak distribution lists four library advisories with no fixed Keycloak release yet. None is reachable in this configuration:
    • Guava CVE-2026-102554 (Java deserialization of untrusted data, which Keycloak does not do)
    • OpenTelemetry CVE-2026-118259 (tracestate header parsing; tracing is off and nginx strips the tracing headers)
    • MariaDB Connector/J CVE-2026-119210/119276/119280/119281 (the server is built for PostgreSQL, so the MariaDB driver is never loaded)
  • Temporary admin. bootstrap-admin is meant to be replaced (Step 6). Keycloak's brute-force protection is on in both realms, and nginx rate-limits sign-in and token requests per client address.
  • Directory passwords. The directory stores the passwords it is given as hashes. Keycloak never sees or stores directory passwords. It asks the directory to check them. Keycloak's federation is read-only, so password changes happen in the directory (ldappasswd).
  • Deprecated features off. The image disables Keycloak's deprecated identity-brokering-api:v1 and twitter-broker:v1 features.

Support

SecureAnyCloud provides support for this image by email at sales@secureanycloud.com. Keycloak is documented at https://www.keycloak.org/documentation and OpenLDAP at https://www.openldap.org/doc/.

Keycloak is a Cloud Native Computing Foundation project, and OpenLDAP is a registered trademark of the OpenLDAP Foundation. SecureAnyCloud is not affiliated with or endorsed by the CNCF, the Keycloak project, Red Hat or the OpenLDAP Foundation.

Deploy on AWS

Launch Keycloak with OpenLDAP 26.8.1 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.

View on Marketplace

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on AWS