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):
Create BCFKS 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"
If you encounter a permissions-related error, grant write permissions to your working directory and rerun the above command:
sudo chown 1000:1000 "$(pwd)"
chmod 700 "$(pwd)"
Verify the BCFKS 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 Server Certificate (PEM)

To set up HTTPS using PEM files (instead of a keystore), follow the steps to create a local CA and sign a server certificate.
  1. Generate a private key for the Certificate Authority (CA):
    openssl genrsa -out myCA.key 4096
    # Saves the key to the output file myCA.key
    # Sets the key size to 4096 bits for extra security
    
  2. Create a root self-signed CA certificate:
    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"
    
  3. Generate a Server RSA private key for Keycloak:
    openssl genrsa -out keycloak.key 2048
    # Saves the key to the output file keycloak.key
    # Sets the key size to 2048 bits for extra security
    
  4. 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"
    
  5. Create a file keycloak.ext containing certificate extension settings for a TLS certificate:
    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
    
  6. Sign a Certificate Signing Request (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
  1. 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:
Import CA into 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 -d --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 -d --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'
Visit the Keycloak console (UI) in HTTPS at https://localhost:8443.
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.keystore so only the file owner has read/write access and nobody else has access:
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.
Last modified on January 28, 2026