First of all, I have tried everything on this forum I could find about Keycloak, but cannot make this installation work. I have tried to resolve it with Gemini, but to no avail.
About my experience
I am fairly new to GCP and have take the basics of the Cloud Engineer training plan. But I have successfully built, deployed and managed cloud applications on Heroku.
Overview
- A Cloud SQL Postgres instance, with a dedicated db user keycloak on schema keycloak
- A Keycloak container, built for linux/amd64 as authorization server, running in Cloud Run (ingress: allow all, authentication: allow unauthenticated)
- All our running in the same VPC subnet in the northamerica-northeast1 or northamerica-northeast2 regions.
- We need to do this as affordable as possible as we are bootstrapping our startup, hence the choice for Cloud Run.
… still need to do
- A Cloud Run Springboot app with an embedded React app, using a different schema on the same database database and keycloak as an authorization server.
All of this works locally (starting db, keycloak and app in containers with docker-compose), but not on GCP.
What am I doing wrong? How do I make Keycloak work for our setup? Has someone been able to make this work?
Challenges
- Simply be able to start keycloak and access it. I have stripped it from all features (even working with in-memory database) to ensure that everythin works. Whenever I try to connect, I get 'service unavailable’, even though the instance boots correctly (see logs below).
- Connect keycloak to the database. I have seen information about needing to setup Cloud SQL JDBC Socket Factory, but I’ve also seen information about me being able to use /cloudsql/:: as hostname. The latter is the newer article, but doesn’t seem to work.
- Make this instance accessible on a custom domain. I can’t use ‘custom domains’ because of the regions I’m working in.
- Install our app in Cloud Run (if possible from code with Gradle, with embedded React app)
Configuration
Dockerfile
FROM quay.io/keycloak/keycloak:latest
WORKDIR /opt/keycloak
COPY --chown=keycloak:root src/bin/entrypoint.sh bin/entrypoint.sh
COPY --chown=keycloak:root src/conf/certs conf/certs
ENV *KC_FEATURES_DISABLED*=admin-fine-grained-authz,cache-embedded-remote-store,ciba,client-policies,client-secret-rotation,client-types,clusterless,declarative-ui,device-flow,docker,dpop,dynamic-scopes,fips,impersonation,kerberos,multi-site,oid4vc-vci,opentelemetry,organization,par,passkeys,preview,recovery-codes,scripts,step-up-authentication,transient-users,update-email
ENV *KC_HTTPS_CERTIFICATE_FILE*=conf/certs/kc.crt.pem
ENV *KC_HTTPS_CERTIFICATE_KEY_FILE*=conf/certs/kc.key.pem
ENV *KC_HOSTNAME_STRICT*=false
RUN bin/kc.sh build -Djava.net.preferIPv4Stack=true
ENTRYPOINT ["bin/entrypoint.sh"]
entrypoint.sh
**#!/bin/bash**
SERVED_PORT=${PORT:-8080}
printf "Booting Keycloak: bin/kc.sh start -Djava.net.preferIPv4Stack=true --https-port=%s --optimized\n" "$SERVED_PORT"
. bin/kc.sh start -Djava.net.preferIPv4Stack=true --https-port=$SERVED_PORT --optimized
Deployment command
GCP_REGION=northamerica-northeast2
GCP_SVC_ACCOUNT=<service account email>
GCP_IMAGE=<image name>
gcloud run deploy socrates-keycloak \
--image $GCP_IMAGE \
--service-account=$GCP_SVC_ACCOUNT \
--platform managed \
--region $GCP_REGION \
--allow-unauthenticated \
--ingress=all \
--set-cloudsql-instances=socrates \
--min-instances=1 \
--max-instances=1 \
--memory=1024Mi
Logs
These logs are from the point there’s a request to when the instance restarts. The ‘Booting Keycloak’ is the start of a new deployment as well.
2025-02-25 09:08:12.956 EST GET50367 B12 msChrome 133 https://socrates-keycloak-1066886235428.northamerica-northeast2.run.app/
2025-02-25 09:08:13.054 EST 2025-02-25 14:08:13,053 INFO [org.infinispan.CLUSTER] (Thread-14) ISPN000080: Disconnecting JGroups channel `ISPN`
2025-02-25 09:08:13.076 EST 2025-02-25 14:08:13,076 INFO [com.arjuna.ats.jbossatx] (Shutdown thread) ARJUNA032014: Stopping transaction recovery manager
2025-02-25 09:08:13.152 EST 2025-02-25 14:08:13,153 INFO [io.quarkus] (Shutdown thread) Keycloak stopped in 0.172s
2025-02-25 09:08:13.227 EST Booting Keycloak: bin/kc.sh start -Djava.net.preferIPv4Stack=true --https-port=8080 --optimized
2025-02-25 09:08:19.687 EST 2025-02-25 14:08:19,688 INFO [org.keycloak.quarkus.runtime.storage.infinispan.CacheManagerFactory] (main) Starting Infinispan embedded cache manager
2025-02-25 09:08:20.755 EST 2025-02-25 14:08:20,756 INFO [org.infinispan.CONTAINER] (Thread-5) ISPN000556: Starting user marshaller 'org.infinispan.commons.marshall.ImmutableProtoStreamMarshaller'
2025-02-25 09:08:21.191 EST 2025-02-25 14:08:21,192 WARN [org.jgroups.stack.Configurator] (Thread-5) JGRP000014: ThreadPool.thread_dumps_threshold has been deprecated: ignored
2025-02-25 09:08:21.247 EST 2025-02-25 14:08:21,202 INFO [org.infinispan.CLUSTER] (Thread-5) ISPN000078: Starting JGroups channel `ISPN` with stack `udp`
2025-02-25 09:08:21.249 EST 2025-02-25 14:08:21,251 INFO [org.jgroups.JChannel] (Thread-5) local_addr: f4b6c396-62c0-46a7-9b7f-aa0fedbbf3fe, name: localhost-54947
2025-02-25 09:08:21.254 EST 2025-02-25 14:08:21,256 ERROR [org.jgroups.protocols.UDP] (Thread-5) failed setting interface to null (/169.254.9.1): java.lang.IllegalArgumentException: Invalid value 'null'
2025-02-25 09:08:21.255 EST 2025-02-25 14:08:21,256 ERROR [org.jgroups.protocols.UDP] (Thread-5) failed setting interface to null (/169.254.9.1): java.lang.IllegalArgumentException: Invalid value 'null'
2025-02-25 09:08:21.257 EST 2025-02-25 14:08:21,258 WARN [org.jgroups.protocols.UDP] (Thread-5) JGRP000015: the receive buffer of socket MulticastSocket was set to 20MB, but the OS only allocated 4.19MB
2025-02-25 09:08:21.257 EST 2025-02-25 14:08:21,259 WARN [org.jgroups.protocols.UDP] (Thread-5) JGRP000015: the receive buffer of socket MulticastSocket was set to 25MB, but the OS only allocated 4.19MB
2025-02-25 09:08:21.264 EST 2025-02-25 14:08:21,266 INFO [org.jgroups.protocols.FD_SOCK2] (Thread-5) server listening on *.33068
2025-02-25 09:08:21.797 EST 2025-02-25 14:08:21,798 INFO [org.keycloak.broker.provider.AbstractIdentityProviderMapper] (main) Registering class org.keycloak.broker.provider.mappersync.ConfigSyncEventListener
2025-02-25 09:08:23.182 EST 2025-02-25 14:08:23,183 INFO [org.keycloak.quarkus.runtime.storage.database.liquibase.QuarkusJpaUpdaterProvider] (main) Initializing database schema. Using changelog META-INF/jpa-changelog-master.xml
2025-02-25 09:08:23.269 EST 2025-02-25 14:08:23,271 INFO [org.jgroups.protocols.pbcast.GMS] (Thread-5) localhost-54947: no members discovered after 2002 ms: creating cluster as coordinator
2025-02-25 09:08:23.279 EST 2025-02-25 14:08:23,280 INFO [org.infinispan.CLUSTER] (Thread-5) ISPN000094: Received new cluster view for channel ISPN: [localhost-54947|0] (1) [localhost-54947]
2025-02-25 09:08:23.389 EST 2025-02-25 14:08:23,390 INFO [org.infinispan.CLUSTER] (Thread-5) ISPN000079: Channel `ISPN` local address is `localhost-54947`, physical addresses are `[169.254.9.1:48604]`
2025-02-25 09:08:28.579 EST 2025-02-25 14:08:28,580 INFO [org.keycloak.services] (main) KC-SERVICES0050: Initializing master realm
2025-02-25 09:08:31.591 EST 2025-02-25 14:08:31,592 WARN [io.agroal.pool] (main) Datasource '<default>': JDBC resources leaked: 1 ResultSet(s) and 0 Statement(s)
2025-02-25 09:08:31.949 EST Default STARTUP TCP probe succeeded after 1 attempt for container "socrates-keycloak-1" on port 8080.
2025-02-25 09:08:31.964 EST 2025-02-25 14:08:31,964 INFO [io.quarkus] (main) Keycloak 26.0.8 on JVM (powered by Quarkus 3.15.1) started in 17.976s. Listening on: https://0.0.0.0:8080
2025-02-25 09:08:31.964 EST 2025-02-25 14:08:31,965 INFO [io.quarkus] (main) Profile prod activated.
2025-02-25 09:08:31.964 EST 2025-02-25 14:08:31,965 INFO [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, jdbc-h2, keycloak, narayana-jta, opentelemetry, reactive-routes, rest, rest-jackson, smallrye-context-propagation, vertx]