Skip to main content
To deploy Keycloak in FIPS mode, you need a FIPS-approved keystore. In this tutorial we will use the Bouncy Castle FIPS KeyStore (termed BCFKS). A BCFKS keystore is a Java KeyStore (JKS) format provided by Bouncy Castle that is specifically designed for FIPS-compliant cryptography. The following guide involves the following components:
FilePurpose
server.keystore (BCFKS)FIPS-approved keystore (private key + cert)
truststore.bcfksFIPS-approved truststore (contains CA certs)
myCA.crt / myCA.keyLocal CA (root) for signing/trusting dev certs
keycloak.crt / keycloak.keyServer certificate & key (PEM) for Keycloak
Prerequisites
  • Docker available locally
  • Token to pull images from the Minimus image registry
  • A working directory for keystores and certs

Deploy Keycloak for production in HTTPS mode (or in HTTP dev mode)

1

Create a BCFKS Keystore (FIPS‑approved)

Use keytool from the Keycloak FIPS image to generate a BCFKS keystore and keypair (provider CCJ):
Docker run command to create keystore
docker run --rm \
  -v "$(pwd)":/tmp/keystore  \
  --entrypoint keytool  \
  reg.mini.dev/keycloak-fips \
  -J-Djava.security.properties=/usr/share/conf/java.security.append \
  -J-cp -J"/opt/keycloak/providers/*" \
  -v   -keystore /tmp/keystore/server.keystore \
  -storetype bcfks  \
  -providername CCJ \
  -alias "localhost" \
  -genkeypair  \
  -sigalg SHA512withRSA  \
  -keyalg RSA  \
  -dname CN="localhost" \
  -storepass "minimusstoretest2025"  \
  -keypass "minimusstorekeypass2025"
Verify the BCFKS keystore:
Verify the keystore
docker run --rm -v "$(pwd)":/tmp/keystore  \
  --entrypoint keytool  \
  reg.mini.dev/keycloak-fips \
  -J-Djava.security.properties=/usr/share/conf/java.security.append \
  -J-cp -J"/opt/keycloak/providers/*"  \
  -v   -keystore /tmp/keystore/server.keystore  \
  -storetype bcfks \
  -list   -storepass "minimusstoretest2025"
2

Generate a Local CA and a Server Certificate (PEM)

To set up HTTPS using PEM files (instead of a keystore), create a local CA and sign a server cert:
# 1) CA private key + self‑signed CA cert
openssl genrsa -out myCA.key 4096
openssl req -x509 -new -nodes -key myCA.key \
 -sha256 -days 3650 -out myCA.crt  \
 -subj "/C=US/ST=Local/L=Local/O=MyOrg/OU=Dev/CN=MyLocalCA"

# 2) Server private key for Keycloak
openssl genrsa -out keycloak.key 2048

# 3) CSR for your Keycloak host (edit CN)
openssl req -new -key keycloak.key \
  -out keycloak.csr   \
  -subj "/C=US/ST=Local/L=Local/O=MyOrg/OU=Dev/CN=keycloak.local"

# 4) SAN extension
cat > keycloak.ext <<EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = keycloak.local
DNS.2 = localhost
EOF

# 5) Sign CSR with your CA
openssl x509 -req -in keycloak.csr \
-CA myCA.crt -CAkey myCA.key -CAcreateserial \
-out keycloak.crt -days 825 -sha256 -extfile keycloak.ext
Run ls to verify that the following certificates were created:
  • CA: myCA.crt, myCA.key, myCA.srl
  • Server (PEM): keycloak.crt, keycloak.key, keycloak.csr, keycloak.ext
3

Create a BCFKS Truststore (to trust your CA)

Import your CA into a BCFKS truststore:
docker run --rm -v "$(pwd)":/tmp/keystore \
  --entrypoint keytool  \
  reg.mini.dev/keycloak-fips \
  -J-Djava.security.properties=/usr/share/conf/java.security.append  \
  -J-cp -J"/opt/keycloak/providers/*"  \
  -v   -keystore /tmp/keystore/truststore.bcfks  \
  -storetype bcfks   -providername CCJ  \
  -import   -file /tmp/keystore/myCA.crt  \
  -storepass "minimusstoretest2025"   -trustcacerts   -noprompt
4

Run Keycloak

To run in dev mode, deploy Keycloak in HTTP:
Run Keycloak in HTTP
docker run --rm -p 8080:8080 \
-e KC_BOOTSTRAP_ADMIN_USERNAME=minimusadmin \
-e KC_BOOTSTRAP_ADMIN_PASSWORD=minimusadminpass2025 \
reg.mini.dev/keycloak-fips \
start-dev --features=fips  --fips-mode=strict \
--https-key-store-password='minimusstoretest2025' \
--hostname=localhost   --log-level='INFO'
Visit the Keycloak console (UI) at http://localhost:8080.
Even in HTTP mode, FIPS checks still apply to admin and other passwords so ensure they have at least 14 characters.
To run in production, deploy Keycloak with the truststore in HTTPS:
Run Keycloak in HTTPS
docker run --rm -p 8443:8443 \
  -v "$(pwd)/keycloak.crt":/opt/keycloak/conf/tls.crt:ro \
  -v "$(pwd)/keycloak.key":/opt/keycloak/conf/tls.key:ro \
  -e KC_HTTPS_CERTIFICATE_FILE=/opt/keycloak/conf/tls.crt \
  -e KC_HTTPS_CERTIFICATE_KEY_FILE=/opt/keycloak/conf/tls.key \
  -e KC_BOOTSTRAP_ADMIN_USERNAME=minimusadmin2025 \
  -e KC_BOOTSTRAP_ADMIN_PASSWORD=minimusadmin2025 \
  reg.mini.dev/keycloak-fips \
  start  --features=fips       --fips-mode=strict  \
  --https-key-store-password='minimusstoretest2025'  \
  --hostname=localhost       --log-level='INFO'
5

Trust the CA locally (browser/curl)

sudo cp myCA.crt /usr/local/share/ca-certificates/myCA.crt
sudo update-ca-certificates
6

File hygiene

Change the file permissions in server.keystoreso only the file owner can read/write to it, and nobody else can access it:
chmod 600 *.key server.keystore *.bcfks || true

Troubleshooting

If you get an error password must be at least 112 bits, it means that one or more passwords is under 14 characters long. Passwords should be 16-24 characters. Check the passwords for the following variables: KC_BOOTSTRAP_ADMIN_PASSWORD, KC_HTTPS_KEY_STORE_PASSWORD, truststore password, etc.