Como utilizar reverse proxys para ultrapassar limitações em software?

Olá a todos.

Recentemente um colega e amigo puxou um assunto muito interessante no que trata de limitações do Nexus repository server. Ele lembrou-me e muito bem, que os registry’s (repositórios) de docker não podem partilhar portas no host onde o Nexus está a correr.

Isto na pratica, significa que se tiveres 300 registry’s diferentes na mesma máquina, terás de pedir acesso de rede a 300 portas diferentes para teres a coisa a funcionar bem.
Só por si, se fosse uma questão apenas de ambientes estáticos, não faria grande mal. Agora imaginem que estão a dar suporte a uma empresa que tem uma cultura de devops bastante avançada e que cada um dos departamentos tem um registry por aplicação, e sempre que lançam uma nova aplicação, iniciam um novo registry.
Agora imaginem ter de pedir conectividade e fecho da mesma para todos estes projectos no lifecycle deles, junto com o debug que iria como sempre ser pedido. Não estou a dizer que a culpa seja da network claro 🙂 Tambem pode ser do dns 🙂

Com esse pensamento em mente, escrevi este post onde vou explicar como através de um reverse proxy em nginx podemos nós controlar os acessos, fazendo uso de apenas uma conectividade de rede do servidores docker, ao nosso registry.

Pré-requisitos

Antes de começar, iremos precisar:

  • Um servidor Linux (CentOS 7/8 ou RHEL 7/8).
  • Acesso root ou sudo ao servidor.
  • Certificados SSL válidos (ou pode usar o Let’s Encrypt).
  • Conhecimento básico em linha de comando e administração de sistemas.

Instalando o Nginx

Em primeiro lugar, iremos instalar o Nginx no servidor. Utilizaremos o gestor de pacotes RPM.

Adicionando o Repositório Nginx

Criem um arquivo de repositório para o Nginx:

sudo vi /etc/yum.repos.d/nginx.repo

Adicionem o seguinte conteúdo ao arquivo:

[nginx-stable]
name=nginx stable repo
baseurl=https://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

Instalando o Nginx

Atualizem os repositórios e instalem o Nginx:

sudo yum update
sudo yum install nginx

Iniciando e Systemd-enabling o Nginx

Inicie o serviço Nginx e habilite-o para iniciar automaticamente no boot:

sudo systemctl start nginx
sudo systemctl enable nginx

Configurando o Nginx para responder em HTTPS com Certificados SSL

Para configurarmos o Nginx para usar HTTPS, iremos precisará de um certificado SSL e uma chave privada. Se não tiverem um certificado SSL self signed, assinado pela vossa CA, ou tiverem preguiça de gerar um localmente, pode obter um gratuitamente do Let’s Encrypt.

Instalando o Certbot

Certbot é uma ferramenta que facilita a obtenção de certificados SSL do Let’s Encrypt.

Instale o Certbot:

sudo yum install epel-release
sudo yum install certbot

Obtendo o Certificado SSL

Obtenham o certificado para o vosso domínio:

sudo certbot certonly --standalone -d dominio.com -d www.dominio.com

Certifiquem-se de substituir `dominio.com` pelo vosso domínio real.

Configurando o Nginx para responder em HTTPS

Editem o arquivo de configuração principal do Nginx:

sudo vi /etc/nginx/nginx.conf

Adicionem a configuração HTTPS no bloco do servidor:

server {
listen 443 ssl;
server_name dominio.com www.dominio.com;

ssl_certificate /etc/letsencrypt/live/dominio.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dominio.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;

location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

Não se esqueçam de ajustar os caminhos dos certificados para os locais corretos onde o Certbot os deixou. Não se esquecam igualmente de configurar um mecanismo de renovação, tendo em conta que um certificado da Let’s Encrypt dura apenas 90 dias.

Configurando o Reverse Proxy

Agora, vamos configurar o Nginx para funcionar como um reverse proxy e redirecionar as requisições para diferentes serviços com base nos caminhos das URLs.

Estrutura de Diretórios

Vamos supor que conforme falamos anteriormente temos dois serviços do Nexus a correr em portas diferentes no servidor:

– Serviço A em `http://nexuserver:8081`
– Serviço B em `http://nexuserver:8082`

Configurando Endpoints

Editem o arquivo de configuração do Nginx:

sudo vi /etc/nginx/conf.d/reverse-proxy.conf

Adicionem as configurações para redirecionar os pedidos baseados no caminho da URL:

server {
listen 80;
server_name dominio.com www.dominio.com;

location / {
return 301 https://$host$request_uri;
}
}

server {
listen 443 ssl;
server_name dominio.com www.dominio.com;

ssl_certificate /etc/letsencrypt/live/dominio.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dominio.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;

location /registryA/ {
proxy_pass http://nexuserver:8081/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location /registryB/ {
proxy_pass http://nexuserver:8082/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

Explicação das Configurações

  • Redirecionamento HTTP para HTTPS**: Todas as requisições para a porta 80 são redirecionadas para a porta 443 (HTTPS).
  • Configuração SSL**: Define os certificados SSL e os protocolos de segurança.
  • Bloco `location /registryA/`**: Redireciona as requisições que começam com `/servicoA/` para `http://nexuserver:8081/`.
  • Bloco `location /registryB/`**: Redireciona as requisições que começam com `/servicoB/` para `http://nexuserver:8082/`.

Testando a Configuração

Antes de reiniciarem o Nginx, testem a configuração para garantir que não há erros. Alias sempre que fizerem qualquer alteração em qualquer nginx testem a configuração para garantir que não há erros 🙂

sudo nginx -t

Se o teste for bem-sucedido, reiniciem o Nginx para aplicar as mudanças:

sudo systemctl restart nginx

Nota: Já sei que por esta altura ha gente a ler o post com azedume por causa do restart ao nginx. Estou a ver as perguntas, ó Nuno, porque restart? Porque não fizeste graceful reload? … porque quando se adicionam certificados novos o reload não os apanha.

Verificando o Funcionamento

Para garantirem que a configuração está funcionando corretamente, sigam estes passos:

Acedam ao serviço A**: Abram um browser e vão  até `https://dominio.com/servicoA/`. O vosso pedido deverá ser redirecionado para o serviço em execução em `http://nexusserver:8081`.
Acedam ao serviço B**: Abram um browser e vão  até `https://dominio.com/servicoB/`.O vosso pedido deverá ser redirecionado para o serviço em execução em `http://localhost:8082`.

Verifiquem se as respostas estão corretas e que não há problemas de redirecionamento ou erros de certificado.

Manutenção e Renovação do Certificado SSL

Conforme falado acima, os certificados do Let’s Encrypt são válidos apenas por 90 dias. É altamente recomendado automatizar a renovação dos certificados. O Certbot pode fazer isto automaticamente.

Configurando a Renovação Automática

Adicionem uma tarefa cron para renovar os certificados automaticamente:

sudo crontab -e

Adicionem a seguinte linha ao arquivo cron para executar a renovação duas vezes ao dia:

0 0,12 * * * /usr/bin/certbot renew --quiet

Esta linha configurará o Certbot para verificar e renovar os certificados, caso seja necessário, duas vezes ao dia, à meia-noite e ao meio-dia.

Conclusão e considerações finais.

E chegamos ao fim de mais um post semanal. Neste falamos e demonstramos como podemos fazer uso de múltiplas ferramentas para ultrapassar limitações aplicativas.
Neste caso especifico, mostramos como podemos configurar um reverse proxy com Nginx para gerenciar múltiplos serviços sob o mesmo domínio/porta.
Utilizando caminhos de URL diferentes, podemos facilmente redirecionar os pedidos para endpoints diferentes, garantindo uma integração suave e eficiente entre seus serviços. A somar a isto Além disso, a configuração de HTTPS garante que todas as comunicações são seguras, protegendo os dados em trânsito.
Podemos anuir igualmente que se deployment em bulk for uma coisa habitual na empresa que estão a suportar, talvez efetuar automatização que vos crie templates de vhosts em bulk sempre que um projeto novo entre seja vantagoso para vós.

Na pratica, configuramos o Nginx como um reverse proxy que responde em HTTPS, redirecionando requisições para diferentes registrys do Nexus com base nos caminhos das URLs. Este tipo de configuração não apenas melhora a organização e a segurança dos nossos serviços, mas também oferece uma base sólida para futuras expansões e integrações.

Até a próxima semana, e ja sabem. Se tiverem duvidas ou reparos, sabem onde me encontrar.
Abraço.
Nuno

PS: Agradeço ao João Santos pela excelente ideia para este post.