Pular para o conteúdo principal

Instalação

Se quiser executar o projeto do Keycloak localmente para teste, é necessário ter o Java instalado. Vamos rodar o projeto localmente para conhecer um pouco dos arquivos que nos interessam e depois vamos partir para rodar como container. Se quiser executar via Docker, temos o comando logo a seguir em Rodando com Docker, mas é bom entender o projeto primeiro.

Na página de Download baixe o zip file e descompacte em algum 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

# Verifique se o Java esta instalado, se não tiver procure como instalar no seu 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)

Alguns aplicativos e ferramentas (tipo o próprio Keycloak) precisam da variável JAVA_HOME setada pra saber onde está o Java.

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

Para rodar o 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 ele subiu em http://0.0.0.0:8080.

alt text

Defina o usuário e senha para o administrador admin. Em produção busque uma senha realmente forte e um usuario diferente de admin. Fazendo o login com esse usuário já chegamos na página inicial.

alt text

No modo desenvolvimento, por isso usando o start-dev, foi criado o diretório data. Esse é o banco de dados em modo desenvolvimento. Se não for passado o banco de dados, o projeto irá criar um banco de dados H2 para uso local. Em produção devemos ter um banco de dados para isso.

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

5 directories, 2 files

Para o servidor subir ele vai utilizar o arquivo de configuração keycloak.conf que fica na pasta conf. Inicialmente esta tudo comentado.

O arquivo conf/keycloak.conf é um dos jeitos formais de configurar o Keycloak, principalmente quando você roda ele via o script kc.sh.

É equivalente a configurar via variáveis de ambiente, só que mais organizado e 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

O Keycloak segue essa ordem de prioridade (de menor pra maior) em busca de suas configurações.

  1. Defaults internos
  2. conf/keycloak.conf
  3. Variáveis de ambiente (ex: KC_HTTP_PORT=8181)
  4. Argumentos CLI (ex: bin/kc.sh start-dev --http-port=8181)

Todas as configurações podem ser encontradas na página all-config.

Por exemplo, se quisermos mudar a porta que é 8080 (default) para 9090.

alt text

Poderíamos adicionar http-port=9090 no arquivo de configuração, passar por flag no comando ou colocar na variável de ambiente. Vamos testar.

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 # AQUI!
2025-05-21 10:15:31,217 INFO [io.quarkus] (main) Profile dev activated.
2025-05-21 10:15:31,217 I

Essas configurações envolvem itens como:

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

Todas as configurações que envolvem identidade são persistidas no banco de dados, não são configuradas via arquivo ou variáveis de ambiente. Se fossemos subir um keycloak que já tivesse configurações de identidade seria necessário fazer um export e depois um import para o novo keycloak.

Com o comando export poderíamos exportar toda ou parte da configuração, veremos mais pra frente ao falar de backups.

Aqui um pouco de informação do servidor.

alt text

Alguns provedores de identidade que poderíamos configurar.

alt text

Vamos explorar as coisas mais detalhes um pouco mais pra frente.

Agora vamos testar subir um banco de dados localmente para ver o que temos de tabela. Faça o download e instale direto no host. Instale junto o pgAdmin só para que possamos analisar via UI as tabelas.

Adicione uma conexão e coloque a senha de administrador que você configurou. Como será só um banco local de teste coloquei a senha admin.

alt text

Como é uma instalação limpa só temo o database postgres e dentro dele nenhuma tabela.

alt text

Vamos criar uma database só para o Keycloak para ficar isolado. Vou dar o nome de keycloakdb. Da mesma forma esse databae começará limpa e sem nenhuma tabela no schemas.

alt text

Agora vamos configurar para que o Keycloak use esse database vamos ajustar as variáveis de ambiente para o banco de dados. Se quiser fazer via arquivo também é possível. Vou fazer desta maneira pois futuramente vamos utilizar essas variáveis de ambiente para instalar o keycloak no kubernetes e todas as configurações serão passadas via variável de ambiente.

# Esse é o tipo do banco, poderia ser outro mysql
export KC_DB=postgres
export KC_DB_USERNAME=postgres
export KC_DB_PASSWORD=admin
# Na url que dizemos qual será o database por isso /keycloackdb
export KC_DB_URL=jdbc:postgresql://localhost:5432/keycloakdb
❯ bin/kc.sh start-dev

Ao mudar o banco precisamos recriar o usuário administrador pois esse usuário estava armazenado no banco H2 anteriormente.

Podemos ver todas as tabelas que foram criadas. Como o Keycloak não encontrou as tabelas que precisa então criou todas. Somente será criada as tabelas se não forem encontradas. Quando atualizamos o Keycloak ele automaticamente faz ajustes nas tabelas. Novas tabelas podem ser criadas e algumas existentes podem ser alteradas de acordo com a necessidade do upgrade. Para isso é usada uma bibliocate chamada Liquibase. Não é necessário fazer nada manualmente, o que é uma grande vantagem.

Foram criadas 88 tabelas. Faça um over view dessas tabelas.

alt text

A lista das tabelas já nos trará o primeiro contato com alguns conceitos importantes que veremos na UI do Keycloak.

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

Rodando com Docker

Podemos subir o Keycloack também já usando containers. Nesse exemplo já estamos setando o username do administrador e password sendo mais uma variável de ambiente que podemos aproveitar. Nesse exemplo vamos rodar o Keycloak mas o banco de dados será o H2 e se perderá assim que o container morrer, pois não mapeamos volumes, é ótimo para testes iniciais.

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 eu tenho um homelab pessoal, vou montar um docker para fornecer o serviço de forma que eu possa redirecionar o domínio keycloak.puziol.com.br para o ip do meu homelab na porta escolhida.

Para montar esse docker vamos utilizar o seguinte comando.

docker run
-d
--name='keycloak'
--net='dockernet' # Minha rede do docker no 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' # PRECISA SER UM URL VÁLIDA PARA PRODUÇÃO
-e 'KEYCLOAK_ADMIN'='ColoqueSeuAdministrador'
-e 'KEYCLOAK_ADMIN_PASSWORD'='ColoqueUmaSenhaForte'
-e 'KEYCLOAK_DATABASE_HOST'='postgres'
-e 'KEYCLOAK_DATABASE_PORT'='5432'
-e 'KEYCLOAK_DATABASE_USER'='UserDoDatabase'
-e 'KEYCLOAK_DATABASE_PASSWORD'='PasswordDoDatabase'
-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'='' #Caso queira passar mais argumento no futuro
-p '9999:8080/tcp' 'bitnami/keycloak:26.2.3'
809f9c651a3784dcead6404c714a10b798f02a00082a8b081d98ba3d968dc6eb

Para isso vamos utilizar uma imagem mantida pela bitnami que é uma ótima referência. Conferindo as tags nesse momento vou optar pela tag 26.2.3 que é a última antes das rc.

Já tenho um PostgreSQL rodando na minha rede interna (dockernet) com o nome postgres, então posso referenciá-lo diretamente pelo hostname. Antes de iniciar o Keycloak, foi necessário criar um banco de dados chamado keycloak.

Um detalhe importante de segurança: defini a variável KEYCLOAK_HOSTNAME_ADMIN=http://10.0.0.10:9999, o que restringe o acesso à interface de administração apenas dentro da minha rede local. Se eu tentar acessar keycloak.puziol.com.br ele irá me redirecional para o http://10.0.0.10:9999 automaticamente. Para as telas de login futuras precisamos definir o realm que iremos utilizar.

O domínio keycloak.puziol.com.br continua funcionando para acessos públicos (ex: login dos usuários), mas não serve para acessar o painel administrativo nessa configuração.

Kubernetes

Sobre rodar o keycloak em kubernetes para um modo produtivo podemos utilizar o Keycloak Operator ou um chart Oficial, mas vamos fazer isso mais pra frente. Fica aqui como um TODO.