O HAProxy é um balanceador de carga TCP e HTTP que termina o TLS, ou seja, ele descriptografa o tráfego na borda e reenvia HTTP simples para os seus servidores de backend. Isso faz dele a única máquina no caminho que precisa do certificado, e ele quer esse certificado em um formato específico: um único ficheiro, contendo o certificado, quaisquer intermediários e a chave privada.
Este guia cobre todo o percurso: gerar um CSR, montar o ficheiro PEM, escrever o frontend e o backend, verificar a configuração e recarregar sem interromper as conexões ativas. Os comandos foram executados na HAProxy 3.4, o ramo atual de suporte de longo prazo, lançado em junho de 2026 e mantido até o segundo trimestre de 2031.
O que o HAProxy espera: um único ficheiro PEM
A maioria dos servidores recebe o certificado, a cadeia e a chave como três configurações separadas. O HAProxy recebe apenas uma. O seu manual de configuração descreve a palavra-chave crt como designando “um ficheiro PEM contendo tanto os certificados necessários quanto quaisquer chaves privadas associadas”, construído pela concatenação de ficheiros PEM, e acrescenta que “se a sua CA exigir um certificado intermediário, este também pode ser concatenado neste ficheiro”.
Dois comportamentos vale a pena conhecer antes de começar, porque poupam trabalho mais tarde:
- A chave pode estar junto do certificado em vez de dentro dele. Se o ficheiro não tiver nenhuma chave privada, o HAProxy procura o mesmo caminho com .key acrescentado. Assim, mydomain.pem mais mydomain.pem.key funciona tão bem quanto um único ficheiro combinado.
- Pode apontar o crt para um diretório. O HAProxy carrega todos os ficheiros que encontrar lá e seleciona o certificado correto por requisição usando SNI. É assim que se serve vários sites a partir de um único frontend, sem uma linha bind para cada um.
Gerar o CSR e a chave privada
Um CSR é o pedido codificado que se entrega à Autoridade Certificadora. Gere-o na própria máquina HAProxy, ou em qualquer lugar onde possa manter a chave privada segura, já que a chave nunca sai do seu lado.
openssl req -new -newkey rsa:2048 -nodes
-keyout mydomain.key -out mydomain.csr
-subj "/C=US/ST=California/L=San Jose/O=Your Company/CN=mydomain.com"
-addext "subjectAltName=DNS:mydomain.com,DNS:www.mydomain.com"
A linha -addext não é opcional na prática. Os navegadores deixaram de comparar nomes de host com o Common Name há anos e leem apenas o Subject Alternative Name, portanto um CSR que traga apenas um CN produz um certificado que falha em todos os navegadores atuais. Liste todos os nomes que o certificado deve cobrir, incluindo o domínio simples e a forma www, se servir ambos.
Retire as opções -subj e -addext se preferir ser questionado para cada campo. De qualquer forma, terminará com dois ficheiros: mydomain.csr para submeter, e mydomain.key para guardar. Confirme que o CSR contém o que espera antes de o submeter, seja com o nosso decodificador de CSR ou localmente:
openssl req -noout -text -verify -in mydomain.csr
Verifique se as entradas SAN estão listadas e se a assinatura é validada. Se preferir não usar a linha de comandos, o nosso gerador de CSR produz o mesmo par diretamente no navegador. Mais informação sobre os comandos subjacentes está no nosso guia de comandos OpenSSL.
Obter o certificado emitido
Submeta o CSR à CA, escolha o tipo de certificado que corresponde ao que está a proteger, e conclua a validação. Um certificado de domínio único cobre um nome de host, um wildcard cobre todos os subdomínios de primeiro nível, e um certificado multi-domínio (SAN) cobre uma lista de nomes não relacionados. Por detrás de um balanceador de carga, o multi-domínio é a escolha comum, já que uma instância HAProxy normalmente serve como front-end para vários sites.
A CA devolve um arquivo contendo o seu certificado e a cadeia intermediária, geralmente como um ficheiro CA bundle. Ambos já estão em formato PEM, que é o que precisa. Planeie a renovação desde já e não deixe para depois: desde 15 de março de 2026 um certificado TLS publicamente confiável pode ser válido por no máximo 200 dias, descendo para 100 dias em março de 2027 e 47 dias em março de 2029, pelo que a substituição manual deixa de ser prática dentro de pouco tempo.
Construir o ficheiro PEM que o HAProxy vai ler
Crie um diretório para os certificados e monte o ficheiro aí. Mantenha tudo num único local desde o início; dividir isto entre um diretório home, /etc/haproxy e /etc/ssl é como as pessoas acabam por editar um ficheiro enquanto o HAProxy lê outro.
sudo mkdir -p /etc/haproxy/certs
sudo chmod 700 /etc/haproxy/certs
Concatene o certificado, depois os intermediários, depois a chave privada. O redirecionamento tem de ser executado como root, portanto encaminhe para tee em vez de escrever sudo cat ... > /etc/haproxy/certs/..., que falha com um erro de permissão porque a shell abre o ficheiro de saída como o seu próprio utilizador antes de o sudo alguma vez ser executado:
cat mydomain.crt intermediate.crt mydomain.key
| sudo tee /etc/haproxy/certs/mydomain.pem > /dev/null
Esse ficheiro agora contém a sua chave privada em texto simples, portanto bloqueie-o antes de avançar:
sudo chown root:root /etc/haproxy/certs/mydomain.pem
sudo chmod 600 /etc/haproxy/certs/mydomain.pem
Permissões exclusivas para root são o correto aqui, não um obstáculo. O HAProxy é iniciado com privilégios de superutilizador, o que o seu manual refere ser necessário para que depois possa mudar para o seu próprio utilizador sem privilégios, e é durante esse arranque que ele lê o certificado. Não há necessidade de alargar as permissões para que o utilizador haproxy possa ler a chave, e não deve fazê-lo.
Se construiu o CSR numa máquina diferente, copie os ficheiros primeiro e elimine as cópias do diretório de trânsito depois:
scp mydomain.crt intermediate.crt mydomain.key sysadmin@haproxy-server:/home/sysadmin/
Configurar o HAProxy
Abra o /etc/haproxy/haproxy.cfg num editor de terminal no próprio servidor, como nano ou vim. Edite-o diretamente em vez de o fazer numa estação de trabalho, para que nunca esteja a recarregar um ficheiro diferente daquele que testou.
O frontend
Um único frontend pode aceitar tanto HTTP simples quanto HTTPS. Vincule a porta 80 para o redirecionamento, vincule a porta 443 com o certificado, e envie tudo o resto para o backend:
frontend web_frontend
mode http
bind *:80
bind *:443 ssl crt /etc/haproxy/certs/mydomain.pem alpn h2,http/1.1
http-request redirect scheme https code 301 unless { ssl_fc }
default_backend web_servers
alpn h2,http/1.1 oferece HTTP/2 e recorre a HTTP/1.1 caso necessário. O redirecionamento só é acionado quando o pedido não chegou por TLS, o que é o que ssl_fc testa, portanto os pedidos na porta 443 passam diretamente.
Coloque todas as opções TLS naquela única linha bind
É aqui que as configurações do HAProxy mais frequentemente correm mal, e falha em silêncio. Os guias apresentam frequentemente o endurecimento (hardening) do TLS como um segundo passo, mostrando uma nova linha bind para a porta 443 com opções extras nela. Se adicionar essa linha em vez de editar a existente, acaba com duas linhas bind para a mesma porta, e o HAProxy não se queixa. Ele inicia, e abre dois sockets de escuta separados na porta 443 com definições TLS diferentes. Em qual socket cada ligação cai não é algo que possa controlar, pelo que o seu endurecimento cobre aproximadamente metade do seu tráfico.
A verificação da configuração também não deteta isto, e a sua própria documentação explica porquê: -c “apenas realiza uma verificação dos ficheiros de configuração e termina antes de tentar vincular“. Um listener duplicado é uma condição que ocorre no momento do binding, portanto uma verificação de sintaxe nunca a irá detetar.
Defina as predefinições globais em vez disso, para que todas as linhas bind no ficheiro as herdem e não haja nada para duplicar:
global
ssl-default-bind-options ssl-min-ver TLSv1.2 prefer-client-ciphers
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
Vale a pena saber antes de copiar esse bloco para algum lado: ssl-min-ver já assume por defeito TLSv1.2, nas próprias palavras do HAProxy. Defini-lo como TLSv1.2 não muda nada e apenas documenta a intenção, o que é bom, mas não é a melhoria de segurança que muitas vezes é apresentada como sendo. As duas definições de cifras é que fazem trabalho real, e são separadas por propósito: ssl-default-bind-ciphers aplica-se ao TLS 1.2 e inferiores, ssl-default-bind-ciphersuites aplica-se ao TLS 1.3. Defina apenas a primeira e os seus conjuntos TLS 1.3 permanecem nas predefinições.
O backend
Dê a cada servidor um endereço real. Isto importa mais do que parece:
backend web_servers
mode http
balance roundrobin
option httpchk GET /
server web1 10.0.0.11:80 check
server web2 10.0.0.12:80 check
Uma linha server escrita como server web1 :80 check, com o endereço em falta, não gera um erro. O HAProxy aceita-a e resolve o endereço em falta para 0.0.0.0, que o seu manual trata como um valor especial que significa que a ligação é reencaminhada para o mesmo endereço IP a que o cliente se ligou. Esse endereço é o próprio HAProxy, portanto o backend acaba silenciosamente por apontar para a própria porta 80 do HAProxy, que é o frontend que acabou de configurar. O tráfico faz um ciclo de volta para o redirecionamento em vez de chegar a qualquer aplicação, e as verificações de saúde parecem saudáveis porque há realmente algo à escuta. Se um balanceador de carga responder a todos os pedidos HTTPS com um redirecionamento para si próprio, verifique primeiro as linhas server.
Como o HAProxy termina o TLS, os backends recebem HTTP simples na porta 80 e não precisam de certificado próprio. Se a política exigir encriptação também nesse trecho, adicione ssl verify required e um ficheiro CA às linhas server, e aponte-as para a porta 443 em vez disso.
Passe o esquema original ao backend. Como o backend agora recebe HTTP simples, uma aplicação que gere URLs absolutos, como WordPress, Django e Rails todos fazem, irá gerá-los com http://, o que se manifesta como conteúdo misto ou como um ciclo de redirecionamento que a própria aplicação cria. Adicione uma linha ao frontend:
http-request set-header X-Forwarded-Proto https if { ssl_fc }
e uma ao backend, que também passa o endereço IP real do cliente:
option forwardfor
A maioria das frameworks depois precisa de ser informada para confiar nesses cabeçalhos; essa parte é configurada na aplicação, não no HAProxy.
Verifique a configuração antes de a aplicar
Nunca reinicie um balanceador de carga com um ficheiro não verificado. Valide primeiro:
sudo haproxy -c -V -f /etc/haproxy/haproxy.cfg
Com -V ele imprime Configuration file is valid em caso de sucesso e devolve o estado de saída zero. Sem ele, o sucesso é silencioso. Quaisquer avisos são reportados independentemente de o ficheiro ser válido ou não, portanto leia a saída em vez de confiar na ausência de texto em vermelho.
Recarregue em vez de reiniciar
sudo systemctl reload haproxy
A distinção é real num balanceador de carga. Um reload inicia um novo processo e sinaliza o antigo para “terminar o que estão a fazer e depois saírem”, pelo que os pedidos já em curso são concluídos normalmente. Um restart sinaliza o processo antigo para “terminar imediatamente sem concluir o que estavam a fazer”, o que corta ligações ativas, incluindo uploads e chamadas de API de longa duração. Use restart apenas quando um reload não conseguir aplicar a alteração, como depois de alterar as definições de processo na secção global.
Confirme que o serviço voltou e está à escuta em ambas as portas:
sudo systemctl status haproxy
sudo ss -tlnp | grep haproxy
Exatamente um socket de escuta por porta é o que quer aqui. Dois na porta 443 significa que tem a linha bind duplicada descrita anteriormente.
Verifique se o certificado está a ser servido
Verifique o que o HAProxy realmente apresenta, incluindo a cadeia, a partir do próprio servidor:
openssl s_client -connect mydomain.com:443 -servername mydomain.com < /dev/null
Leia a secção Certificate chain no topo da saída. O seu certificado deve aparecer na profundidade 0 e o intermediário na profundidade 1. Se a profundidade 1 estiver em falta, o intermediário nunca chegou ao ficheiro PEM, e o site vai funcionar em alguns navegadores enquanto falha noutros. Ignore a linha Verify return code ao avaliar isto: ela reporta apenas o veredicto da cadeia, e pode ler-se como sucesso em situações que nada têm a ver com o que está a testar.
Depois confirme a partir do exterior, onde o resultado reflete o que os visitantes reais obtêm. O nosso SSL Checker reporta o certificado, a cadeia e a data de expiração.
Renovações e automação
Substituir o ficheiro PEM é todo o procedimento de renovação: reconstrua-o a partir do novo certificado e da mesma chave ou de uma nova, e depois recarregue. Nada na configuração do HAProxy referencia a data de expiração, portanto não é necessária nenhuma edição de configuração enquanto o caminho do ficheiro permanecer o mesmo.
Com os prazos de validade dos certificados a encurtar, vale a pena configurar a automação já agora. O HAProxy ganhou um cliente ACME incorporado na versão 3.2, configurado através de uma secção acme. Trate-o como uma pré-visualização e não como infraestrutura de produção por agora: ainda está marcado como experimental na 3.4 e exige expose-experimental-directives na secção global, suporta apenas os tipos de desafio http-01, dns-01 e dns-persist-01, e os certificados que gera têm de ser extraídos do socket de estatísticas (stats socket) para chegarem ao disco. O tipo dns-persist-01, adicionado na 3.4, usa um registo TXT estático que é definido uma vez e nunca muda entre renovações, pelo que não exige acesso de escrita à API do fornecedor DNS em cada renovação. A alternativa consolidada é executar um cliente ACME externo e fazer com que o seu passo de implementação (deploy) reconstrua o ficheiro PEM e recarregue o HAProxy, que é o mesmo padrão descrito no nosso guia ACME para Apache e NGINX.
Perguntas Frequentes
O seu certificado primeiro, depois quaisquer intermediários, depois a chave privada. O manual do HAProxy descreve o ficheiro como sendo construído pela concatenação de ficheiros PEM e diz que o intermediário pode ser concatenado nele. Se preferir manter a chave separada, deixe-a fora por completo e guarde-a com o mesmo caminho acrescido de .key, que o HAProxy carrega automaticamente.
Normalmente uma linha server no backend sem endereço, como server web1 :80 check. O HAProxy resolve o endereço vazio para 0.0.0.0, e esse endereço significa que a ligação é reencaminhada para o mesmo endereço IP a que o cliente se ligou, que é o próprio HAProxy. O backend, portanto, aponta para a própria porta 80 do HAProxy, que é o frontend que emite o redirecionamento de HTTP para HTTPS. Dê a cada linha server um endereço IP real ou um nome de host.
Pode, e esse é o problema. O HAProxy não as mescla nem avisa, e haproxy -c passa porque termina antes de tentar vincular. Fica com dois sockets de escuta numa única porta, com quaisquer opções TLS diferentes que cada linha traga, portanto uma definição presente em apenas uma delas aplica-se apenas a parte do seu tráfico. Mantenha uma linha bind por porta e coloque as definições TLS partilhadas em ssl-default-bind-options.
Não por si só. O HAProxy documenta o valor predefinido de ssl-min-ver como já sendo TLSv1.2, portanto defini-lo para o mesmo valor apenas regista a sua intenção sem alterar o comportamento. O verdadeiro endurecimento vem das definições de cifras, e lembre-se de que o TLS 1.3 precisa de ssl-default-bind-ciphersuites enquanto o TLS 1.2 e inferiores usam ssl-default-bind-ciphers.
Não na configuração padrão. O HAProxy termina o TLS na borda e reenvia HTTP simples, razão pela qual apenas o balanceador de carga detém o certificado. Adicione ssl verify required com um ficheiro CA nas linhas server apenas se a sua política exigir que o trecho interno também seja encriptado.
Aponte o crt para um diretório em vez de um ficheiro. O HAProxy carrega todos os certificados que lá estiverem e escolhe o correto por requisição usando SNI, portanto uma única linha bind cobre todos eles. Um certificado multi-domínio (SAN) é a outra opção, e adequa-se a um conjunto de nomes que renovam juntos.
O ramo 3.4, lançado em junho de 2026, é a versão atual de suporte de longo prazo e é mantido até ao segundo trimestre de 2031. Os ramos de numeração par do HAProxy são os LTS, com aproximadamente cinco anos de manutenção, enquanto ramos de numeração ímpar como o 3.3 recebem entre 12 e 18 meses. Tudo neste guia aplica-se à versão 3.0 e posteriores; apenas o cliente ACME incorporado exige a 3.2 ou mais recente.
Se o certificado estiver instalado mas os navegadores continuarem a reclamar, os nossos guias sobre erros comuns de SSL cobrem as causas habituais, mais frequentemente uma cadeia incompleta ou um nome que o certificado não lista.
Economize 10% em certificados SSL ao fazer seu pedido hoje!
Emissão rápida, criptografia forte, 99,99% de confiança no navegador, suporte dedicado e garantia de reembolso de 25 dias. Código do cupom: SAVE10


