HTTP-01 Challenge
Cuando solicitas un certificado, Let's Encrypt necesita verificar que controlas el dominio o subdominio específico para el que estás solicitando. El HTTP-01 Challenge verifica esto haciendo una solicitud HTTP en el puerto 80.
Por ejemplo: si solicitas certificado para api.domain.com, Let's Encrypt valida solo ese subdominio, no el dominio completo. Para cubrir múltiples subdominios, necesitas solicitar certificado para cada uno o usar wildcard vía DNS-01 Challenge que veremos más adelante.
Prerrequisito de DNS: Solo el registro A/CNAME apuntando a la IP del servidor (ya existente si el sitio funciona). No es necesario crear ningún registro adicional.
Prerrequisito del servidor:
- Puerto 80 accesible públicamente
- Servidor web respondiendo solicitudes HTTP
Cómo funciona:
- Ejecutas Certbot solicitando un certificado
- Let's Encrypt genera un token único y lo envía a Certbot
- Certbot crea automáticamente el archivo en
/.well-known/acme-challenge/TOKEN - Let's Encrypt hace solicitud HTTP para verificar el token
- Si se valida, el certificado es emitido
- Certbot elimina automáticamente el archivo de token
Certbot es el cliente ACME oficial desarrollado por Electronic Frontier Foundation (EFF) en asociación con Let's Encrypt. Automatiza todo el proceso de obtención y renovación de certificados.
¿Necesitas crear cuenta? ¡No! Certbot crea una cuenta automáticamente en la primera ejecución. Solo solicita un email (opcional) para avisos de expiración. Las credenciales quedan en /etc/letsencrypt/accounts/.
Como ACME es un protocolo abierto, existen otros clientes compatibles: acme.sh (shell script), Caddy (servidor web), Traefik (proxy reverso), cert-manager (Kubernetes).
Certbot es herramienta, no servicio. Lo instalas una única vez y él gestiona múltiples certificados para diferentes dominios en el mismo servidor. Después de la primera ejecución, Certbot configura automáticamente un systemd timer (o cron job) que verifica renovaciones 2x al día. Si un certificado está próximo al vencimiento, renueva automáticamente.
Importante: No necesitas crear ningún archivo manualmente. Certbot se encarga de todo el proceso.
Certbot es una aplicación completamente separada de tu aplicación real. Arquitectura:
Instalación de Certbot
# Ubuntu/Debian
sudo apt update
sudo apt install certbot
# Plugin para Nginx si es necesario
sudo apt install python3-certbot-nginx
# Plugin para Apache si es necesario
sudo apt install python3-certbot-apache
# CentOS/RHEL/Rocky + plugin
sudo dnf install certbot python3-certbot-nginx
Los plugins no son obligatorios, pero si quieres usar los comandos --nginx o --apache, que veremos adelante, facilitará mucho ya que configuran esos servidores web automáticamente. Sin plugin, usa certonly y configura manualmente.
| Modo | Plugin | Qué hace |
|---|---|---|
--nginx | Requiere plugin | Obtiene certificado y configura Nginx |
--apache | Requiere plugin | Obtiene certificado y configura Apache |
certonly | No requiere | Solo obtiene certificado (configuración manual) |
Obtener certificado
# Con Nginx (recomendado - configura automáticamente)
sudo certbot --nginx -d subdomain.domain.com.br
# Con Apache
sudo certbot --apache -d subdomain.domain.com.br
# Solo certificado (sin configurar servidor)
sudo certbot certonly --webroot -w /var/www/html -d subdomain.domain.com.br
Certbot hace automáticamente: recibe el token, crea el archivo en /.well-known/acme-challenge/, aguarda validación, elimina el archivo e instala el certificado creando el timer para renovación en el sistema.
Comandos Útiles
# Verificar el timer de renovación automática
systemctl list-timers | grep certbot
# Listar todos los certificados gestionados
certbot certificates
# Renovar todos los certificados (ejecutado automáticamente por el timer)
certbot renew
Dónde Quedan los Certificados
Después de validación exitosa, Certbot almacena los certificados en /etc/letsencrypt/:
/etc/letsencrypt/
├── live/
│ └── domain.com/
│ ├── cert.pem # Certificado del servidor
│ ├── chain.pem # Cadena intermedia
│ ├── fullchain.pem # cert.pem + chain.pem (usa este en el servidor)
│ └── privkey.pem # Clave privada (¡proteger!)
├── archive/ # Historial de certificados anteriores
├── renewal/ # Configuraciones de renovación
└── accounts/ # Credenciales de la cuenta ACME
En la configuración del servidor, usa:
ssl_certificate: apunta afullchain.pemssl_certificate_key: apunta aprivkey.pem
# Verificar certificados instalados
sudo certbot certificates
# Salida esperada:
# Certificate Name: domain.com
# Domains: domain.com
# Expiry Date: 2024-04-15 (VALID: 89 days)
# Certificate Path: /etc/letsencrypt/live/domain.com/fullchain.pem
# Private Key Path: /etc/letsencrypt/live/domain.com/privkey.pem
Renovación Manual (sistemas antiguos)
En sistemas sin systemd timer, agrega un cron job:
# Editar crontab
sudo crontab -e
# Agregar línea para renovación 2x al día
0 0,12 * * * certbot renew --quiet --post-hook "systemctl reload nginx"
Flujo de renovación:
- Timer/cron ejecuta
certbot renew - Certbot verifica certificados instalados
- Identifica certificados con menos de 30 días de validez
- Inicia proceso de renovación (repite validación HTTP-01)
- Sustituye certificado antiguo por el nuevo
- Ejecuta post-hook para recargar servidor web
Riesgos y Consideraciones de Seguridad
1. Rate Limits
Como Let's Encrypt es gratuito, existen límites para evitar abuso:
| Límite | Significado | Ejemplo |
|---|---|---|
| 50 certificados/dominio/semana | Máximo de 50 certificados para subdominios de tu dominio | api.site.com, www.site.com, etc. sumados |
| 5 duplicados/semana | Mismo certificado (exactos dominios) solo puede ser emitido 5x | Evita loops accidentales en scripts |
| 10 cuentas/IP/3h | Creación de nuevas cuentas ACME limitada | Afecta solo primera instalación |
En la práctica: Estos límites raramente afectan uso normal. Problemas surgen en:
- Scripts con bugs que piden certificados en loop
- Ambientes de test/desarrollo sin usar staging
Solución: Usa --test-cert (staging) para pruebas - tiene límites mucho mayores:
# Ambiente de pruebas (no genera certificado válido, pero prueba todo el proceso)
certbot certonly --test-cert --nginx -d test.domain.com
# Producción (certificado real)
certbot certonly --nginx -d prod.domain.com
2. ¿Y si la Renovación Falla?
Si el timer automático falla en renovar, el certificado expira y tu sitio queda sin HTTPS. Esto puede ocurrir por:
| Causa común | Qué pasó |
|---|---|
| Puerto 80 bloqueado | Firewall cambió, Let's Encrypt no puede validar |
| Servidor parado | Nginx/Apache no estaba corriendo en el momento de la renovación |
| Dominio cambió | DNS no apunta más al servidor |
| Disco lleno | No puede guardar nuevo certificado |
Cómo verificar si está todo ok:
# Ver estado de los certificados y cuándo expiran
sudo certbot certificates
# Probar si la renovación va a funcionar (sin renovar de verdad)
sudo certbot renew --dry-run
Monitoreo simple: Agrega una alerta por email si la renovación falla:
# Agregar en crontab (sudo crontab -e)
0 8 * * * certbot renew --dry-run --quiet || echo "ALERTA: Renovación SSL falló!" | mail -s "Certbot Falló" [email protected]
Esto corre todos los días a las 8h y solo envía email si hay problema.
3. Protegiendo tu Dominio con CAA Records
Cualquier persona puede intentar obtener un certificado para tu dominio. Si un atacante consigue acceso temporal a tu servidor o DNS, podría obtener un certificado válido.
Para solucionar esta situación tenemos el CAA (Certificate Authority Authorization) que es un registro DNS que dice "solo ESTA autoridad certificadora puede emitir certificados para mi dominio".
# Agrega estos registros DNS en tu proveedor (Cloudflare, Route53, etc.)
# Solo Let's Encrypt puede emitir certificados para este dominio
domain.com. CAA 0 issue "letsencrypt.org"
# Bloquea emisión de wildcards (opcional)
domain.com. CAA 0 issuewild ";"
# Recibir email si alguien intenta emitir certificado no autorizado
domain.com. CAA 0 iodef "mailto:[email protected]"
Verificar si CAA está configurado:
dig CAA domain.com
4. Protegiendo la Clave Privada
La clave privada (privkey.pem) es el secreto más importante. Quien tenga acceso puede hacerse pasar por tu sitio.
# Verificar permisos (debe ser 600, solo root lee)
ls -la /etc/letsencrypt/live/domain.com/
# Corregir si es necesario
sudo chmod 600 /etc/letsencrypt/live/domain.com/privkey.pem
sudo chown root:root /etc/letsencrypt/live/domain.com/privkey.pem
Nunca hagas:
- Copiar claves a repositorios git
- Enviar claves por email/chat
- Dar permiso de lectura a otros usuarios