Skip to content

Instantly share code, notes, and snippets.

@jrschumacher
Last active May 21, 2025 12:02
Show Gist options
  • Save jrschumacher/caa44f66fc24f88e050cbaa1f1948098 to your computer and use it in GitHub Desktop.
Save jrschumacher/caa44f66fc24f88e050cbaa1f1948098 to your computer and use it in GitHub Desktop.
Run Docker Compose with Architecture-Specific Java Flags for Apple Silicon (M4 SVE Workaround)
#!/bin/bash
# This script detects the host CPU architecture and specific Apple Silicon model
# to apply necessary Java options for Keycloak to avoid SIGILL errors.
HOST_ARCH=$(uname -m)
OSTYPE=$(uname)
EXTRA_JAVA_OPTS=""
echo "Detecting host architecture: $HOST_ARCH on $OSTYPE"
if [[ "$OSTYPE" == "Darwin" && "$HOST_ARCH" == "arm64" ]]; then
# Running on macOS ARM (Apple Silicon)
CPU_BRAND_STRING=$(sysctl -n machdep.cpu.brand_string)
echo "Detected Apple Silicon CPU: $CPU_BRAND_STRING"
# Check if the CPU brand string contains "M4"
# This pattern might need adjustment if future M-series chips behave differently.
# The "*-Pro", "*-Max", "*-Ultra" variants usually share the base chip generation.
if [[ "$CPU_BRAND_STRING" == *"M4"* ]]; then
echo "Detected M4 chip. Setting JAVA_OPTS_APPEND for SVE workaround."
EXTRA_JAVA_OPTS="-XX:UseSVE=0"
else
# Assume M1, M2, M3, or other future chips not needing the workaround
echo "Detected M1, M2, M3, or other chip. No specific JAVA_OPTS_APPEND needed."
EXTRA_JAVA_OPTS="" # Ensure it's empty if not M4
fi
else
# Not running on macOS ARM (either x86_64 or Linux ARM, etc.)
echo "Not running on macOS ARM. No specific JAVA_OPTS_APPEND needed."
EXTRA_JAVA_OPTS="" # Ensure it's empty
fi
export EXTRA_JAVA_OPTS
echo "EXTRA_JAVA_OPTS set to: '$EXTRA_JAVA_OPTS'"
# Now run docker compose, passing the EXTRA_JAVA_OPTS environment variable.
# The ${EXTRA_JAVA_OPTS} syntax in the docker-compose.yaml will pick this up.
docker compose "$@" # Pass along any arguments given to the script (e.g., up -d)
services:
keycloak:
volumes:
- ./certs:/etc/x509/tls/
- ./truststore:/truststore/
image: keycloak/keycloak:25.0
restart: always
command:
- "start-dev"
- "--verbose"
- "-Djavax.net.ssl.trustStorePassword=password"
- "-Djavax.net.ssl.HostnameVerifier=AllowAll"
- "-Djavax.net.ssl.trustStore=/truststore/truststore.jks"
- "--spi-truststore-file-hostname-verification-policy=ANY"
ports:
- "9001:9001"
- "8888:8888"
- "8443:8443"
healthcheck:
test:
- CMD-SHELL
- |
[ -f /tmp/HealthCheck.java ] || echo "public class HealthCheck {
public static void main(String[] args) throws java.lang.Throwable {
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true);
javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance(\"SSL\");
sc.init(null, new javax.net.ssl.TrustManager[]{
new javax.net.ssl.X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; }
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {}
}
}, new java.security.SecureRandom());
javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
java.net.HttpURLConnection conn = (java.net.HttpURLConnection)new java.net.URL(args[0]).openConnection();
System.exit(java.net.HttpURLConnection.HTTP_OK == conn.getResponseCode() ? 0 : 1);
}
}" > /tmp/HealthCheck.java && java /tmp/HealthCheck.java https://localhost:9001/auth/health/live
timeout: 10s
retries: 3
start_period: 2m
environment:
KC_PROXY: edge
KC_HTTP_RELATIVE_PATH: /auth
KC_DB_VENDOR: postgres
KC_DB_URL_HOST: keycloakdb
KC_DB_URL_PORT: 5432
KC_DB_URL_DATABASE: keycloak
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: changeme
KC_HOSTNAME_STRICT: "false"
KC_HOSTNAME_STRICT_BACKCHANNEL: "false"
KC_HOSTNAME_STRICT_HTTPS: "false"
KC_HTTP_ENABLED: "true"
KC_HTTP_PORT: "8888"
KC_HTTPS_PORT: "8443"
KC_HTTP_MANAGEMENT_PORT: "9001"
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: changeme
#KC_HOSTNAME_URL: http://localhost:8888/auth
KC_FEATURES: "preview,token-exchange"
KC_HEALTH_ENABLED: "true"
KC_HTTPS_KEY_STORE_PASSWORD: "password"
KC_HTTPS_KEY_STORE_FILE: "/truststore/truststore.jks"
KC_HTTPS_CERTIFICATE_FILE: "/etc/x509/tls/localhost.crt"
KC_HTTPS_CERTIFICATE_KEY_FILE: "/etc/x509/tls/localhost.key"
KC_HTTPS_CLIENT_AUTH: "request"
# If you are running on a M4 chip use the run-compose.sh script to start the containers
# The EXTRA_JAVA_OPTS variable allows users to pass additional Java options and is used by the run-compose.sh script
# to set the JAVA_OPTS_APPEND environment variable in the Keycloak container
JAVA_OPTS_APPEND: "${EXTRA_JAVA_OPTS}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment