Certificado wildcard com Let's Encrypt através da validação DNS
Um certificado wildcard não pode ser validado através do servidor web, passa obrigatoriamente por um registo TXT no DNS. Este guia mostra a via manual e a automática em Debian 13, Debian 12, Ubuntu 24.04 e Ubuntu 22.04, além dos erros em que o processo realmente encalha.
Um certificado wildcard cobre todos os nomes de um mesmo nível: shop.MeuDominio.pt, mail.MeuDominio.pt, cliente-4711.MeuDominio.pt, incluindo aqueles que hoje ainda nem existem. É precisamente por isso que o caminho habitual, o que passa pelo servidor web, aqui deixa de funcionar. Este guia mostra as duas vias possíveis, a manual e a automática, e dedica especial atenção aos pontos onde as coisas costumam correr mal na prática.
Tudo o que se segue foi testado em Debian 13, Debian 12, Ubuntu 24.04 LTS e Ubuntu 22.04 LTS. Os quatro sistemas diferem no Certbot bastante mais do que a maioria dos guias admite, por isso encontra mais abaixo uma tabela sobre o assunto.
Porque é que um certificado wildcard só funciona via DNS
O Let's Encrypt conhece três métodos de validação. Dois deles ficam de fora para os wildcards:
- HTTP-01 coloca um ficheiro em
http://name/.well-known/acme-challenge/token. Mas para*.MeuDominio.ptnão existe nenhum nome único sob o qual esse ficheiro pudesse estar. A autoridade de certificação teria de consultar uma quantidade infinita de nomes de host. - TLS-ALPN-01 tem o mesmo problema, valida igualmente um host concreto na porta 443.
- DNS-01 verifica um registo TXT em
_acme-challenge.MeuDominio.pt. Quem consegue criar esse registo controla a zona e, com ela, qualquer nome abaixo dela. É a única prova que encaixa num asterisco.
Na prática isto significa que --apache, --nginx, --webroot e --standalone não servem para wildcards. Quem tenta mesmo assim recebe esta mensagem:
Client with the currently selected authenticator does not support any
combination of challenges that will satisfy the CA. You may need to use an
authenticator plugin that can do challenges over DNS.
Não é uma falha da sua configuração, é a resposta correta a um pedido impossível. Para o caso normal, com alguns nomes fixos, a via do servidor web continua a ser a certa, e descrevemo-la no artigo sobre o certificado SSL gratuito com Certbot.
Um segundo ponto que quase todos os guias omitem: um certificado wildcard cobre apenas os nomes um nível abaixo. *.MeuDominio.pt vale para shop.MeuDominio.pt, mas nem para MeuDominio.pt em si nem para a.b.MeuDominio.pt. O domínio raiz tem de o pedir à parte, e isso tem consequências para o registo TXT, como verá mais abaixo.
Requisitos e a situação dos pacotes em cada distribuição
Precisa de acesso root por SSH, de um domínio cuja zona administre e do Certbot. Para a emissão não é necessário um servidor web em funcionamento, nem a porta 80 tem de estar aberta. É um efeito secundário agradável: pode emitir um certificado até para um serviço que não está sequer ligado à internet.
Instale o Certbot e as ferramentas de DNS:
apt update
apt install -y certbot bind9-dnsutils
O pacote bind9-dnsutils fornece o dig. Nos quatro sistemas, o nome antigo dnsutils já não passa de um pacote de transição que aponta para bind9-dnsutils. Verifique que versão do Certbot lhe calhou:
certbot --version
As diferenças são consideráveis e são elas que decidem qual das vias lhe fica sequer disponível:
| Sistema | Certbot | Plugins nos repositórios da distribuição |
| Debian 13 | 4.0.0 | cloudflare, desec, google, infomaniak, rfc2136, route53 |
| Debian 12 | 2.1.0 | cloudflare, digitalocean, dnsimple, gandi, gehirn, google, linode, ovh, rfc2136, route53, sakuracloud |
| Ubuntu 24.04 | 2.9.0 | cloudflare, digitalocean, dnsimple, gandi, gehirn, google, infomaniak, linode, ovh, rfc2136, route53, sakuracloud |
| Ubuntu 22.04 | 1.21.0 | cloudflare, digitalocean, dnsimple, gandi, gehirn, google, linode, ovh, rfc2136, route53, sakuracloud |
E aqui está a surpresa: o Debian 13 retirou do arquivo a maioria dos plugins de DNS. Quem trabalhava no Debian 12 com python3-certbot-dns-ovh ou python3-certbot-dns-linode e atualiza para o Debian 13 deixa simplesmente de encontrar lá o pacote. Um apt upgrade que atravessa a fronteira entre distribuições remove-o, e a renovação falha sem que ninguém repare. Verifique isto antes de mudar de distribuição.
Os plugins que o seu sistema carrega de facto são mostrados por:
certbot plugins
A via manual com registo TXT
A via manual não precisa de acesso a nenhuma API e funciona com qualquer fornecedor de DNS. Serve para experimentar e para zonas em que raramente mexe. Tem uma desvantagem grave, a que chegamos já a seguir.
Baixe antes o TTL do futuro registo TXT na sua zona, para 60 a 300 segundos. Não custa nada e poupa-lhe tempo de espera mais tarde. Depois:
certbot certonly --manual --preferred-challenges dns \
--cert-name meudominio.pt \
-d "*.MeuDominio.pt" -d MeuDominio.pt
As aspas à volta de "*.MeuDominio.pt" são obrigatórias. Sem elas, a shell substitui o asterisco pelos nomes de ficheiros do diretório atual e o Certbot pede certificados para os seus ficheiros. --cert-name é igualmente muito recomendável: caso contrário, o Certbot deriva o nome da pasta do certificado a partir do primeiro nome, e ninguém quer ter de procurar um diretório com um asterisco no nome.
O Certbot detém-se e mostra algo deste género:
Please deploy a DNS TXT record under the name:
_acme-challenge.MeuDominio.pt.
with the following value:
gfj9Xq...Rg85nM
Chega agora o ponto em que a maioria das tentativas falha. Pediu dois nomes, o asterisco e o domínio raiz. São duas validações separadas e ambas vão dar ao mesmo nome de registo _acme-challenge.MeuDominio.pt, com dois valores diferentes. O Certbot até o diz:
This must be set up in addition to the previous challenges; do not remove, replace, or undo the previous challenge tasks yet. Note that you might be asked to create multiple distinct TXT records with the same name. This is permitted by DNS standards.
Muitas interfaces de DNS oferecem, no entanto, um único campo para o mesmo nome e substituem o primeiro valor pelo segundo. No fim fica apenas um valor na zona, uma das duas validações falha, e a mensagem de erro continua a mencionar só um nome. Se a sua interface não admitir dois registos TXT com o mesmo nome, isso exclui a via manual. Use então a delegação por CNAME, mais abaixo.
Verifique primeiro, carregue no Enter depois
O Certbot fica à espera da sua confirmação. Não carregue logo no Enter. Abra uma segunda sessão SSH e consulte primeiro o servidor de nomes autoritativo, não o resolver local:
dig +short NS MeuDominio.pt
dig +short TXT _acme-challenge.MeuDominio.pt @ns1.fornecedor.example
dig +short TXT _acme-challenge.MeuDominio.pt @1.1.1.1
dig +short TXT _acme-challenge.MeuDominio.pt @8.8.8.8
Só quando ambos os valores aparecerem numa mesma consulta, e isso em vários resolvers independentes entre si, é que deve carregar no Enter. Uma saída vazia significa que o registo ainda não está lá. Assim se apresenta um domínio sem registo, a saída fica vazia:
dig +short TXT _acme-challenge.example.com @1.1.1.1
Porquê o desvio pelo servidor autoritativo? Se consultar _acme-challenge antes de ter criado o registo, o seu resolver memoriza essa inexistência durante todo o TTL negativo indicado no registo SOA, muitas vezes uma hora inteira. Fica então muito tempo sem ver nada, embora o registo já lá esteja há muito, e procura o erro no sítio errado. O servidor autoritativo não tem essa cache.
O senão da via manual
Um certificado emitido com --manual e sem script nunca se renova sozinho. Na execução automática seguinte, o log diz:
An authentication script must be provided with --manual-auth-hook when using
the manual plugin non-interactively.
O Certbot salta esse certificado e continua com os restantes, e o código de saída costuma passar despercebido. Só dá por isso quando o navegador reclama. Conte, portanto, com repetir o mesmo procedimento à mão a cada 60 a 90 dias, ou mude para uma das vias automáticas.
A via automática com um plugin do fornecedor
Se o seu fornecedor de DNS tiver uma API e existir um plugin do Certbot para ela, é o próprio Certbot que cria o registo TXT, espera, deixa validar e volta a retirá-lo. É esta a via que quer para sistemas em produção. Com a Cloudflare como exemplo:
apt install -y python3-certbot-dns-cloudflare
Guarde as credenciais fora do diretório web e proteja-as de imediato:
mkdir -p /root/.secrets/certbot
chmod 700 /root/.secrets/certbot
Em /root/.secrets/certbot/cloudflare.ini entra exatamente uma linha:
dns_cloudflare_api_token = OSeuTokenAqui
Depois disso, sem falta:
chmod 600 /root/.secrets/certbot/cloudflare.ini
Caso contrário, o Certbot avisa em cada execução que as permissões são demasiado amplas. Use um token restrito com direito de escrita nos registos DNS, não a chave global da conta. A chave global ainda funciona, mas pode fazer tudo na sua conta e fica depois em texto simples no servidor. Um token pode ser limitado a uma única zona e revogado isoladamente se algo correr mal.
A emissão:
certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials /root/.secrets/certbot/cloudflare.ini \
--dns-cloudflare-propagation-seconds 60 \
--cert-name meudominio.pt \
-d "*.MeuDominio.pt" -d MeuDominio.pt
O valor de --propagation-seconds é o tempo de espera entre a criação do registo e o pedido de validação. A predefinição são 10 segundos e fica curta para muitas zonas. 60 segundos são um bom ponto de partida, com fornecedores lentos até 120. Este único número explica grande parte das renovações que falham esporadicamente, aquelas que mais ninguém consegue reproduzir.
Para outros fornecedores o pacote chama-se python3-certbot-dns-<fornecedor>, e os parâmetros seguem o mesmo padrão. Consulte a tabela acima para saber se o seu fornecedor sequer está presente na sua distribuição.
Quando falta o pacote adequado
O reflexo imediato é pip install certbot-dns-qualquercoisa. No Debian 12, no Debian 13 e no Ubuntu 24.04 isso acaba assim:
error: externally-managed-environment
× This environment is externally managed
É intencional, não é um defeito. No Ubuntu 22.04 o mesmo comando ainda passa, mas mistura pacotes do pip com os pacotes do sistema, e no apt upgrade seguinte as versões do Certbot e do plugin deixam de encaixar. Não force isso com --break-system-packages.
A saída limpa é a versão snap do Certbot, que traz os plugins consigo e se mantém atualizada sozinha. Remova antes o pacote da distribuição, para que não fiquem dois Certbot a administrar o mesmo diretório:
apt remove -y certbot
snap install --classic certbot
ln -s /snap/bin/certbot /usr/bin/certbot
snap set certbot trust-plugin-with-root=ok
snap install certbot-dns-cloudflare
Importante: os dados existentes em /etc/letsencrypt/ mantêm-se, o snap assume-os. Mas depois o timer do systemd passa a chamar-se snap.certbot.renew.timer e já não certbot.timer. Quem não repara nisso fica com dois timers ou com nenhum.
Sem plugin do fornecedor: rfc2136 e delegação CNAME
Dois métodos funcionam independentemente de quem seja o seu fornecedor de DNS.
rfc2136 é a via padrão para a atualização dinâmica de DNS com chave TSIG. Funciona com BIND, Knot e PowerDNS e existe como pacote nos quatro sistemas:
apt install -y python3-certbot-dns-rfc2136
Se operar o seu próprio DNS, esta é a solução mais robusta, porque não precisa de nenhum serviço externo nem de nenhuma API HTTP.
A delegação CNAME é a resposta mais elegante a dois problemas ao mesmo tempo. Cria uma única vez, na sua zona principal, um registo que nunca mais muda:
_acme-challenge.MeuDominio.pt. CNAME MeuDominio.pt.acme.outra-zona.pt.
O Let's Encrypt segue as cadeias de CNAME quando procura o registo TXT. O registo TXT nasce portanto na zona de destino, e só aí é que o servidor precisa de permissões de escrita. Isto resolve vários pontos de uma só vez:
- As credenciais no servidor web não conseguem alterar a sua zona principal. Um servidor web comprometido não pode desviar registos MX.
- A zona de destino pode conter vários valores TXT em simultâneo, mesmo que a interface do seu fornecedor principal não saiba fazê-lo.
- A zona de destino pode ter um TTL muito baixo sem que a zona principal sofra com isso.
O próprio CNAME nunca mais é tocado, por isso pode ter um TTL alto. Verifica-se com:
dig +short CNAME _acme-challenge.MeuDominio.pt @1.1.1.1
Automatizar a renovação
O Certbot já traz do pacote um timer que corre duas vezes por dia. Um certificado só é renovado quando é mesmo necessário:
systemctl list-timers certbot.timer
Se não estiver a correr:
systemctl enable --now certbot.timer
Nos quatro sistemas o pacote traz dois gatilhos: /lib/systemd/system/certbot.timer e, além disso, /etc/cron.d/certbot. O ficheiro de cron verifica logo no início se o timer está ativo e, nesse caso, não faz nada, ou seja, não se renova duas vezes. Por isso não precisa de um cronjob de renovação próprio, seria o terceiro gatilho para a mesma tarefa.
Há aqui uma diferença entre distribuições que convém conhecer. O Certbot até à versão 3 renova quando faltam menos de 30 dias de validade. O Certbot 4.0, ou seja, a versão do Debian 13, renova em vez disso quando resta um terço do período de validade. Com os 90 dias habituais hoje em dia, ambos chegam ao mesmo momento. Assim que o Let's Encrypt emitir certificados de duração mais curta, as duas versões passam a comportar-se de forma diferente, e só a nova se adapta automaticamente.
Teste o processo em modo de simulação. Assim não se emite nada nem se gasta qualquer limite:
certbot renew --dry-run
Um certificado wildcard não é inscrito pelo Certbot na configuração do servidor web, isso tem de o fazer uma vez à mão. Para que o servidor web carregue mesmo o certificado novo depois de cada renovação, crie um deploy hook. Escreva-o como ficheiro, não como parâmetro:
mkdir -p /etc/letsencrypt/renewal-hooks/deploy
O conteúdo de /etc/letsencrypt/renewal-hooks/deploy/reload-webserver.sh:
#!/bin/sh
systemctl reload nginx
A seguir, torne-o executável:
chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-webserver.sh
Os scripts deste diretório correm para cada certificado renovado. O parâmetro --deploy-hook, pelo contrário, só é escrito no ficheiro de renovação exatamente dos certificados que foram tratados naquele momento. Os certificados acrescentados mais tarde já não o têm, e isso só se nota meses depois.
Um aviso quanto às credenciais da API: se o token for revogado no fornecedor ou expirar, a renovação falha sem que nada esteja visivelmente partido. Afinal, o certificado ainda é válido. Só 30 dias mais tarde é que o serviço fica em baixo. Verifique por isso de vez em quando que os certificados estão de facto a ficar mais recentes, e não confie nos avisos de expiração por e-mail.
Como perceber que resultou mesmo
O facto de o comando ter terminado sem erros não prova nada. Estas três verificações provam. Primeiro, o resumo:
certbot certificates
Em Domains têm de constar ambos os nomes, *.MeuDominio.pt e MeuDominio.pt. Se faltar o asterisco, recebeu um certificado normal e apenas não deu por isso.
Segundo, um olhar ao próprio ficheiro:
openssl x509 -noout -text -in /etc/letsencrypt/live/meudominio.pt/fullchain.pem | grep -A1 "Subject Alternative Name"
Aí tem de aparecer DNS:*.MeuDominio.pt. O campo determinante é Subject Alternative Name, não o Common Name, que os navegadores modernos já nem sequer avaliam.
Terceiro, e esta é a verdadeira prova, consulte um nome que acabou de inventar:
echo | openssl s_client -servername test-1234.MeuDominio.pt -connect MeuDominio.pt:443 2>/dev/null | openssl x509 -noout -subject -dates
Se isso devolver um certificado válido e nenhum aviso, o wildcard funciona mesmo. Só então é que terminou.
Erros frequentes, tal como aparecem
- "DNS problem: NXDOMAIN looking up TXT for _acme-challenge.MeuDominio.pt": o registo não existe, ainda não se propagou, ou criou-o no fornecedor errado. O caso mais frequente: o domínio está registado no fornecedor A, mas os servidores de nomes apontam para o fornecedor B e o registo está em A. O único que conta é o que
dig +short NS MeuDominio.ptdevolve. - "Incorrect TXT record ... found at _acme-challenge.MeuDominio.pt": existe lá um valor, mas o errado. Típico depois de uma interrupção, quando o valor antigo continua na zona, ou quando a interface escreveu o segundo valor por cima do primeiro. Apague os registos
_acme-challengeantigos e comece de novo. - "DNS problem: SERVFAIL looking up TXT ... the domain's nameservers may be malfunctioning": quase sempre uma assinatura DNSSEC danificada, por exemplo depois de uma mudança de fornecedor em que o registo DS antigo ficou publicado na registry. Corrija isso primeiro, senão qualquer emissão falha.
- "CAA record for MeuDominio.pt prevents issuance": a pedra no caminho que mais vezes passa despercebida. Para os wildcards, a autoridade de certificação avalia primeiro
issuewild. Quem definiuissue "letsencrypt.org", mas tem ao lado umissuewild ";", obtém certificados normais e wildcards não. Verifique comdig +short CAA MeuDominio.pt. - "too many certificates (5) already issued for this exact set of identifiers": para a mesma combinação de nomes são permitidos cinco certificados em sete dias. Teste por isso com
--dry-runou contra o ambiente de testes com--test-cert. O bloqueio expira sozinho e não há forma de o levantar. - A interface mostra o registo TXT, mas o dig não: alguns fornecedores exigem que as alterações à zona sejam publicadas de forma explícita. Um registo guardado não é automaticamente um registo ativo.
- O nome do registo fica duplicado: algumas interfaces acrescentam o domínio automaticamente. Escreva aí apenas
_acme-challenge, caso contrário resulta_acme-challenge.MeuDominio.pt.MeuDominio.pt. Umdigao nome completo denuncia isso de imediato.
Perspetiva: DNS-PERSIST-01
O Let's Encrypt está a trabalhar num novo método de validação chamado DNS-PERSIST-01. Em vez de publicar um token novo a cada renovação, deposita uma única vez um registo permanente que autoriza uma determinada conta ACME a emitir certificados. A partir daí, o servidor deixa de precisar de qualquer permissão de escrita no DNS para renovar. Para os wildcards isso seria um ganho claro em segurança.
Segundo o roteiro do Let's Encrypt, o ambiente de testes estava previsto para o final do primeiro trimestre de 2026 e a operação em produção para o segundo trimestre. Se o Certbot vai suportar o método, é algo que de momento não foi anunciado. Não conte já com isso, mas mantenha-o debaixo de olho se estiver justamente a montar de raiz uma gestão de certificados.
Resumo
Um certificado wildcard só é possível através da validação por DNS, porque um asterisco não se consegue demonstrar através de um único servidor web. A via manual com um registo TXT funciona em todo o lado, mas nunca se renova sozinha. A via do plugin do fornecedor é a única que pode deixar a correr sem supervisão, e na prática falha quase sempre por um tempo de espera demasiado curto ou por credenciais que se tornaram inválidas em silêncio. Se guardar apenas uma coisa: verifique o registo TXT no servidor de nomes autoritativo antes de deixar o Certbot prosseguir, e conte mesmo com dois registos sob o mesmo nome quando pedir o asterisco mais o domínio raiz.
Perguntas frequentes
Porque é que não posso emitir um certificado wildcard com o Apache ou o nginx?
O certificado *.MeuDominio.pt cobre também MeuDominio.pt?
Porque é que preciso de dois registos TXT com o mesmo nome?
Como verifico se o registo TXT já se propagou?
Um certificado wildcard emitido à mão renova-se automaticamente?
Que plugins de DNS para Certbot existem no Debian 13?
O que traz uma delegação CNAME de _acme-challenge?
2026 KernelHost GmbH. Todos os direitos reservados. Este guia está protegido por direitos de autor. A sua republicação noutros sites, na íntegra, em parte ou de forma editada, não é permitida sem o nosso consentimento por escrito. Citações com indicação da fonte e ligação são expressamente bem-vindas.

