Cliente ACME Lego
O cliente ACME Lego é um projeto independente, gratuito e de código aberto escrito na linguagem Go. É ideal para integração personalizada e scripting e beneficia de amplo suporte por parte dos registadores de domínios e fornecedores de DNS. O Lego é um cliente ACME flexível que pode ser facilmente integrado em sistemas e scripts personalizados. Além da validação HTTP-01, oferece validação DNS através de muitos fornecedores de DNS (lista de fornecedores de DNS suportados) para obter certificados SSL WildCard.
O guia utiliza sintaxe verificada na versão Lego 5.*.* e destina-se a Debian/Ubuntu com Apache 2 e o cliente ACME Lego.
Conteúdo do artigo
- Instalação do Lego
- Apache, webroot
- Ficheiros de configuração do Lego
- Emissão do certificado
- Implementação no Apache
- Renovação automática
Conceitos básicos
- ACME – protocolo para emissão e renovação automatizadas de certificados SSL/TLS.
- HTTP-01 – método de validação ACME que verifica a propriedade do domínio utilizando um ficheiro temporário acessível através de HTTP.
- DNS-01 – método de validação através do registo DNS TXT
_acme-challenge. - EAB kid + hmac – detalhes External Account Binding (EAB) da autoridade de certificação. Ligam o Certbot a uma conta ou produto.
- Systemd service - um ficheiro de configuração que indica ao sistema Linux como iniciar uma aplicação e mantê-la em execução mesmo após um reinício do servidor.
Se o domínio example.com aparecer nos exemplos, substitua-o sempre pelo seu próprio domínio.
Instalação do Lego
apt update
apt install -y curl tar
cd /tmp
LEGO_URL=$(curl -s https://api.github.com/repos/go-acme/lego/releases/latest | sed -n 's/.*"browser_download_url": "\(.*linux_amd64.tar.gz\)".*/\1/p' | head -n1)
echo "$LEGO_URL"
curl -L -o lego.tar.gz "$LEGO_URL"
tar -xzf lego.tar.gz
install -m 0755 lego /usr/local/bin/lego
lego --version
Após uma instalação bem-sucedida, recomendamos remover os ficheiros temporários.
rm -f /tmp/lego /tmp/lego.tar.gz /tmp/LICENSE /tmp/CHANGELOG.md
| Comando / valor | O que faz / o que substituir |
|---|---|
apt update |
Atualiza a lista de pacotes. |
apt install -y curl tar |
Instala as ferramentas para descarregar e extrair o Lego. |
LEGO_URL=... |
Encontra o URL do pacote de versão Linux amd64 mais recente. |
curl -L -o lego.tar.gz |
Descarrega o arquivo do Lego. |
tar -xzf lego.tar.gz |
Extrai o arquivo. |
install -m 0755 lego /usr/local/bin/lego |
Instala o Lego como um comando de sistema executável. |
lego --version |
Verifica a versão instalada do Lego. |
Apache, webroot
Este procedimento cria uma configuração básica de VirtualHost para o domínio na porta 80. Define o DocumentRoot, as permissões do diretório web, cria os logs do Apache, ativa a configuração utilizando o a2ensite, verifica a sua correção (apache2ctl configtest) e recarrega as alterações. Por fim, verifica a disponibilidade do website utilizando um pedido HTTP curl.
Antes de executar, substitua o valor example.com na linha DOMAIN="example.com" pelo seu próprio domínio. A variável $DOMAIN é depois utilizada nos comandos seguintes para os caminhos, o vhost do Apache e a página de teste.
cd /var/www
apt update
apt install -y apache2
systemctl enable --now apache2
a2enmod rewrite headers ssl
systemctl reload apache2
# or just updates
apt update
apt install --only-upgrade apache2
systemctl reload apache2
DOMAIN="example.com"
mkdir -p /var/www/$DOMAIN/public
chown -R www-data:www-data /var/www/$DOMAIN
chmod -R 755 /var/www/$DOMAIN
echo "OK $DOMAIN" > /var/www/$DOMAIN/public/index.html
| Comando / valor | O que faz / o que substituir |
|---|---|
cd /var/www |
Muda para o diretório onde os ficheiros web são normalmente armazenados. |
apt update |
Atualiza a lista de pacotes. |
apt install -y apache2 |
Instala o Apache; o -y confirma automaticamente a instalação. |
systemctl enable --now apache2 |
Ativa o Apache no arranque do servidor e inicia-o ao mesmo tempo. |
a2enmod rewrite headers ssl |
Ativa os módulos para redirecionamentos, cabeçalhos e HTTPS. |
DOMAIN="example.com" |
Define a variável do domínio. Substitua example.com pelo seu próprio domínio. |
mkdir/chown/chmod/echo |
Cria o webroot, define as permissões para o Apache e guarda uma página de teste simples. |
Vhost HTTP tanto para o apex como para o subdomínio:
cat > /etc/apache2/sites-available/$DOMAIN.conf <<EOF
<VirtualHost *:80>
ServerName $DOMAIN
ServerAlias www.$DOMAIN
DocumentRoot /var/www/$DOMAIN/public
<Directory /var/www/$DOMAIN/public>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog \${APACHE_LOG_DIR}/${DOMAIN}_error.log
CustomLog \${APACHE_LOG_DIR}/${DOMAIN}_access.log combined
</VirtualHost>
EOF
a2ensite "$DOMAIN.conf"
apache2ctl configtest
systemctl reload apache2
curl -I "http://$DOMAIN"
curl -I "http://www.$DOMAIN"
Resultado: Após abrir http://example.com, a página de teste deve aparecer.
| Comando / valor | O que faz / o que substituir |
|---|---|
cat > ... <<EOF |
Escreve um novo vhost HTTP do Apache num ficheiro em sites-available. |
ServerName $DOMAIN |
O domínio principal do virtual host. |
ServerAlias www.$DOMAIN |
Cria o tratamento do subdomínio de primeiro nível. |
DocumentRoot |
O diretório a partir do qual o Apache serve o conteúdo. |
a2ensite "$DOMAIN.conf" |
Ativa o vhost. |
apache2ctl configtest |
Verifica a sintaxe da configuração do Apache. |
curl -I http://$DOMAIN |
Verifica a resposta HTTP do domínio. |
Ficheiros de configuração do Lego
A abordagem recomendada para o Lego v5 é armazenar as definições num ficheiro de configuração. O systemd service não precisa então de conter um comando longo com domínios e hooks.
Ficheiro de configuração lego.yml
O ficheiro .yml é um ficheiro de configuração de texto em formato YAML, utilizado para uma notação clara de definições, parâmetros e dados estruturados. Antes de guardar a configuração YAML, substitua example.com pelo seu próprio domínio, vas@email.cz pelo seu e-mail de contacto e os valores KID / HMAC pelos detalhes da sua encomenda de certificado ACME.
mkdir /etc/lego/$DOMAIN
nano /etc/lego/$DOMAIN/lego.yml
storage: /etc/lego/example.com
accounts:
certum-account:
server: certum
email: your@email.com # your email address for CA Certum
acceptsTermsOfService: true
eab:
kid: KID
hmacKey: HMAC
servers:
certum:
url: https://acme.certum.pl/directory
challenges:
http-chal:
http:
# Path to your website's document root.
# Lego will temporarily write a file to this directory .well-known/acme-challenge/
webroot: /var/www/example.com/public
certificates:
example-com:
account: certum-account
challenge: http-chal
domains:
- example.com
- www.example.com
renew:
days: 30
hooks:
deploy:
command: systemctl reload apache2
Dica! Pode gerar um conteúdo YML quase completo diretamente no servidor e depois basta preencher o e-mail, o kid e o hmacKey corretos. Basta executar o comando abaixo e copiar o conteúdo da página index.html para o ficheiro lego.yml.
›› Mostrar/Ocultar o YML preparado.
cat > "/var/www/$DOMAIN/public/index.html" <<EOF
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>${DOMAIN}</title>
<style>
body { font-family: sans-serif; max-width: 900px; margin: 40px auto; }
pre { background:#f4f4f4; padding:1em; overflow:auto; }
</style>
</head>
<body>
<h1>OK – ${DOMAIN}</h1>
<p>Apache is working correctly.</p>
<h2>lego.yml</h2>
<pre><code>storage: /etc/lego/${DOMAIN}
accounts:
certum-account:
server: certum
email: YOUR_EMAIL
acceptsTermsOfService: true
eab:
kid: YOUR_KID
hmacKey: YOUR_HMAC_KEY
servers:
certum:
url: https://acme.certum.pl/directory
challenges:
http-chal:
http:
webroot: /var/www/${DOMAIN}/public
certificates:
${DOMAIN//./-}:
account: certum-account
challenge: http-chal
domains:
- ${DOMAIN}
- www.${DOMAIN}
renew:
days: 30
hooks:
deploy:
command: systemctl reload apache2
</code></pre>
</body>
</html>
EOF
O ficheiro lego.yml contém o EAB HMAC, pelo que tem de ter permissões restritas. Na documentação, utilize apenas marcadores de posição.
chmod 600 /etc/lego/$DOMAIN/lego.yml
Verificar as permissões e o proprietário do ficheiro:
stat -c "%a %U:%G %n" /etc/lego/$DOMAIN/lego.yml
| Comando / valor | O que faz / o que substituir |
|---|---|
storage |
Diretório para a conta do Lego, os certificados e os metadados. |
accounts |
Definição da conta ACME, incluindo o e-mail e os detalhes EAB. |
servers.certum.url |
O endpoint ACME da Certum. |
challenges.http-chal |
Validação através de http. |
certificates |
Lista de certificados que o Lego deve gerir. |
domains |
O domínio apex e o domínio wildcard no certificado. |
renew.days |
Quantos dias antes da expiração o Lego deve renovar. |
hooks.deploy.command |
Comando após uma emissão ou renovação bem-sucedida, aqui o recarregamento do Apache. |
Emissão do certificado SSL/TLS
Antes de executar, verifique echo ${DOMAIN} ou defina a variável DOMAIN para o nome do seu domínio DOMAIN="example.com". A ferramenta Lego realiza a validação HTTP-01 utilizando um ficheiro armazenado temporariamente no webroot, verifica a propriedade do domínio e depois cria um certificado SSL/TLS. O certificado, a chave privada e o certificado do emissor (intermédio) serão armazenados no diretório /etc/lego/${DOMAIN}/certificates/.
lego --config /etc/lego/$DOMAIN/lego.yml
Durante a geração, o cliente ACME Lego imprime informações sobre o pedido:
root@vmiXXXXXXXX:~# echo ${DOMAIN}
example.com
root@:~# lego --config /etc/lego/$DOMAIN/lego.yml
INFO Archive account scope=accountID filepath=/etc/lego/example.com/accounts/acme.certum.pl/certum-acme/
archives=/etc/lego/example.com/archives/accounts/acme.certum.pl_certum-acme_1785270773.zip
INFO Private key saved. filepath=/etc/lego/example.com/accounts/acme.certum.pl/certum-account/certum-account.key
INFO Registering the account (EAB). email=your@email.com
WARN !!!! HEADS UP !!!!
Your account credentials have been saved in your
configuration directory at "/etc/lego/example.com/accounts".
You should make a secure backup of this folder now. This
configuration directory will also contain private keys
generated by lego and certificates obtained from the ACME
server. Making regular backups of this folder is ideal.
INFO Obtaining bundled SAN certificate. domains="example.com, www.example.com"
INFO Use solver. domain=www.example.com type=http-01
INFO Use solver. domain=example.com type=http-01
INFO http01: Trying to solve HTTP-01. domain=www.example.com
INFO The server validated our request. domain=www.example.com
INFO http01: Trying to solve HTTP-01. domain=example.com
INFO The server validated our request. domain=example.com
INFO Validations succeeded; requesting certificates. domains="example.com, www.example.com"
INFO Waiting for certificates. timeout=30s interval=500ms domains="example.com, www.example.com"
INFO Server responded with a certificate. domains="example.com, www.example.com"
INFO Writing file. filepath=/etc/lego/example.com/certificates/acmeapi-online.crt
INFO Writing file. filepath=/etc/lego/example.com/certificates/acmeapi-online.issuer.crt
INFO Writing file. filepath=/etc/lego/example.com/certificates/acmeapi-online.key
INFO Writing file. filepath=/etc/lego/example.com/certificates/acmeapi-online.pem
INFO Writing file. filepath=/etc/lego/example.com/certificates/acmeapi-online.json
Verificar os ficheiros do certificado SSL gerado
Mostra o conteúdo do diretório de certificados criado pelo serviço Lego, incluindo o certificado, a chave privada e o certificado do emissor para o domínio selecionado.
ls -la /etc/lego/$DOMAIN/certificates/
O diretório certificates/ contém o .crt emitido, o .key, os certificados intermédios da autoridade de certificação e os metadados.
Implementar o certificado no Apache
Este exemplo utiliza a variável ${DOMAIN}, que já deverá ter definido desde o início do guia. Antes de executar os comandos, pode certificar-se de que a variável está definida corretamente, por exemplo: echo ${DOMAIN}
A variável ${DOMAIN} é utilizada no nome do ficheiro de configuração, nos valores ServerName e ServerAlias e no caminho para o webroot.
Aviso! - os caminhos para o certificado SSL e a chave privada utilizam o domínio na forma example-com. Os caminhos têm de corresponder ao domínio utilizado na configuração do Lego.
cat > /etc/apache2/sites-available/${DOMAIN}-le-ssl.conf <<EOF
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName ${DOMAIN}
ServerAlias www.${DOMAIN}
DocumentRoot /var/www/${DOMAIN}/public
<Directory /var/www/${DOMAIN}/public>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
SSLEngine on
SSLCertificateFile /etc/lego/${DOMAIN}/certificates/${DOMAIN//./-}.crt
SSLCertificateKeyFile /etc/lego/${DOMAIN}/certificates/${DOMAIN//./-}.key
ErrorLog ${APACHE_LOG_DIR}/${DOMAIN}_ssl_error.log
CustomLog ${APACHE_LOG_DIR}/${DOMAIN}_ssl_access.log combined
</VirtualHost>
</IfModule>
EOF
a2ensite ${DOMAIN}-le-ssl.conf
apache2ctl configtest
systemctl reload apache2
curl -I https://${DOMAIN}
curl -I https://www.${DOMAIN}
Resultado: HTTPS funcional.
| Comando / valor | O que faz / o que substituir |
|---|---|
cat > ...-le-ssl.conf |
Cria o vhost HTTPS do Apache. |
ServerName / ServerAlias |
Especifica o domínio apex e o subdomínio. |
SSLCertificateFile |
Caminho para o certificado. |
SSLCertificateKeyFile |
Caminho para a chave privada. |
a2ensite |
Ativa o vhost HTTPS. |
systemctl reload apache2 |
Recarrega a nova configuração do Apache. |
curl -I https://... |
Verifica a resposta HTTPS. |
Renovação automática
O Lego pode renovar o certificado automaticamente, mas após a instalação não cria por si próprio as systemd units para a execução regular. É por isso necessário criar duas units para a renovação automática:
- lego-example-com-renew.service – executa a verificação e, se necessário, a renovação do certificado.
- lego-example-com-renew.timer – assegura que o serviço é executado diariamente a uma hora definida.
Antes de inserir, substitua example-com no nome do service/timer pelo seu próprio nome, se necessário, e substitua example.com no caminho da configuração pelo seu próprio domínio.
cat > /etc/systemd/system/lego-${DOMAIN//./-}-renew.service <<EOF
[Unit]
Description=Renew ACME Certum SSL for example.com using Lego HTTP-01
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/lego --config /etc/lego/${DOMAIN}/lego.yml
EOF
cat > /etc/systemd/system/lego-${DOMAIN//./-}-renew.timer <<EOF
[Unit]
Description=Daily Lego renewal check for ${DOMAIN}
[Timer]
OnCalendar=*-*-* 03:20:00
RandomizedDelaySec=1800
Persistent=true
[Install]
WantedBy=timers.target
EOF
Após criar as units, verifique o seu conteúdo:
cat /etc/systemd/system/lego-example-com-renew.service
echo "----------------"
cat /etc/systemd/system/lego-example-com-renew.timer
Recarregue as novas units, ative o timer e verifique se está em execução:
systemctl daemon-reload
systemctl enable --now lego-${DOMAIN//./-}-renew.timer
systemctl list-timers | grep lego
Resultado: O timer está ativo e o systemd agendou a sua próxima execução.
| Comando / valor | O que faz / o que substituir |
|---|---|
lego-example-com-renew.service |
Systemd service para uma execução única do Lego renew/run. |
Type=oneshot |
O serviço inicia, executa a sua tarefa e termina. |
ExecStart |
Executa o Lego de acordo com o lego.yml. |
lego-example-com-renew.timer |
Systemd timer que executa o serviço regularmente. |
OnCalendar |
Hora da verificação diária. |
RandomizedDelaySec |
Atraso aleatório para que os pedidos não comecem todos exatamente ao mesmo tempo. |
Persistent=true |
Executa uma execução perdida após o arranque do servidor. |
systemctl enable --now |
Ativa o timer e ativa-o imediatamente. |
Teste seguro do serviço:
systemctl start lego-${DOMAIN//./-}-renew.service
systemctl status lego-${DOMAIN//./-}-renew.service --no-pager
journalctl -u lego-${DOMAIN//./-}-renew.service -n 100 --no-pager
Resultado: Se o certificado não estiver perto de expirar, o Lego pode indicar que a renovação não é necessária. Este é o comportamento correto.
| Comando / valor | O que faz / o que substituir |
|---|---|
systemctl start ...service |
Executa manualmente o serviço de renovação para um teste. |
systemctl status ... |
Mostra se o serviço terminou com sucesso |
journalctl -u ... |
Mostra os logs mais recentes do serviço. |
Lista das units do Lego disponíveis:
ls -l /etc/systemd/system/lego*
systemctl list-timers | grep lego
Resultado: Ambas as variantes mostram todos os serviços e timers relacionados com o cliente ACME Lego.
Para onde seguir?
Voltar para Ajuda
Encontrou um erro ou não entendeu algo? Escreva para nós!
