- Procedimento de implantação para executar o Keycloak isolado com Docker rootless em uma única VM Linux, enquanto o nginx do sistema cuida da terminação TLS e do proxy reverso para o SSO
- Os pré-requisitos são acesso SSH, um domínio ou subdomínio para o Keycloak, registro
A, usuário keycloak sem senha, diretório home em /srv/keycloak e instalação do Docker rootless
- O
docker-compose.yml usa postgres:16 e quay.io/keycloak/keycloak:25.0.1, com o Keycloak vinculado apenas a 127.0.0.1:8080 e senhas e KC_HOSTNAME gerenciados no .env
- O nginx redireciona requisições HTTP de
your.tld.com para HTTPS e encaminha com proxy_pass; depois de emitir o certificado com o Certbot, ativa-se KC_PROXY_HEADERS: xforwarded
- Se forem necessários um tema personalizado ou execução com
--optimized, é possível criar uma imagem própria com um Dockerfile multi-stage; em produção, também dá para ajustar adicionalmente o tamanho do buffer do JGroups e a recuperação de transações do Quarkus
Estrutura de implantação e pré-requisitos
- O Keycloak é uma opção de IAM open source para usar quando for difícil implementar diretamente o gerenciamento de usuários e SSO em uma aplicação web
- É interoperável com os principais protocolos de SSO, como
OpenID Connect (OIDC), OAuth 2.0 e SAML
- A configuração foi escrita com base no Keycloak
23.0.6 e testada até a versão 25.0.5
- A estrutura geral usa o nginx como proxy reverso central, encaminhando o tráfego para localhost dentro de namespaces rootless Docker separados por serviço
- O tráfego web entra por
0.0.0.0:80 e 0.0.0.0:443, e o nginx o repassa para o Keycloak em 127.0.0.1:8080
- O objetivo é uma configuração econômica que compartilha os recursos de um único host, mas separa os ambientes dos serviços
Preparação
- O ambiente básico necessário é uma VM Linux, acesso remoto via SSH e um domínio ou subdomínio para o serviço Keycloak
- O domínio precisa de um registro
A e, opcionalmente, pode ter também um registro AAAA
- A configuração básica do Docker rootless segue o procedimento de outro post no Mastodon
- Criar um novo usuário non-root
keycloak sem senha
- Definir o diretório home como
/srv/keycloak
- Adicionar a faixa do usuário
keycloak em /etc/subuid e /etc/subgid
- Instalar o Docker rootless com
dockerd-rootless-setuptool.sh
- Configurar o início automático do serviço para o usuário
keycloak
Executando o Keycloak com Docker Compose
- Ao entrar no usuário
keycloak recém-criado, usa-se machinectl shell keycloak@
- O método
sudo -u keycloak -H bash deve ser evitado porque a variável de ambiente XDG_RUNTIME_DIR não fica preparada
- Primeiro, crie os diretórios de dados persistentes e dos arquivos do Docker
- O caminho dos dados do PostgreSQL é
/srv/keycloak/data/postgres16
- Os arquivos do Docker ficam em
~/docker
- O
docker-compose.yml usa diretamente a imagem oficial do Keycloak e o PostgreSQL
- A imagem do PostgreSQL é
postgres:16
- A imagem do Keycloak é
quay.io/keycloak/keycloak:25.0.1
- Em produção, recomenda-se usar uma tag específica da imagem em vez de
:latest
- As principais configurações do contêiner do Keycloak são as seguintes
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://postgres_db/keycloak
KC_HOSTNAME: ${KC_HOSTNAME:-your.tld.com}
KC_HTTP_ENABLED: true
HTTP_ADDRESS_FORWARDING: true
KEYCLOAK_ADMIN: admin
- A porta é vinculada apenas ao localhost com
'127.0.0.1:8080:8080'
- No
.env, ficam os valores sensíveis ou que variam por ambiente
POSTGRES_PASSWORD
KEYCLOAK_ADMIN_PASSWORD
KC_HOSTNAME
- A sintaxe
${KC_HOSTNAME:-your.tld.com} usa o valor de KC_HOSTNAME no .env se ele existir; caso contrário, usa your.tld.com como padrão
/srv/keycloak/data/postgres16 armazena os dados persistentes do PostgreSQL, então deve entrar na rotina de backup periódico
- Para reinicializar completamente, basta apagar e recriar essa pasta do PostgreSQL; ela será criada novamente na próxima inicialização
- Se
~/docker for mantido como repositório Git, é possível adicionar .env ao .gitignore e versionar apenas o docker-compose.yml
Teste local
- Inicie a stack do Docker Compose e acompanhe os logs
docker compose up -d && docker compose logs --follow
- Para acessar a porta local do Keycloak na VM, crie um túnel SSH reverso
ssh you@111.11.11.11 -L :8080:127.0.0.1:8080 -p 22 -N -v
- No navegador, abra
127.0.0.1:8080 para verificar a tela de boas-vindas do Keycloak
Proxy reverso nginx e TLS
- Depois de sair do usuário
keycloak, faça a configuração do nginx do sistema
- Troque
your.tld.com pelo domínio real e, no registrador do domínio, adicione o registro A para que as consultas DNS apontem para o IP da VM
- Crie e ative o arquivo de configuração do site no nginx
nano /etc/nginx/sites-available/your.tld.com.conf
ln -s /etc/nginx/sites-available/your.tld.com.conf /etc/nginx/sites-enabled/
- A configuração do nginx redireciona requisições HTTP para HTTPS e, no bloco do servidor HTTPS, faz o proxy para o Keycloak
proxy_set_header Host $host
proxy_set_header X-Real-IP $remote_addr
proxy_set_header X-Forwarded-For $remote_addr
proxy_set_header X-Forwarded-Proto $scheme
proxy_pass http://127.0.0.1:8080
- Para a configuração SSL, recomenda-se usar o Mozilla SSL configurator for nginx para gerar valores padrão adequados à versão do nginx
- Após testar a configuração, recarregue o nginx
nginx -t
systemctl reload nginx
- Ao emitir o certificado com o Certbot, as linhas necessárias em
your.tld.com.conf são atualizadas automaticamente
certbot --nginx -d your.tld.com
- Depois disso, ative
ssl_trusted_certificate /etc/letsencrypt/live/your.tld.com/chain.pem; e recarregue o nginx novamente
- Para funcionar atrás do nginx, ative
KC_PROXY_HEADERS: xforwarded no docker-compose.yml e reinicie a stack Docker
docker compose down && docker compose up -d && docker compose logs --follow
Caminho de depuração
- Depois da configuração, acesse
your.tld.com e confirme o login do usuário admin com a senha definida no .env
- O primeiro ponto de verificação são os logs do Docker Compose
docker compose logs --follow
- Os logs de acesso e erro do nginx podem ser acompanhados nestes arquivos
tail -f /var/log/nginx/your.tld.com-access.log
tail -f /var/log/nginx/your.tld.com-error.log
- Se for necessário verificar diretamente o banco de dados do Keycloak, entre no usuário
keycloak e execute o psql dentro do contêiner PostgreSQL
machinectl shell keycloak@
cd ~/docker
docker compose exec postgres_db /bin/bash
psql -h localhost -p 5432 -U keycloak keycloak
Imagem personalizada e execução optimized
- A configuração básica usa a imagem pré-compilada do
quay.io
- Se forem necessários personalização de tema ou execução no modo
--optimized, construa uma imagem própria
- O Dockerfile usa a imagem oficial do Keycloak com build multi-stage
- Na etapa builder, define
ENV KC_DB=postgres
- Executa
/opt/keycloak/bin/kc.sh build
- Copia
/opt/keycloak/ para a imagem final
- Define
ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]
- No
docker-compose.yml, faça as seguintes mudanças
- Remova ou comente a linha
image:
- Ative
build: .
- Adicione
command: start --optimized
- Depois disso, derrube a stack Docker, opcionalmente execute o build explícito e inicie novamente
docker compose down
docker compose build
docker compose up -d && docker compose logs --follow
Ajustes adicionais feitos em produção
- O aviso de buffer de recepção do
MulticastSocket relacionado ao JGroups foi resolvido adicionando valores de buffer no /etc/sysctl.conf do host
net.core.rmem_max = 26214400
net.core.wmem_max = 1048576
- Para aplicar a configuração, execute
sysctl -p
- O aviso de recuperação de transações XA do Quarkus foi resolvido adicionando um volume mount e uma variável de ambiente ao serviço Keycloak
- Volume:
/srv/keycloak/data/keycloak/ObjectStore/:/ObjectStore/
- Variável de ambiente:
QUARKUS_TRANSACTION_MANAGER_ENABLE_RECOVERY: true
- Antes da inicialização, crie o diretório ObjectStore no host e, dentro do contêiner, altere o proprietário de
/ObjectStore para o user ID 1000
Etapas após a configuração
- O estado final é uma configuração em que o serviço Keycloak dentro do Docker rootless roda atrás do proxy reverso nginx do sistema, e o nginx faz a terminação SSL
- Para atualização automática dos contêineres, consulte o procedimento de atualização automática em outro post no Mastodon
- A próxima etapa de configuração é adicionar e-mail no console administrativo do Keycloak
- Depois disso, é possível adicionar realms e configurar temas
- Para temas, podem ser usados keycloakify e keycloakify-starter
- O Dockerfile inclui uma linha comentada para copiar o JAR de tema do keycloakify para
/opt/keycloak/providers/
1 comentários
Opiniões no Hacker News
Recentemente, ao adicionar autenticação ao meu homelab, escolhi o Authelia
O Keycloak também funciona, mas é grande demais e, para usá-lo com o forward auth do traefik, é preciso mais um serviço adicional
O Authelia não tem uma UI para edição de usuários e também não faz sincronização bidirecional com um servidor LDAP de backend, mas pode ser configurado apenas com arquivos estáticos e variáveis de ambiente, então se encaixa bem em muitos casos
Se a ideia é adicionar autenticação a alguns serviços e colocar SSO nos que suportam, vale começar pelo Authelia
Se você precisa de SSO, configuração fácil e UI administrativa, o FusionAuth também vale uma olhada. A UI/UX tem mesmo um ar de meados dos anos 2000, mas você pode baixá-lo e executá-lo diretamente[0], ele é amigável a Docker[1] e oferece várias formas de configuração[2], como gerenciar OIDC ou outras configurações com Terraform[3]
Pode ser usado gratuitamente, mas não é open source[4]
0: https://fusionauth.io/download
1: https://fusionauth.io/docs/get-started/download-and-install/...
2: https://fusionauth.io/docs/operate/deploy/configuration-mana...
3: https://fusionauth.io/docs/operate/deploy/terraform
4: https://fusionauth.io/license-faq#28
Uso o Caddy como proxy reverso e o integrei ao Authelia[1], e funciona bem
Coloquei autenticação de dois fatores robusta em todos os serviços e sinto que é suficientemente seguro acessar meus apps auto-hospedados sem VPN
Porém, como o Authelia não tem um novo release há mais de um ano, fico preocupado do ponto de vista de segurança
[0] https://github.com/lldap/lldap
[1] https://www.authelia.com/integration/proxies/caddy/
[1] https://github.com/greenpau/caddy-security
É um caso de uso muito bom para ambientes de homelab, especialmente se você não precisa ou não quer os recursos das soluções maiores
Procurei e não encontrei algo em formatos como schema simples, JSON ou HTTP, e é difícil acreditar que quase todo mundo que reinventou tudo não tenha reinventado o LDAP
Pelo que sei, na prática o único outro padrão é o Active Directory
Também tenho curiosidade se existe algum padrão ou protocolo para delegar o controle de acesso para fora
O Authelia consegue controlar acesso por padrões de URL, mas, por exemplo, no caso de um servidor de arquivos, eu esperaria algo como verificar permissões no servidor LDAP com base no ID do usuário autenticado e em uma chave no banco de dados
Isso parece ir na direção oposta do OAuth2, em que o servidor obtém permissão para acessar um serviço de terceiros
Recentemente, estive pesquisando como configurar um SSO relativamente simples no meu homelab, e o objetivo principal era facilitar o login com autenticação do Google ou do GitHub
No meu emprego anterior, usei tanto o JetBrains Hub[1] quanto o Keycloak, e ambos eram bem chatos de configurar
O JetBrains Hub era realmente muito fácil de começar a usar, e minha experiência anterior também foi assim, mas era inconveniente que o registro Docker não tivesse a tag latest
Sei que fixar versões é uma boa prática, mas para uso pessoal normalmente quero atualizar todos os contêineres Docker de uma vez
Já o Keycloak foi muito trabalhoso para começar; no modo de desenvolvimento era fácil, mas a configuração de produção travou
Pelo que me lembro, tinha a ver com um certificado wildcard do Let's Encrypt, e depois de algumas horas desisti
No fim, escolhi o Dex[2]. Eu tinha adiado por falta de documentação, mas a configuração real foi muito fácil: bastaram um YAML básico, um banco de dados SQLite e um subdomínio
Combinei o Dex com o excelente OAuth2 Proxy[3] e um template personalizado do Nginx Proxy Manager para transformar isso em uma configuração de SSO de duas linhas para cada serviço interno, e também criei um template Docker do Dex para unRAID[4]
Fora de casa, acrescentei Cloudflare Access e WAF para reforçar a segurança, e só gostaria de adicionar o CrowdSec para obter um pouco mais de visibilidade
Pessoalmente, acho que essa é a opção mais simples
https://github.com/lastlogin-io/obligator
Criei uma tabela comparativa incompleta de vários servidores OpenID Connect auto-hospedáveis[0]
Uma das coisas que me surpreendeu foi como a base de código do Keycloak é realmente enorme
[0]: https://github.com/lastlogin-io/obligator?tab=readme-ov-file...
É engraçada a ideia de que o Keycloak resolve problemas de segurança
Dê uma olhada na lista de CVEs e você vai entender o que quero dizer
Também seria ridículo chamar de “segura” uma solução fechada e opaca que não tem CVEs reportadas
Além disso, a versão mais recente, 22.0.2, tem apenas 3 vulnerabilidades conhecidas
https://www.cvedetails.com/vulnerability-list/vendor_id-25/p...
Pelo menos foi muito útil o artigo mencionar https://www.keycloakify.dev/
Parece uma ótima alternativa à abordagem padrão de temas
Uso há 2 anos e só tenho coisas boas a dizer
O mantenedor responde muito rápido, e recentemente houve mudanças tanto no Keycloak quanto no keycloakify para melhorar a compatibilidade futura da abordagem de temas
Atualmente, oficialmente, só há suporte para apps criados com create-react-app, mas o branch vite está em desenvolvimento e, pessoalmente, já venho usando com vite há algum tempo
Estou de olho no authentik[1] e no authelia[2]
O Authelia parece muito bom, mas fiquei um pouco cauteloso porque o Keycloak tem um conector para Angular, enquanto no Authelia seria preciso configurar manualmente, por exemplo, um plugin OIDC para Angular
Ainda assim, se houver uma configuração para Keycloak, acho que fica mais fácil começar
[1] https://goauthentik.io/
[2] https://www.authelia.com/
Eu protejo constantemente mais de 10 serviços em Docker e Kubernetes e, se você não gosta de configurar a proteção de cada serviço de forma independente, vai sofrer com o authentik
O authentik tem um bug grave[0] em que, ao proteger vários subdomínios (app1.example.com, app2.example.com etc.) com uma única configuração, quando o usuário se reautentica após a sessão expirar, ele é redirecionado aleatoriamente para outro serviço
[0]: https://github.com/goauthentik/authentik/issues/6886
Não dá para corrigir sem uma mudança que quebre compatibilidade, e ele não funciona com muitas ferramentas que usam o grant cc
Depois de ver isso, risquei totalmente da lista de candidatos
https://github.com/goauthentik/authentik/issues/6139
Se houver algo em que eu possa ajudar na configuração do Angular, ficarei feliz em ajudar via GitHub Discussions
O Authentik parecia melhor, mas o bug mencionado em outra resposta parece bem ruim
O problema do Keycloak é que ele é um projeto antigo e passou por mudanças enormes
Começou como um projeto JBOSS, e sua utilidade como IdP brilha na autenticação de clusters on-premises, mas acho que para por aí
Implementei o Keycloak em larga escala no AWS ECS em um departamento de uma Fortune 500, e fazer o clustering funcionar direito pareceu uma Guerra dos Mil Anos
A descoberta por DNS não funcionava corretamente, e a descoberta de cluster era baseada em UDP, então não funcionava em ambientes de nuvem
Um login com estado em um servidor não existia em outro, então balanceamento de carga simples era impossível, e sessões fixas eram a única opção
É fácil subir o Keycloak com
docker rune plugá-lo como se fosse o Auth0, mas a sensação é de comprar uma Ford F-150 1996 com 250 mil milhas rodadasEla anda e funciona, mas a manutenção é realmente terrível
Pelo que lembro, o método padrão de descoberta usa multicast, que não vem habilitado em redes de nuvem comuns nem em redes overlay do Swarm/Kubernetes
Também vi o database ping, que usa um RDBMS como uma espécie de mecanismo de quórum, mas parecia muito frágil e com cara de último recurso
No fim, consegui usar um driver de cluster Kubernetes que descobria os nós pelo DNS do cluster Swarm
Foi bem difícil fazer funcionar, mas desde então, até onde sei, está estável
Hoje em dia parece que também existe um driver de rede EC2 nativo, mas não cheguei a investigá-lo pessoalmente
Fico curioso para saber quando foi essa implantação no ECS
Nós só permitimos UDP para DNS
O Keycloak é ótimo, mas pode ser bastante confuso para iniciantes
Tem muitos recursos e a documentação não é das melhores
Testei recentemente o Zitadel e achei muito mais fácil de usar
Porém, como não dá para executá-lo com um banco de dados embutido, a hospedagem própria fica um pouco mais difícil
A direção daqui para frente é usar Postgres como banco de dados, então espero que fique mais fácil implantá-lo junto com outras ferramentas
Meu chefe recentemente chamou o Keycloak de “um presente que não para de dar”, mas na verdade queria dizer que ele continua gerando novos tickets no Jira para descobrir como fazer alguma coisa
Ainda assim, temos Terraform que cria um cluster EKS e implanta o Keycloak, cria clientes SAML/OIDC, adiciona provedores de identidade externos e até configura um AWS IAM Identity Provider
Depois que você descobre o que dá para fazer, como fazer pela UI e como automatizar com o Terraform provider do mrparkers, o uso em si fica muito fácil
Um amigo precisa dele :)
Depois de usar o Keycloak por alguns anos, sinceramente me cansei de todos os comportamentos peculiares e comecei a procurar alternativas
Vários candidatos, como o Authentik, pareciam bons, mas o Zitadel[1] chamou minha atenção, e desde então nunca olhei para trás
[1] https://zitadel.com/blog/zitadel-vs-keycloak
Fico curioso para saber o que foi decisivo para te atrair