Blog do VG

Codificar é uma arte, mas nem todo mundo é um artista.

LinuxTutoriais

Fazendo deploy de Keycloak v17+ em container docker com Nginx como Proxy Reverso + SSL com LetsEncrypt

Eae devs, sussa?

Neste post vou explicar como fazer deploy de um Keycloak versão 17+ (a partir da versão 17 o keycloak mudou de Wildfly para Quarkus além de outras mudanças) usando Nginx como proxy reverso com certificado SSL gerado automaticamente com Lets Encrypt.

Para isso vamos usar:

Docker-Gen para gerar automaticamente a configuração dos vhosts para o Nginx.
Nginx Proxy como proxy reverso para servir o Keycloak (Com terminação SSL no proxy reverso).

Acme Companion para gerar e gerenciar os certificados através do Lets Encrypt.

Como isso funciona?

Pra entender melhor como isso vai funcionar, seria necessário que você leia a documentação destes serviços que mencionei aí em cima, mas em resumo vamos colocar os contêineres do nginx-proxy, docker-gen, acme-companion e keycloak dentro de uma mesma network do docker, você provavelmente deve saber que para usarmos o Nginx como proxy reverso temos que configurar os server blocks (ou virtual hosts) nos arquivos de configuração, porém, usando o docker-gen em conjunto com algumas váriaveis de ambiente no container, essa configuração dos servers blocks é gerada automaticamente, o docker-gen vai gerar através de metadados de cada container, para isso temos que ter algumas váriáveis no container do keycloak, e são elas:

VIRTUAL_HOST = Subdomínio ou domínio por onde o keycloak vai ser acessado, o DNS deve estar apontando pro IP da máquina onde o container está rodando.
LETSENCRYPT_HOST = Via de regra deve ser igual ao valor do VIRTUAL_HOST.
LETSENCRYPT_EMAIL = E-mail que vai receber as notificações do Lets Encrypt em caso de problemas.
VIRTUAL_PORT = Porta em que o serviço (Keycloak) vai ser acessível na rede do docker (esta porta não será publicada para fora é apenas para o docker-gen gerar a configuração do Nginx).

Uma vez que o docker-gen gere os arquivos de configuração dos virtual hosts o Nginx vai ler estes arquivos (vamos configurar ambos os contêineres para usar os mesmos volumes do docker), com isso o Acme Companion vai ficar escutando os eventos nos containers que estão mapeados com as váriaveis de ambiente e tendo criação ou alteração de algum virtual host, vai fazer o challenge http com o Lets Encrypt para gerar os certificados.

 

Mão na massa

Para esse exemplo vou usar um droplet com Ubuntu 20.04 (VPS) da Digital Ocean, mas você pode usar de outro Cloud Provider também, só lembrando que se for usar EC2 na AWS é preciso liberar o Security Group para as portas 80 e 443, se você quiser usar a Digital Ocean na faixa e como consequência me ajudar a ganhar uns créditos tb, basta clicar aqui para ganhar um crédito de $100 para usar por até 60 dias.

Depois de criar a sua máquina não esqueça de configurar o seu servidor de DNS para apontar para o ip da máquina que vc criou no Cloud Provider, no meu caso estou usando o CloudFlare, com o subdomínio sso.guidi.dev.br que é onde vai ficar o meu Keycloak.

 

Depois disso faça login no servidor e instale o docker e o docker compose conforme os passos disponíveis aqui.

A partir da versão 17 a forma de instalar o keycloak via docker mudou, é necessário fazer o build do container, conforme descrito aqui.

Para agilizar o processo eu já fiz o build do container da versão 18.0.0 do keycloak e publiquei no meu dockerhub.

O compose que vamos usar está publicado no meu github, então instale o git na máquina.

apt-get install git

depois de instalar o git, clone o repositório de templates do meu github para o diretório de sua escolha.

git clone https://github.com/guidi/templates.git

Crie uma rede do docker chamada nginx-proxy, essa rede será usada pelo container do nginx-proxy, docker-gen, acme companion e os contêineres que forem proxyados pelo nginx-proxy.

docker network create nginx-proxy

no repositório que foi clonado no servidor, navegue até o diretório do compose do keycloak 18.0.0

Renomeie o arquivo .env.example para .env

mv .env.example .env

Edite os valores das variáveis de ambiente dentro do arquivo .env conforme sua necessidade, aqui ficou assim (e-mail incorreto por questões de SPAM)

MYSQL_DB=keycloak
MYSQL_USER=keycloak
MYSQL_ROOT_PASSWORD=keycloak#r00ter
MYSQL_PASS=keycloak#p4ss
KC_DB_URL=jdbc:mysql://mysql_keycloak:3306/keycloak
KC_DB_USERNAME=keycloak
KC_DB_PASSWORD=keycloak#p4ss
KC_HOSTNAME=sso.guidi.dev.br
KEYCLOAK_ADMIN=admin
KEYCLOAK_ADMIN_PASSWORD=keycloakp4ssw0rd
VIRTUAL_HOST=sso.guidi.dev.br
LETSENCRYPT_HOST=sso.guidi.dev.br
LETSENCRYPT_EMAIL=meuemail@gmail.com

Execute o compose 

docker compose up --build -d

Depois que o processo for concluído execute o comando docker ps para ver se o container do keycloak e do mysql estão rodando.

docker ps

O resultado deve ser algo mais ou menos assim.

CONTAINER ID   IMAGE                   COMMAND                  CREATED              STATUS              PORTS                 NAMES
0d5454018281   guidi/keycloak:18.0.0   "/opt/keycloak/bin/k…"   About a minute ago   Up 49 seconds       8080/tcp, 8443/tcp    keycloak_mysql
5d7ecef0e727   mysql:8.0.29            "docker-entrypoint.s…"   About a minute ago   Up About a minute   3306/tcp, 33060/tcp   mysql_keycloak

para saber se o keycloak se comunicou com o mysql e iniciou corretamente é possível usar o comando docker logs com o container id.

docker logs 0d5454018281

Caso o keycloak tenha iniciado com sucesso você deve ver nos logs uma mensagem similar a essa.

[io.quarkus] (main) Keycloak 18.0.0 on JVM (powered by Quarkus 2.7.5.Final) started in 72.040s. Listening on: http://0.0.0.0:8080

Agora o keycloak está rodando, mas ainda não é acessível pela internet, para isso vamos usar o compose do nginx proxy que está no meu repositório do github, dentro do servidor, navegue até a pasta templates/compose/nginx-proxy e execute o comando para subir o compose.

docker compose up --build -d

O resultado deve ser algo similar a mensagem abaixo.

⠿ Volume "nginx-proxy_conf"        Created                                0.0s
 ⠿ Volume "nginx-proxy_vhost"       Create...                              0.0s
 ⠿ Volume "nginx-proxy_html"        Created                                0.0s
 ⠿ Volume "nginx-proxy_certs"       Create...                              0.0s
 ⠿ Volume "nginx-proxy_acme_state"  C...                                   0.0s
 ⠿ Container nginx-proxy            Started                                1.1s
 ⠿ Container nginx-proxy-gen        Started                                1.2s
 ⠿ Container nginx-proxy-le         Started                                1.8s

Execute um docker ps para pegar o id dos containeres que estão rodando.

docker ps

O resultado esperado é algo similar a isso.

CONTAINER ID   IMAGE                             COMMAND                  CREATED          STATUS          PORTS                                                                      NAMES
a7d75e5f320f   nginxproxy/acme-companion:2.2.1   "/bin/bash /app/entr…"   40 seconds ago   Up 38 seconds                                                                              nginx-proxy-le
3946507c1c55   nginxproxy/docker-gen:0.9.0       "/usr/local/bin/dock…"   40 seconds ago   Up 38 seconds                                                                              nginx-proxy-gen
4cae610baac2   nginx:1.21.6                      "/docker-entrypoint.…"   41 seconds ago   Up 39 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp   nginx-proxy
0d5454018281   guidi/keycloak:18.0.0             "/opt/keycloak/bin/k…"   10 minutes ago   Up 10 minutes   8080/tcp, 8443/tcp                                                         keycloak_mysql
5d7ecef0e727   mysql:8.0.29                      "docker-entrypoint.s…"   10 minutes ago   Up 10 minutes   3306/tcp, 33060/tcp                                                        mysql_keycloak

faça um docker logs no container do acme-companion para confirmar que o certificado foi gerado.

docker logs a7d75e5f320f

E caso tenha ocorrido com sucesso, o resultado esperado deve ser algo similar a isso aqui.

[Tue Jun 21 03:32:13 UTC 2022] Installing cert to:/etc/nginx/certs/sso.guidi.dev.br/cert.pem
[Tue Jun 21 03:32:13 UTC 2022] Installing CA to:/etc/nginx/certs/sso.guidi.dev.br/chain.pem
[Tue Jun 21 03:32:13 UTC 2022] Installing key to:/etc/nginx/certs/sso.guidi.dev.br/key.pem
[Tue Jun 21 03:32:13 UTC 2022] Installing full chain to:/etc/nginx/certs/sso.guidi.dev.br/fullchain.pem
Reloading nginx docker-gen (using separate container nginx-proxy-gen)...
Reloading nginx (using separate container nginx-proxy)...
Sleep for 3600s

Ao acessar o domínio que você informou nas váriaveis de ambiente do keycloak você deve conseguir ver a página de administração.

Agora basta logar com o usuário e senha que você informou nas variáveis de ambiente KEYCLOAK_ADMIN e KEYCLOAK_ADMIN_PASSWORD do compose do keycloak.

 

Então é isso, espero que este post tenha te ajudado de alguma forma, se tiver dúvidas é só mandar nos comentários.

vanderson

Analista/Desenvolvedor de Sistemas, Gamer, Blogger e um jogador de futebol praticamente profissional (no vídeogame).