Skip to main content

Instalación

Si quieres ejecutar el proyecto de Keycloak localmente para pruebas, es necesario tener Java instalado. Vamos a ejecutar el proyecto localmente para conocer un poco los archivos que nos interesan y después vamos a pasar a ejecutarlo como contenedor. Si quieres ejecutarlo mediante Docker, tenemos el comando justo a continuación en Ejecutando con Docker, pero es bueno entender el proyecto primero.

En la página de Descarga descarga el archivo zip y descomprímelo en algún lugar.

cd Downloads
ls
keycloak-26.2.4.zip
unzip keycloak-26.2.4.zip
cd keycloak-26.2.4
ls
bin conf lib LICENSE.txt providers README.md themes version.txt

# Verifica si Java está instalado, si no lo tienes busca cómo instalarlo en tu sistema
java --version
openjdk 24.0.1 2025-04-15
OpenJDK Runtime Environment Temurin-24.0.1+9 (build 24.0.1+9)
OpenJDK 64-Bit Server VM Temurin-24.0.1+9 (build 24.0.1+9, mixed mode, sharing)

Algunas aplicaciones y herramientas (como el propio Keycloak) necesitan la variable JAVA_HOME configurada para saber dónde está Java.

echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/temurin-24.jdk/Contents/Home

Para ejecutar keycloak

❯ ./bin/kc.sh start-dev
Updating the configuration and installing your custom providers, if any. Please wait.
WARNING: A terminally deprecated method in sun.misc.Unsafe has been called
WARNING: sun.misc.Unsafe::objectFieldOffset has been called by org.jboss.threads.JBossExecutors (file:/Users/davidprata/Downloads/keycloak-26.2.4/lib/lib/main/org.jboss.threads.jboss-threads-3.8.0.Final.jar)
WARNING: Please consider reporting this to the maintainers of class org.jboss.threads.JBossExecutors
WARNING: sun.misc.Unsafe::objectFieldOffset will be removed in a future release
2025-05-21 09:46:04,471 INFO [io.quarkus.deployment.QuarkusAugmentor] (main) Quarkus augmentation completed in 2621ms
Running the server in development mode. DO NOT use this configuration in production.
WARNING: A terminally deprecated method in sun.misc.Unsafe has been called
WARNING: sun.misc.Unsafe::allocateMemory has been called by io.netty.util.internal.PlatformDependent0$2 (file:/Users/davidprata/Downloads/keycloak-26.2.4/lib/lib/main/io.netty.netty-common-4.1.118.Final.jar)
WARNING: Please consider reporting this to the maintainers of class io.netty.util.internal.PlatformDependent0$2
WARNING: sun.misc.Unsafe::allocateMemory will be removed in a future release
2025-05-21 09:46:07,291 INFO [org.keycloak.quarkus.runtime.storage.database.liquibase.QuarkusJpaUpdaterProvider] (main) Initializing database schema. Using changelog META-INF/jpa-changelog-master.xml
2025-05-21 09:46:08,576 INFO [org.keycloak.quarkus.runtime.storage.infinispan.CacheManagerFactory] (main) Starting Infinispan embedded cache manager
2025-05-21 09:46:08,620 INFO [org.keycloak.quarkus.runtime.storage.infinispan.CacheManagerFactory] (main) JGroups JDBC_PING discovery enabled.
2025-05-21 09:46:08,692 INFO [org.infinispan.CONTAINER] (main) Virtual threads support enabled
2025-05-21 09:46:08,816 INFO [org.infinispan.CONTAINER] (main) ISPN000556: Starting user marshaller 'org.infinispan.commons.marshall.ImmutableProtoStreamMarshaller'
2025-05-21 09:46:09,014 INFO [org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFactory] (main) Node name: node_105167, Site name: null
2025-05-21 09:46:09,146 INFO [org.keycloak.services] (main) KC-SERVICES0050: Initializing master realm
2025-05-21 09:46:10,734 INFO [io.quarkus] (main) Keycloak 26.2.4 on JVM (powered by Quarkus 3.20.0) started in 6.167s. Listening on: http://0.0.0.0:8080
2025-05-21 09:46:10,735 INFO [io.quarkus] (main) Profile dev activated.
2025-05-21 09:46:10,735 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]
2025-05-21 09:46:19,591 WARN [org.keycloak.cookie.DefaultCookieProvider] (executor-thread-1) Non-secure context detected; cookies are not secured, and will not be available in cross-origin POST requests

Como podemos ver se levantó en http://0.0.0.0:8080.

alt text

Define el usuario y contraseña para el administrador admin. En producción busca una contraseña realmente fuerte y un usuario diferente de admin. Haciendo login con ese usuario ya llegamos a la página inicial.

alt text

En modo desarrollo, por eso usando start-dev, se creó el directorio data. Esta es la base de datos en modo desarrollo. Si no se pasa la base de datos, el proyecto creará una base de datos H2 para uso local. En producción debemos tener una base de datos para esto.

 ~/Downloads/keycloak-26.2.4
❯ tree data
data
├── h2
│ ├── keycloakdb.mv.db
│ └── keycloakdb.trace.db
└── transaction-logs
└── ShadowNoFileLockStore
└── defaultStore

5 directories, 2 files

Para que el servidor se levante utilizará el archivo de configuración keycloak.conf que está en la carpeta conf. Inicialmente todo está comentado.

El archivo conf/keycloak.conf es una de las formas formales de configurar Keycloak, principalmente cuando lo ejecutas mediante el script kc.sh.

Es equivalente a configurar mediante variables de entorno, solo que más organizado y centralizado.

cat conf/keycloak.conf
# Basic settings for running in production. Change accordingly before deploying the server.

# Database

# The database vendor.
#db=postgres

# The username of the database user.
#db-username=keycloak

# The password of the database user.
#db-password=password

# The full database JDBC URL. If not provided, a default URL is set based on the selected database vendor.
#db-url=jdbc:postgresql://localhost/keycloak

# Observability

# If the server should expose healthcheck endpoints.
#health-enabled=true

# If the server should expose metrics endpoints.
#metrics-enabled=true

# HTTP

# The file path to a server certificate or certificate chain in PEM format.
#https-certificate-file=${kc.home.dir}/conf/server.crt.pem

# The file path to a private key in PEM format.
#https-certificate-key-file=${kc.home.dir}/conf/server.key.pem

# The proxy address forwarding mode if the server is behind a reverse proxy.
#proxy=reencrypt

# Do not attach route to cookies and rely on the session affinity capabilities from reverse proxy
#spi-sticky-session-encoder-infinispan-should-attach-route=false

# Hostname for the Keycloak server.
#hostname=myhostname

Keycloak sigue este orden de prioridad (de menor a mayor) en busca de sus configuraciones.

  1. Defaults internos
  2. conf/keycloak.conf
  3. Variables de entorno (ej: KC_HTTP_PORT=8181)
  4. Argumentos CLI (ej: bin/kc.sh start-dev --http-port=8181)

Todas las configuraciones se pueden encontrar en la página all-config.

Por ejemplo, si queremos cambiar el puerto que es 8080 (default) para 9090.

alt text

Podríamos añadir http-port=9090 en el archivo de configuración, pasarlo por flag en el comando o colocarlo en la variable de entorno. Vamos a probarlo.

export KC_HTTP_PORT=9090
❯ bin/kc.sh start-dev
Running the server in development mode. DO NOT use this configuration in production.
WARNING: A terminally deprecated method in sun.misc.Unsafe has been called
WARNING: sun.misc.Unsafe::allocateMemory has been called by io.netty.util.internal.PlatformDependent0$2 (file:/Users/davidprata/Downloads/keycloak-26.2.4/lib/lib/main/io.netty.netty-common-4.1.118.Final.jar)
WARNING: Please consider reporting this to the maintainers of class io.netty.util.internal.PlatformDependent0$2
WARNING: sun.misc.Unsafe::allocateMemory will be removed in a future release
2025-05-21 10:15:30,211 INFO [org.keycloak.quarkus.runtime.storage.infinispan.CacheManagerFactory] (main) Starting Infinispan embedded cache manager
2025-05-21 10:15:30,251 INFO [org.keycloak.quarkus.runtime.storage.infinispan.CacheManagerFactory] (main) JGroups JDBC_PING discovery enabled.
2025-05-21 10:15:30,331 INFO [org.infinispan.CONTAINER] (main) Virtual threads support enabled
2025-05-21 10:15:30,451 INFO [org.infinispan.CONTAINER] (main) ISPN000556: Starting user marshaller 'org.infinispan.commons.marshall.ImmutableProtoStreamMarshaller'
2025-05-21 10:15:30,635 INFO [org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFactory] (main) Node name: node_350678, Site name: null
2025-05-21 10:15:31,217 INFO [io.quarkus] (main) Keycloak 26.2.4 on JVM (powered by Quarkus 3.20.0) started in 3.353s. Listening on: http://0.0.0.0:9090 # AQUÍ!
2025-05-21 10:15:31,217 INFO [io.quarkus] (main) Profile dev activated.
2025-05-21 10:15:31,217 I

Estas configuraciones involucran elementos como:

  • cache
  • config
  • database
  • features
  • hostname
  • http
  • Management
  • metrics
  • vault
  • logging
  • tracing
  • event
  • trustore
  • security
  • import
  • export
  • bootstrap

Todas las configuraciones que involucran identidad se persisten en la base de datos, no se configuran mediante archivo o variables de entorno. Si fuéramos a levantar un keycloak que ya tuviera configuraciones de identidad sería necesario hacer un export y después un import para el nuevo keycloak.

Con el comando export podríamos exportar toda o parte de la configuración, lo veremos más adelante al hablar de backups.

Aquí un poco de información del servidor.

alt text

Algunos proveedores de identidad que podríamos configurar.

alt text

Vamos a explorar las cosas con más detalle un poco más adelante.

Ahora vamos a probar levantar una base de datos localmente para ver qué tablas tenemos. Haz la descarga e instala directamente en el host. Instala junto pgAdmin solo para que podamos analizar mediante UI las tablas.

Añade una conexión y coloca la contraseña de administrador que configuraste. Como será solo una base de datos local de prueba puse la contraseña admin.

alt text

Como es una instalación limpia solo tenemos la database postgres y dentro de ella ninguna tabla.

alt text

Vamos a crear una database solo para Keycloak para que quede aislado. Le daré el nombre de keycloakdb. De la misma forma esta database empezará limpia y sin ninguna tabla en los schemas.

alt text

Ahora vamos a configurar para que Keycloak use esa database, vamos a ajustar las variables de entorno para la base de datos. Si quieres hacerlo mediante archivo también es posible. Lo haré de esta manera pues en el futuro vamos a utilizar estas variables de entorno para instalar keycloak en kubernetes y todas las configuraciones se pasarán mediante variable de entorno.

# Este es el tipo de la base de datos, podría ser otro mysql
export KC_DB=postgres
export KC_DB_USERNAME=postgres
export KC_DB_PASSWORD=admin
# En la url es donde decimos cuál será la database por eso /keycloakdb
export KC_DB_URL=jdbc:postgresql://localhost:5432/keycloakdb
❯ bin/kc.sh start-dev

Al cambiar la base de datos necesitamos recrear el usuario administrador pues ese usuario estaba almacenado en la base de datos H2 anteriormente.

Podemos ver todas las tablas que fueron creadas. Como Keycloak no encontró las tablas que necesita entonces creó todas. Solo se crearán las tablas si no se encuentran. Cuando actualizamos Keycloak automáticamente hace ajustes en las tablas. Nuevas tablas pueden crearse y algunas existentes pueden alterarse de acuerdo con la necesidad del upgrade. Para esto se usa una biblioteca llamada Liquibase. No es necesario hacer nada manualmente, lo cual es una gran ventaja.

Se crearon 88 tablas. Haz una revisión de esas tablas.

alt text

La lista de las tablas ya nos traerá el primer contacto con algunos conceptos importantes que veremos en la UI de Keycloak.

| alt text | |--------------------------|--------------------------|--------------------------|--------------------------|

Ejecutando con Docker

Podemos levantar Keycloak también usando contenedores. En este ejemplo ya estamos configurando el username del administrador y password siendo una variable de entorno más que podemos aprovechar. En este ejemplo vamos a ejecutar Keycloak pero la base de datos será H2 y se perderá en cuanto el contenedor muera, pues no mapeamos volúmenes, es genial para pruebas iniciales.

docker run -p 8080:8080 -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:26.2.4 start-dev

Como tengo un homelab personal, voy a montar un docker para proporcionar el servicio de forma que pueda redirigir el dominio keycloak.puziol.com.br al IP de mi homelab en el puerto elegido.

Para montar ese docker vamos a utilizar el siguiente comando.

docker run
-d
--name='keycloak'
--net='dockernet' # Mi red de docker en el homelab
--pids-limit 2048
-e TZ="America/Sao_Paulo"
-e HOST_OS="Unraid"
-e HOST_HOSTNAME="Unraid"
-e HOST_CONTAINERNAME="keycloak"
-e 'KEYCLOAK_HOSTNAME'='https://keycloak.puziol.com.br' # NECESITA SER UNA URL VÁLIDA PARA PRODUCCIÓN
-e 'KEYCLOAK_ADMIN'='ColocaTuAdministrador'
-e 'KEYCLOAK_ADMIN_PASSWORD'='ColocaUnaContraseñaFuerte'
-e 'KEYCLOAK_DATABASE_HOST'='postgres'
-e 'KEYCLOAK_DATABASE_PORT'='5432'
-e 'KEYCLOAK_DATABASE_USER'='UsuarioDeLaDatabase'
-e 'KEYCLOAK_DATABASE_PASSWORD'='ContraseñaDeLaDatabase'
-e 'KEYCLOAK_DATABASE_NAME'='keycloak'
-e 'KEYCLOAK_HOSTNAME_ADMIN'='http://10.0.0.10:9999'
-e 'KEYCLOAK_PRODUCTION'='true'
-e 'KEYCLOAK_HOSTNAME_STRICT'='false'
-e 'KEYCLOACK_PROXY'='edge'
-e 'KEYCLOAK_PROXY_HEADERS'='xforwarded'
-e 'KEYCLOAK_EXTRA_ARGS'='' # Por si quieres pasar más argumentos en el futuro
-p '9999:8080/tcp' 'bitnami/keycloak:26.2.3'
809f9c651a3784dcead6404c714a10b798f02a00082a8b081d98ba3d968dc6eb

Para esto vamos a utilizar una imagen mantenida por bitnami que es una excelente referencia. Consultando las tags en este momento voy a optar por la tag 26.2.3 que es la última antes de las rc.

Ya tengo un PostgreSQL ejecutándose en mi red interna (dockernet) con el nombre postgres, entonces puedo referenciarlo directamente por el hostname. Antes de iniciar Keycloak, fue necesario crear una base de datos llamada keycloak.

Un detalle importante de seguridad: definí la variable KEYCLOAK_HOSTNAME_ADMIN=http://10.0.0.10:9999, lo que restringe el acceso a la interfaz de administración solo dentro de mi red local. Si intento acceder a keycloak.puziol.com.br me redireccionará al http://10.0.0.10:9999 automáticamente. Para las pantallas de login futuras necesitamos definir el realm que vamos a utilizar.

El dominio keycloak.puziol.com.br continúa funcionando para accesos públicos (ej: login de los usuarios), pero no sirve para acceder al panel administrativo en esta configuración.

Kubernetes

Sobre ejecutar keycloak en kubernetes para un modo productivo podemos utilizar el Keycloak Operator o un chart Oficial, pero vamos a hacer eso más adelante. Queda aquí como un TODO.