Zimbra Letsencrypt Multidomínios Howto

Faz tempo que mantenho um ambiente de hospedagem de e-mails para pequenos clientes. Eles são muito especiais porque se preocupam de verdade com a privacidade, sem abrir mão de ter todos os recursos e comodidades dos grades provedores.

Na KyaHosting.com garantimos isso.

Mas em tempos de muito cuidado e proteção, ter conexões encriptadas reconhecidas pelos navegadores é muito importante. A iniciativa da EFF, Let’sEncrypt permite ter certificados atenticados e reconhecidos por quase todos os navegadores, gratuitamente.

Este tutorial se aplica às instalações que tem Proxy instalado e somente a elas. Isso porque o modo que vamos usar altera, exatamente, o Nginx que é usado pelo Zimbra como Proxy Reverso.

Meus requisitos são:

  1. Não ter que reiniciar o Zimbra a cada atualização
  2. Ser multidomínio, pois hospedo muitos domínios

Pré requisitos

  1. Seu Zimbra tem que ter instalado o Proxy
  2. O certbot tem que estar instalado

Metodologia

Nós vamos usar o método chamado “challenge ACME”. Nesse método o “certbot” escreve uma sequência única em um diretório específico que está acessível pela web. Para isso temos que criar o diretório e configurar o Nginx para responder corretamente a URL esperada pelos servidores da Let’sEncrypt.

Então mãos à obra!

Criando o diretório

Abaixo so comandos que usei. É claro que você poderá usar outro diretório, mas cuidado para acertar isso em todas as etapas.


mkdir /opt/zimbra/data/nginx/letsencrypt
chown zimbra: /opt/zimbra/data/nginx/letsencrypt

Alterando o template do Nginx

O que esta alteração vai fazer é criar entradas válidas no Nginx para todos os domínios configurados em seu Zimbra.

1 – Edite o arquivo /opt/zimbra/conf/nginx/templates/nginx.conf.web.http.template

2 – Adicione a linha a baixo antes da última } , assim:

     location ^~ /.well-known/acme-challenge { root /opt/zimbra/data/nginx/letsencrypt; }

}

Reiniciando o proxy para fazer as configurações:

su zimbra -c"/opt/zimbra/bin/zmproxyctl restart"

Testando

O Let’s Encrypt tem limitações de acesso, então o que fazemos é indicar um e-mail diferente por domínio para ser registrado.

Para saber se as configurações estão corretas, é hora de fazer um teste “–dry-run” com o certbot, assim:

certbot certonly -d webmail.dominio1.com --email letsencrypt@dominio1.com --agree-tos --webroot --webroot-path /opt/zimbra/data/nginx/letsencrypt/ --dry-run

Você pode esperar uma saída como esta:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for webmail.dominio1.com
Using the webroot path /opt/zimbra/data/nginx/letsencrypt for all unmatched domains.
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
- The dry run was successful.
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.

Sucesso!!!!

Gerando o certificado real

Basta executar o mesmo comando acima sem o “–dry-run”

certbot certonly -d webmail.dominio1.com --email letsencrypt@dominio1.com --agree-tos --webroot --webroot-path /opt/zimbra/data/nginx/letsencrypt/

O certificado estará salvo em /etc/letsencrypt/live/webmail.seudominio1.com

Assinando o certificado para poder usá-lo

O certificado gerado pelo Let’s Encrypt precisa ser assinado pela autoridade certificadora (CA) da sua instalação do Zimbra, ou vai dar erro. Em seguida o certificado e a chave precisam ser unidas.

Na sequência abaixo vamos juntar as partes e testar

a) Visando facilitar as linhas de comando, vamos começar entrando no diretório onde o Let’s Encrypt salvou seu certificado. Em nosso caso:

cd /etc/letsencrypt/live/webmail.seudominio1.com

b) Crie um arquivo chamado “chain.pem” com o conteúdo abaixo:

-----BEGIN CERTIFICATE-----
MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
-----END CERTIFICATE-----

c) Teste para saber se o certificado está correto, executando o comando abaixo:

/opt/zimbra/bin/zmcertmgr verifycrt comm privkey.pem cert.pem chain.pem

d) Junte os arquivos para assinar o certificado, assim:

>cert.bundle ; cat cert.pem chain.pem >> cert.bundle

e) Remova o certificado anterior se ele existir, assim:

rm -f /opt/zimbra/conf/domaincerts/dominio1.crt

f) Salve o novo certificado, assim:

/opt/zimbra/libexec/zmdomaincertmgr savecrt dominio1.com cert.bundle privkey.pem

g) Instale o certificado, assim:

/opt/zimbra/libexec/zmdomaincertmgr deploycrts

Reiniciando o Zimbra

A parte mais legal deste novo método é que não é preciso parar e reiniciar o Zimbra. Basta fazer um “reload”, que é instantâneo!

su zimbra -c"/opt/zimbra/bin/zmproxyctl reload"

Script!

Script para automatizar isso. Ele recebe o domínio como argumento e eu chamei ele de zm_ssl.sh

#! /bin/bash

if [ "$1" = "" ] ; then
echo "Faltou o domínio!"
exit
fi

oldIFS=$IFS
domain=$1

echo ""
echo "--------------------------------------------------------------------"
echo $domain
echo " "
echo "`date` - Começando o domínio $domain" >> /tmp/ssl_letsencrypt.log

# Gera o certificado
certbot certonly -d $domain --email letsencrypt@$domain --agree-tos --webroot --webroot-path /opt/zimbra/data/nginx/letsencrypt/

# Registrar se deu erro e abortar esse procedimento
if [ "$?" != "0" ] ; then
echo "Deu erro ao gerar o certificado para o domínio $domain"
echo "`date` - ERROR Letsencrypt - $domain" >> /tmp/ssl_letsencrypt.log
exit 1
fi

# Entrar no dir certo, que é o primeiro dominio
cd /etc/letsencrypt/live/$domain

echo "-----BEGIN CERTIFICATE----- 
MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ 
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT 
DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow 
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD 
Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB 
AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O 
rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq 
OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b 
xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw 
7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD 
aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV 
HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG 
SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 
ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr 
AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz 
R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 
JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo 
Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ 
-----END CERTIFICATE-----" >> chain.pem 

echo "Processando domínio $domain" 

# testando o certificado 
/opt/zimbra/bin/zmcertmgr verifycrt comm privkey.pem cert.pem chain.pem 
if [ "$?" != "0" ] ; then 
       echo "Erro ao testar certificado!" 
       echo "`date` - Erro para salvar o certificado!" >> /tmp/zm_ssl-error.log 
       echo "`date` - /opt/zimbra/bin/zmcertmgr verifycrt comm privkey.pem cert.pem chain.pem" >> /tmp/zm_ssl-error.log 
       exit 1 
fi 

# Adicionando o certificado 
>cert.bundle 
cat cert.pem chain.pem >> cert.bundle
rm -f /opt/zimbra/conf/domaincerts/${domain}.crt /opt/zimbra/conf/domaincerts/${domain}.key 
/opt/zimbra/libexec/zmdomaincertmgr savecrt $domain cert.bundle privkey.pem 
if [ "$?" != "0" ] ; then 
       echo "Erro para salvar o certificado!" 
       echo "`date` - Erro para salvar o certificado!" >> /tmp/zm_ssl-error.log 
       echo "`date` - /opt/zimbra/libexec/zmdomaincertmgr savecrt $domain cert.bundle privkey.pem" >> /tmp/zm_ssl-error.log 
       exit 1 
fi 

# Instalando o certificado 
/opt/zimbra/libexec/zmdomaincertmgr deploycrts 
if [ "$?" != "0" ] ; then 
       echo "Erro ao adicionar o certificado!" 
       echo "`date` - Erro ao adicionar o certificado!" >> /tmp/zm_ssl-error.log 
       echo "`date` - /opt/zimbra/libexec/zmdomaincertmgr savecrt $domain cert.bundle privkey.pem" >> /tmp/zm_ssl-error.log 
       exit 1 
fi 

echo "`date` - Certificado instalado para $domain" 
echo "`date` - Certificado instalado para $domain" >> /tmp/zm_ssl-error.log 

#echo "Reiniciando o Nginx do Zimbra..." 
su zimbra -c"/opt/zimbra/bin/zmproxyctl reload"

Atualizando os certificados

Agora que seu Zimbra não precisa ser parado para criar ou renovar certificados, pode-se rodar o comando “renew” som maiores problemas.

É claro que quando o certificado for renovado, será necessário repetir os procedimentos acima.

Para renovar os certificados execute:

certbot renew

E depois refaça a parte do script que assina, verifica, salva e instala o novo certificado.

Script para isso? em breve…. aqui mesmo…