Descripción general
El protocolo ACME (utilizado por Let's Encrypt y otras autoridades de certificación) admite el desafío DNS-01 para la validación de dominios. DNS-01 es el único tipo de desafío que admite certificados wildcard (*.example.com), y no requiere un servidor HTTP en la máquina de destino.
NexDNS ofrece integraciones nativas con los clientes ACME más populares, además de un hook de CLI genérico para cualquier cliente que admita hooks DNS manuales.
Todas las integraciones ACME requieren un token API, disponible en los planes Pro y superiores. Cada cliente busca la zona antes de escribir el desafío, así que el token necesita
zones.readademás derecords.readyrecords.write. Crea uno en nexdns.tech/settings/api-keys.
Cómo se valida un wildcard
El desafío es un registro TXT en _acme-challenge bajo el nombre que se está validando. Un certificado que cubre tanto example.com como *.example.com produce dos valores de desafío distintos en el mismo nombre, y ambos tienen que estar presentes a la vez – todas las integraciones de abajo lo gestionan, y por eso nunca debes eliminar el conjunto de registros entre las dos validaciones.
Deja margen para la propagación
Un registro de desafío tarda unos 30 segundos en llegar a los servidores de nombres, así que esperar 30 segundos no deja ningún margen: hemos visto fallar una validación con NXDOMAIN. Concede a la autoridad de certificación al menos 60 segundos: el plugin de certbot y lego esperan 60 por defecto, y en acme.sh y el hook de CLI la espera la defines tú.
acme.sh
acme.sh es un cliente ACME escrito íntegramente en shell. Nuestro hook de DNS todavía no forma parte de una versión de acme.sh, así que colócalo en ~/.acme.sh/dnsapi/ antes de la primera ejecución: curl -fsSL https://get.nexdns.tech/acme/dns_nexdns.sh -o ~/.acme.sh/dnsapi/dns_nexdns.sh. El mismo archivo está en el repositorio de la CLI por si prefieres leerlo antes.
Emitir un certificado
export NEXDNS_Token="nxd_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
acme.sh --issue --server letsencrypt --dns dns_nexdns \
--dnssleep 60 \
-d example.com -d '*.example.com'
El token se guarda en ~/.acme.sh/account.conf después de la primera ejecución, por lo que no necesitas exportarlo nuevamente para las renovaciones.
Renovar
Las renovaciones se realizan automáticamente mediante cron. Para forzar una renovación manual:
acme.sh --renew -d example.com
lego y Traefik
lego es un cliente ACME basado en Go que también está detrás de la gestión automática de certificados de Traefik. El proveedor se incluye en lego a partir de la versión 5.4.0.
Uso independiente
NEXDNS_API_TOKEN=nxd_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
NEXDNS_PROPAGATION_TIMEOUT=300 \
lego --dns nexdns \
--domains example.com \
--domains '*.example.com' \
--email admin@example.com \
--accept-tos \
run
lego lee sus tiempos de espera como un número simple de segundos: NEXDNS_PROPAGATION_TIMEOUT=300 funciona, mientras que 300s no se puede interpretar y se sustituye en silencio por el valor por defecto de 60 segundos.
Configuración de Traefik
Traefik incorpora la tabla de proveedores de lego al compilar y todavía usa una versión anterior, así que aquí hace falta una compilación de Traefik con lego 5.4.0. Añade el resolutor de desafío DNS de NexDNS a tu configuración de Traefik: el siguiente docker-compose.yml muestra una instalación típica:
services:
traefik:
image: traefik:v3 # lego >= v5.4.0
command:
- "--certificatesresolvers.nexdns.acme.dnschallenge=true"
- "--certificatesresolvers.nexdns.acme.dnschallenge.provider=nexdns"
- "--certificatesresolvers.nexdns.acme.email=admin@example.com"
- "--certificatesresolvers.nexdns.acme.storage=/letsencrypt/acme.json"
environment:
NEXDNS_API_TOKEN: "nxd_xxxxxxxxxxxxxxxxxxxx"
volumes:
- letsencrypt:/letsencrypt
- /var/run/docker.sock:/var/run/docker.sock:ro
ports:
- "443:443"
volumes:
letsencrypt:
Luego usa el resolver en las etiquetas de tu servicio:
labels:
- "traefik.http.routers.myapp.tls.certresolver=nexdns"
- "traefik.http.routers.myapp.tls.domains[0].main=example.com"
- "traefik.http.routers.myapp.tls.domains[0].sans=*.example.com"
cliente certbot
certbot es el cliente oficial de Let's Encrypt. Usa el plugin de autenticación DNS de NexDNS para la validación DNS-01 automatizada.
Instalar el plugin
Instala el plugin desde PyPI o usa la imagen de Docker de abajo, que ya lo incluye.
pip install certbot-dns-nexdns
Crear archivo de credenciales
Crea el archivo ~/.nexdns/certbot-credentials.ini con tu token API:
dns_nexdns_token = nxd_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Restringe los permisos del archivo:
chmod 600 ~/.nexdns/certbot-credentials.ini
Emitir un certificado
certbot certonly \
--authenticator dns-nexdns \
--dns-nexdns-credentials ~/.nexdns/certbot-credentials.ini \
-d example.com \
-d '*.example.com'
Uso con Docker
docker run --rm \
-v /etc/letsencrypt:/etc/letsencrypt \
-v ~/.nexdns/certbot-credentials.ini:/credentials.ini:ro \
nexdns/certbot certonly \
--non-interactive --agree-tos --email admin@example.com \
--authenticator dns-nexdns \
--dns-nexdns-credentials /credentials.ini \
-d example.com \
-d '*.example.com'
Hook de CLI
Si tu cliente ACME admite hooks DNS manuales, puedes usar el CLI de NexDNS como script de hook. Esto funciona con cualquier cliente que proporcione las opciones --manual-auth-hook y --manual-cleanup-hook (p. ej., certbot en modo manual).
certbot con hook de CLI
certbot certonly --manual --preferred-challenges dns \
--manual-auth-hook "nexdns acme hook --action create && sleep 60" \
--manual-cleanup-hook "nexdns acme hook --action delete" \
-d example.com \
-d '*.example.com'
El hook lee las variables de entorno CERTBOT_DOMAIN y CERTBOT_VALIDATION establecidas por certbot y crea o elimina el registro TXT _acme-challenge automáticamente.
El CLI debe estar autenticado antes de usar hooks. Ejecuta
nexdns auth token nxd_xxxo establece la variable de entornoNEXDNS_TOKEN.