Certificado wildcard con Let's Encrypt mediante la validación DNS
Un certificado wildcard no se puede validar a través del servidor web, va obligatoriamente por un registro TXT en el DNS. Esta guía muestra la vía manual y la automática en Debian 13, Debian 12, Ubuntu 24.04 y Ubuntu 22.04, además de los errores en los que realmente se atasca el proceso.
Un certificado wildcard cubre todos los nombres de un mismo nivel: shop.MiDominio.es, mail.MiDominio.es, cliente-4711.MiDominio.es, incluidos los que hoy todavía no existen. Precisamente por eso el camino habitual, el que pasa por el servidor web, aquí ya no sirve. Esta guía muestra las dos vías viables, la manual y la automática, y presta especial atención a los puntos en los que la cosa se tuerce en la práctica.
Todo lo que sigue está comprobado en Debian 13, Debian 12, Ubuntu 24.04 LTS y Ubuntu 22.04 LTS. Los cuatro sistemas se diferencian en Certbot bastante más de lo que admiten la mayoría de las guías, así que más abajo encontrarás una tabla al respecto.
Por qué un certificado wildcard solo funciona por DNS
Let's Encrypt conoce tres métodos de validación. Dos de ellos quedan descartados para los wildcards:
- HTTP-01 deposita un archivo en
http://name/.well-known/acme-challenge/token. Pero para*.MiDominio.esno existe ningún nombre único bajo el que ese archivo pudiera estar. La autoridad de certificación tendría que consultar una cantidad infinita de nombres de host. - TLS-ALPN-01 tiene el mismo problema, también valida un host concreto en el puerto 443.
- DNS-01 comprueba un registro TXT en
_acme-challenge.MiDominio.es. Quien puede crear ese registro controla la zona y, con ella, cualquier nombre por debajo. Es la única prueba que encaja con un asterisco.
En la práctica esto significa que --apache, --nginx, --webroot y --standalone no se pueden usar para wildcards. Quien lo intenta igualmente recibe este mensaje:
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.
No es un fallo de tu configuración, sino la respuesta correcta a una petición imposible. Para el caso normal, con unos pocos nombres fijos, la vía del servidor web sigue siendo la adecuada, y la describimos en el artículo sobre el certificado SSL gratuito con Certbot.
Un segundo punto que casi todas las guías se callan: un certificado wildcard cubre solo los nombres de un nivel por debajo. *.MiDominio.es vale para shop.MiDominio.es, pero ni para MiDominio.es en sí ni para a.b.MiDominio.es. El dominio raíz tienes que solicitarlo aparte, y eso tiene consecuencias para el registro TXT, como verás más abajo.
Requisitos y disponibilidad de paquetes según la distribución
Necesitas acceso root por SSH, un dominio cuya zona administres y Certbot. Para la emisión no hace falta un servidor web en marcha, ni que el puerto 80 esté abierto. Es un efecto secundario agradable: puedes emitir un certificado incluso para un servicio que no está conectado a internet.
Instala Certbot y las herramientas de DNS:
apt update
apt install -y certbot bind9-dnsutils
El paquete bind9-dnsutils aporta dig. En los cuatro sistemas, el nombre antiguo dnsutils ya no es más que un paquete de transición que apunta a bind9-dnsutils. Comprueba qué versión de Certbot te ha tocado:
certbot --version
Las diferencias son considerables y deciden qué vía tienes realmente disponible:
| Sistema | Certbot | Plugins en los repositorios de la distribución |
| 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 |
Y aquí viene la sorpresa: Debian 13 ha sacado del archivo la mayoría de los plugins de DNS. Si en Debian 12 trabajabas con python3-certbot-dns-ovh o python3-certbot-dns-linode y actualizas a Debian 13, allí sencillamente ya no encontrarás el paquete. Un apt upgrade que cruza la frontera entre distribuciones lo elimina, y la renovación se interrumpe sin que nadie se dé cuenta. Comprueba esto antes de cambiar de distribución.
Qué plugins se cargan realmente en tu sistema lo ves con:
certbot plugins
La vía manual con un registro TXT
La vía manual no necesita acceso a ninguna API y funciona con cualquier proveedor de DNS. Sirve para hacer pruebas y para zonas que de todas formas tocas pocas veces. Tiene un inconveniente serio, al que llegamos enseguida.
Baja antes el TTL del futuro registro TXT en tu zona, entre 60 y 300 segundos. No cuesta nada y te ahorra espera después. Entonces:
certbot certonly --manual --preferred-challenges dns \
--cert-name midominio.es \
-d "*.MiDominio.es" -d MiDominio.es
Las comillas alrededor de "*.MiDominio.es" son obligatorias. Sin ellas, el shell sustituye el asterisco por los nombres de archivo del directorio actual y Certbot solicita certificados para tus archivos. --cert-name también es muy recomendable: de lo contrario, Certbot deriva el nombre del directorio del certificado a partir del primer nombre, y nadie quiere tener que buscar un directorio con un asterisco en el nombre.
Certbot se detiene y muestra algo así:
Please deploy a DNS TXT record under the name:
_acme-challenge.MiDominio.es.
with the following value:
gfj9Xq...Rg85nM
Aquí llega el punto en el que fracasan la mayoría de los intentos. Has solicitado dos nombres, el asterisco y el dominio raíz. Son dos validaciones separadas y ambas caen sobre el mismo nombre de registro _acme-challenge.MiDominio.es, con dos valores distintos. Certbot lo dice claramente:
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.
Sin embargo, muchos paneles de DNS ofrecen un único campo de entrada para el mismo nombre y sustituyen el primer valor por el segundo. Al final solo queda un valor en la zona, una de las dos validaciones falla y el mensaje de error menciona igualmente un solo nombre. Si tu panel no admite dos registros TXT con el mismo nombre, eso descarta la vía manual. Usa entonces la delegación por CNAME, más abajo.
Comprueba primero, pulsa Enter después
Certbot espera tu confirmación. No pulses Enter de inmediato. Abre una segunda sesión SSH y consulta primero el servidor de nombres autoritativo, no el resolver local:
dig +short NS MiDominio.es
dig +short TXT _acme-challenge.MiDominio.es @ns1.proveedor.example
dig +short TXT _acme-challenge.MiDominio.es @1.1.1.1
dig +short TXT _acme-challenge.MiDominio.es @8.8.8.8
Pulsa Enter solo cuando ambos valores aparezcan en una misma consulta, y además en varios resolvers independientes entre sí. Una salida vacía significa que el registro todavía no está ahí. Así se ve en un dominio sin registro, la salida queda vacía:
dig +short TXT _acme-challenge.example.com @1.1.1.1
¿Por qué ese rodeo por el servidor autoritativo? Si consultas _acme-challenge antes de haber creado el registro, tu resolver memoriza esa inexistencia durante todo el TTL negativo que indica el registro SOA, a menudo una hora entera. Entonces no ves nada durante mucho rato aunque el registro lleve tiempo publicado, y buscas el fallo en el sitio equivocado. El servidor autoritativo no tiene esa caché.
La pega de la vía manual
Un certificado emitido con --manual y sin script no se renueva nunca solo. En la siguiente ejecución automática, el log dice:
An authentication script must be provided with --manual-auth-hook when using
the manual plugin non-interactively.
Certbot se salta ese certificado y sigue con los demás, y el código de salida suele parecer inofensivo. Te enteras cuando el navegador protesta. Cuenta, por tanto, con repetir el mismo procedimiento a mano cada 60 a 90 días, o cambia a una de las vías automáticas.
La vía automática con un plugin del proveedor
Si tu proveedor de DNS tiene una API y existe un plugin de Certbot para ella, Certbot crea el registro TXT por su cuenta, espera, deja que se valide y lo vuelve a retirar. Esta es la vía que quieres para sistemas en producción. Con Cloudflare como ejemplo:
apt install -y python3-certbot-dns-cloudflare
Guarda las credenciales fuera del directorio web y protégelas de inmediato:
mkdir -p /root/.secrets/certbot
chmod 700 /root/.secrets/certbot
En /root/.secrets/certbot/cloudflare.ini va exactamente una línea:
dns_cloudflare_api_token = TuTokenAqui
Después, sin falta:
chmod 600 /root/.secrets/certbot/cloudflare.ini
De lo contrario, Certbot avisa en cada ejecución de que los permisos son demasiado amplios. Usa un token restringido con permiso de escritura sobre los registros DNS, no la clave global de la cuenta. La clave global todavía funciona, pero puede hacer cualquier cosa en tu cuenta y luego queda en texto plano en el servidor. Un token se puede limitar a una única zona y revocar por separado si algo sale mal.
La emisión:
certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials /root/.secrets/certbot/cloudflare.ini \
--dns-cloudflare-propagation-seconds 60 \
--cert-name midominio.es \
-d "*.MiDominio.es" -d MiDominio.es
El valor de --propagation-seconds es el tiempo de espera entre la creación del registro y la consulta de validación. El valor por defecto son 10 segundos y se queda corto para muchas zonas. 60 segundos son un buen punto de partida, y 120 con proveedores lentos. Esta única cifra explica buena parte de las renovaciones que fallan de forma esporádica, esas que nadie más consigue reproducir.
Para otros proveedores el paquete se llama python3-certbot-dns-<proveedor>, y los parámetros siguen el mismo patrón. Mira la tabla de arriba para saber si tu proveedor está siquiera disponible en tu distribución.
Cuando falta el paquete adecuado
El reflejo inmediato es pip install certbot-dns-loquesea. En Debian 12, Debian 13 y Ubuntu 24.04 eso termina así:
error: externally-managed-environment
× This environment is externally managed
Es intencionado, no es un defecto. En Ubuntu 22.04 el mismo comando todavía pasa, pero entonces mezcla paquetes de pip con los paquetes del sistema, y en el siguiente apt upgrade las versiones de Certbot y del plugin ya no encajan. No lo fuerces con --break-system-packages.
La salida limpia es la versión snap de Certbot, que trae los plugins consigo y se mantiene actualizada sola. Quita antes el paquete de la distribución para que no haya dos Certbot administrando el mismo directorio:
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: los datos existentes en /etc/letsencrypt/ se conservan, el snap los adopta. Pero después el timer de systemd se llama snap.certbot.renew.timer y ya no certbot.timer. Quien pasa eso por alto acaba con dos timers o con ninguno.
Sin plugin del proveedor: rfc2136 y delegación CNAME
Dos métodos funcionan sea quien sea tu proveedor de DNS.
rfc2136 es la vía estándar para la actualización dinámica de DNS con clave TSIG. Funciona con BIND, Knot y PowerDNS, y está disponible como paquete en los cuatro sistemas:
apt install -y python3-certbot-dns-rfc2136
Si gestionas tú mismo tu DNS, esta es la solución más robusta, porque no necesita ningún servicio ajeno ni ninguna API HTTP.
La delegación CNAME es la respuesta más elegante a dos problemas a la vez. En tu zona principal creas una sola vez un registro que ya no volverá a cambiar:
_acme-challenge.MiDominio.es. CNAME MiDominio.es.acme.otra-zona.es.
Let's Encrypt sigue las cadenas de CNAME cuando busca el registro TXT. El registro TXT se crea entonces en la zona de destino, y solo ahí necesita el servidor permisos de escritura. Eso resuelve varias cosas de golpe:
- Las credenciales que hay en el servidor web no pueden modificar tu zona principal. Un servidor web comprometido no puede desviar registros MX.
- La zona de destino puede llevar varios valores TXT a la vez, aunque el panel de tu proveedor principal no sepa hacerlo.
- La zona de destino puede tener un TTL muy bajo sin que la zona principal lo sufra.
El propio CNAME no se vuelve a tocar nunca, así que puede tener un TTL alto. Se comprueba con:
dig +short CNAME _acme-challenge.MiDominio.es @1.1.1.1
Automatizar la renovación
El paquete de Certbot ya trae un timer que se ejecuta dos veces al día. Un certificado solo se renueva cuando hace falta:
systemctl list-timers certbot.timer
Si no está en marcha:
systemctl enable --now certbot.timer
En los cuatro sistemas el paquete trae dos disparadores: /lib/systemd/system/certbot.timer y, además, /etc/cron.d/certbot. El archivo de cron comprueba por sí mismo al principio si el timer está activo y en ese caso no hace nada, así que no se renueva dos veces. Por eso no necesitas un cron de renovación propio, sería el tercer disparador para la misma tarea.
Aquí hay una diferencia entre distribuciones que conviene conocer. Certbot hasta la versión 3 renueva cuando quedan menos de 30 días de validez. Certbot 4.0, es decir, la versión que trae Debian 13, renueva en cambio cuando queda un tercio de la vida útil. Con los 90 días habituales hoy, ambos llegan al mismo momento. En cuanto Let's Encrypt emita certificados de duración más corta, las dos versiones se comportarán de forma distinta, y solo la nueva se adapta automáticamente.
Prueba el proceso en seco. Así no se emite nada ni se consume ningún límite:
certbot renew --dry-run
Certbot no escribe un certificado wildcard en la configuración del servidor web, eso tienes que hacerlo tú una vez. Para que el servidor web cargue de verdad el certificado nuevo después de cada renovación, crea un deploy hook. Escríbelo como archivo, no como parámetro:
mkdir -p /etc/letsencrypt/renewal-hooks/deploy
El contenido de /etc/letsencrypt/renewal-hooks/deploy/reload-webserver.sh:
#!/bin/sh
systemctl reload nginx
Después, hazlo ejecutable:
chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-webserver.sh
Los scripts de este directorio se ejecutan para cada certificado renovado. El parámetro --deploy-hook, en cambio, solo se escribe en el archivo de renovación de aquellos certificados que se trataron justo en ese momento. Los certificados añadidos más tarde no lo tienen, y eso no se nota hasta meses después.
Una advertencia sobre las credenciales de la API: si el proveedor revoca el token o este caduca, la renovación falla sin que nada parezca roto. El certificado sigue siendo válido, al fin y al cabo. El servicio no se cae hasta 30 días más tarde. Comprueba por eso de vez en cuando que los certificados realmente se están renovando, y no te fíes de los avisos de caducidad por correo.
Cómo saber que de verdad ha funcionado
Que el comando terminara sin errores no demuestra nada. Estas tres comprobaciones sí. Primero, el resumen:
certbot certificates
Bajo Domains tienen que figurar ambos nombres, *.MiDominio.es y MiDominio.es. Si falta el asterisco, has obtenido un certificado normal y simplemente no te has dado cuenta.
Segundo, un vistazo al propio archivo:
openssl x509 -noout -text -in /etc/letsencrypt/live/midominio.es/fullchain.pem | grep -A1 "Subject Alternative Name"
Ahí tiene que aparecer DNS:*.MiDominio.es. El campo determinante es Subject Alternative Name, no el Common Name, que los navegadores modernos ya ni siquiera evalúan.
Tercero, y esta es la prueba de verdad, consulta un nombre que te acabes de inventar:
echo | openssl s_client -servername test-1234.MiDominio.es -connect MiDominio.es:443 2>/dev/null | openssl x509 -noout -subject -dates
Si eso devuelve un certificado válido y ninguna advertencia, el wildcard funciona de verdad. Solo entonces has terminado.
Errores frecuentes, palabra por palabra
- "DNS problem: NXDOMAIN looking up TXT for _acme-challenge.MiDominio.es": el registro no existe, todavía no se ha propagado, o lo has creado en el proveedor equivocado. El caso más frecuente: el dominio está registrado en el proveedor A, pero los servidores de nombres apuntan al proveedor B y el registro está en A. Lo único que cuenta es lo que devuelve
dig +short NS MiDominio.es. - "Incorrect TXT record ... found at _acme-challenge.MiDominio.es": hay un valor, pero es el equivocado. Típico después de una interrupción, cuando el valor antiguo sigue en la zona, o cuando el panel ha escrito el segundo valor encima del primero. Borra los registros
_acme-challengeantiguos y empieza de nuevo. - "DNS problem: SERVFAIL looking up TXT ... the domain's nameservers may be malfunctioning": casi siempre una firma DNSSEC rota, por ejemplo tras un cambio de proveedor en el que el registro DS antiguo se quedó publicado en la registry. Repáralo antes, o cualquier emisión fallará.
- "CAA record for MiDominio.es prevents issuance": la piedra en el camino que más a menudo se pasa por alto. Para los wildcards, la autoridad de certificación evalúa primero
issuewild. Quien ha puestoissue "letsencrypt.org", pero tiene al lado unissuewild ";", obtiene certificados normales y ningún wildcard. Compruébalo condig +short CAA MiDominio.es. - "too many certificates (5) already issued for this exact set of identifiers": para la misma combinación de nombres se permiten cinco certificados en siete días. Prueba por eso con
--dry-runo contra el entorno de pruebas con--test-cert. El bloqueo caduca por sí solo y no hay forma de levantarlo. - El panel muestra el registro TXT, pero dig no: algunos proveedores exigen que los cambios en la zona se publiquen de forma explícita. Un registro guardado no es automáticamente un registro activo.
- El nombre del registro queda duplicado: algunos paneles añaden el dominio automáticamente. Escribe ahí solo
_acme-challenge, o acabarás con_acme-challenge.MiDominio.es.MiDominio.es. Undigsobre el nombre completo lo delata al instante.
Perspectiva: DNS-PERSIST-01
Let's Encrypt trabaja en un nuevo método de validación llamado DNS-PERSIST-01. En lugar de publicar un token nuevo en cada renovación, depositas una sola vez un registro permanente que autoriza a una cuenta ACME concreta a emitir certificados. A partir de ahí, el servidor ya no necesita ningún permiso de escritura en el DNS para renovar. Para los wildcards eso supondría una ganancia clara en seguridad.
Según la hoja de ruta de Let's Encrypt, el entorno de pruebas estaba previsto para finales del primer trimestre de 2026 y el funcionamiento en producción para el segundo trimestre. Por ahora no se ha anunciado si Certbot admitirá el método. Así que todavía no cuentes con él, pero tenlo en el radar si justo ahora estás montando de cero una gestión de certificados.
Resumen
Un certificado wildcard solo es posible mediante la validación por DNS, porque un asterisco no se puede demostrar a través de un único servidor web. La vía manual con un registro TXT funciona en todas partes, pero no se renueva nunca sola. La vía del plugin del proveedor es la única que puedes dejar funcionando sin supervisión, y en la práctica suele fallar por un tiempo de espera demasiado corto o por credenciales que se han invalidado en silencio. Si solo te quedas con una cosa: comprueba el registro TXT en el servidor de nombres autoritativo antes de dejar que Certbot siga adelante, y cuenta con dos registros bajo el mismo nombre en cuanto pidas el asterisco más el dominio raíz.
Preguntas frecuentes
¿Por qué no puedo emitir un certificado wildcard con Apache o nginx?
¿El certificado *.MiDominio.es cubre también MiDominio.es?
¿Por qué necesito dos registros TXT con el mismo nombre?
¿Cómo compruebo si el registro TXT ya se ha propagado?
¿Se renueva automáticamente un certificado wildcard emitido a mano?
¿Qué plugins de DNS para Certbot hay en Debian 13?
¿Qué aporta una delegación CNAME de _acme-challenge?
2026 KernelHost GmbH. Todos los derechos reservados. Esta guía está protegida por derechos de autor. Su publicación en otros sitios web, aunque sea de forma parcial o modificada, no está permitida sin nuestro consentimiento por escrito. Las citas con indicación de la fuente y un enlace son muy bienvenidas.

