https con Let's Encrypt
Módulo 7: Dominio, servidor web y https · Tiempo de lectura: 12 minutos
Objetivo de aprendizaje: Después de esta lección podrá solicitar con certbot un certificado gratuito de Let's Encrypt para nginx, redirigir http a https, comprobar la renovación automática y resolver los errores más habituales de una solicitud.
Conceptos clave: certificado, autoridad de certificación (CA), ACME, Let's Encrypt, validación de dominio, HTTP-01, DNS-01, TLS-ALPN-01, certbot, renovación, certbot renew --dry-run, periodo de validez, ARI, límites de tasa (rate limits), staging, CAA, redirección a https
Por qué https, y qué demuestra un certificado
Sin https, todo lo que circula entre el navegador y el servidor viaja por la red sin cifrar: contraseñas, formularios, cookies. Cualquiera que esté en el camino (una wifi pública, un router comprometido) puede leerlo o modificarlo. Por eso los navegadores marcan los sitios http como "no seguro", y algunas funciones solo funcionan con https. Para una caja fuerte de contraseñas como Vaultwarden (lección 9.4), https es incluso obligatorio.
https utiliza TLS, y para ello su servidor necesita un certificado: una prueba, firmada por una autoridad de certificación (CA) en la que confían los navegadores, de que esta clave pertenece a este nombre. Un certificado normal solo demuestra que el solicitante controla el nombre de dominio (validación de dominio). No dice nada sobre quién es usted ni sobre si es de fiar.
Let's Encrypt es una CA gratuita que solo emite certificados validados por dominio, de forma totalmente automática mediante el protocolo ACME. Un programa en su servidor (el cliente ACME) solicita el certificado, demuestra que controla el nombre, lo instala y lo renueva a tiempo. Esta lección utiliza certbot, el cliente de la EFF. Caddy (lección 7.4) lleva un cliente ACME integrado.
¿Cómo se demuestra que controla el nombre?
Let's Encrypt conoce tres tipos de desafío (challenges):
| Desafío | Cómo | Puerto | Comodín (*.example.com) |
|---|---|---|---|
| HTTP-01 | colocar un archivo en http://<naam>/.well-known/acme-challenge/ | 80 | no |
| DNS-01 | crear un registro TXT _acme-challenge.<naam> | ninguno | sí |
| TLS-ALPN-01 | presentar un certificado especial durante el handshake TLS | 443 | no |
Para un VPS normal con un sitio web, HTTP-01 es lo más sencillo. Para ello:
- el nombre debe apuntar a su servidor con A (y AAAA) (lección 7.1);
- el puerto 80 debe estar abierto para todo el mundo, aunque por lo demás su sitio solo use https. Let's Encrypt valida únicamente a través del puerto 80 y desde varios puntos de internet; no puede poner esas direcciones en su firewall;
- su servidor debe responder lo mismo por IPv4 y por IPv6. Si el nombre tiene un registro AAAA, Let's Encrypt prueba primero por IPv6. Solo si IPv6 no consigue ninguna conexión, recurre a IPv4.
DNS-01 lo necesita para un certificado comodín, o si el servidor no es accesible desde fuera. En ese caso, el cliente ACME debe poder modificar su DNS, normalmente mediante una clave API de su proveedor de DNS. Esa clave puede cambiar todo su DNS: guárdela con el mismo cuidado que una contraseña.
Instalar certbot
Los creadores de certbot recomiendan el snap, porque siempre tiene la versión más reciente. En Debian y Ubuntu también puede instalarlo directamente desde el repositorio de paquetes:
anna@web1:~$ sudo apt install certbot python3-certbot-nginxLa versión de la distribución es más antigua, pero recibe actualizaciones de seguridad a través de apt (lecciones 4.1 y 4.2), y eso encaja con el resto de este curso. Elija una de las dos, no ambas: dos instalaciones se estorban entre sí al renovar.
Solicitar un certificado
Con el sitio de la lección 7.2 ya funcionando en el puerto 80:
anna@web1:~$ sudo certbot --nginx -d example.com -d www.example.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address or hit Enter to skip.
(Enter 'c' to cancel):
...
Requesting a certificate for example.com and www.example.com
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/example.com/privkey.pem
This certificate expires on 2027-02-07.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
Deploying certificate
Successfully deployed certificate for example.com to /etc/nginx/sites-enabled/example.com
Successfully deployed certificate for www.example.com to /etc/nginx/sites-enabled/example.com
Congratulations! You have successfully enabled HTTPS on https://example.com and https://www.example.com(La fecha y los detalles son un ejemplo.) El plug-in --nginx hace tres cosas: prepara temporalmente el desafío, obtiene el certificado y adapta su server block con un bloque listen 443 ssl y una redirección de http a https. Si prefiere hacerlo usted mismo, utilice certbot certonly --nginx y añada las líneas a su configuración.
Algunos puntos a tener en cuenta:
- Solicite de una vez todos los nombres que pertenecen al sitio (
-dpor cada nombre). Cada nombre debe apuntar al servidor; de lo contrario, falla toda la solicitud. - La clave privada (
privkey.pem) se encuentra en/etc/letsencrypt/live/y solo root puede leerla. No la copie a otros lugares y nunca la incluya en una copia de seguridad que otros puedan leer. - La dirección de correo es opcional. Desde junio de 2025, Let's Encrypt ya no envía correos cuando un certificado está a punto de caducar. Por tanto, usted mismo debe vigilar que la renovación funcione (lección 8.3).
Redirigir http a https
Después de certbot, su configuración tendrá más o menos este aspecto (simplificado; certbot añade sus propios comentarios # managed by Certbot y a veces líneas if):
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
root /var/www/example.com;
...
}El primer bloque redirige todo lo que llega por http al mismo nombre y la misma ruta por https, con una redirección permanente (301). El archivo del desafío para la renovación sigue funcionando: Let's Encrypt sigue esa redirección. El segundo bloque es el sitio real. Si además quiere redirigir www al nombre sin prefijo (o al revés), hágalo en un bloque propio, para que los visitantes vean un único nombre fijo.
Renovar: automáticamente, y comprobarlo
Un certificado de Let's Encrypt es válido ahora durante 90 días. Ese plazo se va a acortar: Let's Encrypt ha anunciado que el perfil estándar emitirá certificados de 64 días a partir del 10 de febrero de 2027 y de 45 días a partir del 16 de febrero de 2028. Renovar a mano, por tanto, no es una opción; tiene que hacerse automáticamente.
Al instalarse, certbot crea un temporizador de systemd (o una línea de cron) que comprueba dos veces al día si hay que renovar algún certificado. Compruebe que existe y pruebe la renovación con una solicitud de prueba:
anna@web1:~$ systemctl list-timers 'certbot*'
NEXT LEFT LAST PASSED UNIT ACTIVATES
Mon 2026-11-09 22:41:00 CET 9h left - - certbot.timer certbot.service
anna@web1:~$ sudo certbot renew --dry-run
...
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/example.com/fullchain.pem (success)Después de la renovación, nginx también debe cargar el nuevo certificado. Con el plug-in de nginx, certbot se encarga de ello; si utiliza certonly, cree un deploy hook que recargue nginx, por ejemplo un script ejecutable en /etc/letsencrypt/renewal-hooks/deploy/ con systemctl reload nginx.
Los buenos clientes ACME utilizan ARI (ACME Renewal Information): Let's Encrypt indica entonces cuándo debe renovarse un certificado, por ejemplo antes de lo previsto si hay un problema con una serie de certificados. Por eso, mantenga su cliente actualizado.
Si una solicitud falla
| Mensaje (abreviado) | Causa | Solución |
|---|---|---|
Timeout during connect (likely firewall problem) | puerto 80 cerrado, o el nombre apunta a otra dirección | firewall (lección 5.2), A/AAAA (lección 7.1) |
Invalid response from http://.../.well-known/acme-challenge/...: 404 | responde otro servidor u otro server block, a menudo por IPv6 | listen [::]:80, revisar el registro AAAA |
CAA record for example.com prevents issuance | un registro CAA solo permite otra autoridad emisora | ajustar CAA (lección 7.1) |
too many certificates already issued | un límite de tasa (rate limit) | esperar; probar con staging |
Let's Encrypt aplica límites de tasa (rate limits) para evitar abusos. Los más importantes: como máximo 50 certificados nuevos por dominio registrado cada 7 días, como máximo 5 certificados para exactamente el mismo conjunto de nombres cada 7 días, y como máximo 5 validaciones fallidas por nombre cada hora. Quien está haciendo pruebas y solicita una y otra vez se topa rápidamente con ellos. Por eso, pruebe con el entorno de staging, que tiene límites mucho más amplios pero emite certificados en los que los navegadores no confían:
anna@web1:~$ sudo certbot certonly --nginx --staging -d test.example.comSi allí funciona, solicite el certificado real.
En AlmaLinux y Rocky Linux
Allí certbot procede de EPEL (dnf install certbot python3-certbot-nginx) o se instala como snap. El plug-in y los comandos son los mismos. Tenga en cuenta firewalld (--add-service=http --add-service=https) y SELinux si los certificados están en una ubicación poco habitual.
En la práctica
En un plan de hosting, el panel se encarga del certificado por usted (en WebOké y en otras empresas de hosting con DirectAdmin, cPanel o Plesk). En un VPS lo hace usted mismo, con certbot, Caddy o el cliente ACME que acompañe a su software. Esto es así con cualquier proveedor.
Resumen
- Un certificado de Let's Encrypt demuestra que usted controla el nombre; certbot lo solicita, lo instala y lo renueva mediante ACME.
- HTTP-01 necesita el puerto 80 abierto para todo el mundo y la misma respuesta por IPv4 e IPv6; DNS-01 es para comodines.
certbot --nginx -d ... -d ...se encarga del certificado y de la redirección a https; solicite de una vez todos los nombres de un sitio.- Los certificados son ahora válidos durante 90 días y ese plazo se acortará; compruebe el temporizador y
certbot renew --dry-run, y vigile usted mismo la fecha de caducidad. - Pruebe con
--stagingpara evitar los límites de tasa; preste atención a CAA.
Cuestionario
Ejercicio
Ejercicio Z7.3: https con un certificado válido. Solicite un certificado para su sitio (con certbot o Caddy), redirija http a https y pruebe la renovación con certbot renew --dry-run (con Caddy: compruebe en los registros que se ha obtenido el certificado). Introduzca el nombre de su sitio. El programa establece una conexión TLS al puerto 443 y comprueba si el certificado es válido, está firmado por una autoridad de confianza y cubre su nombre; después solicita http://<naam>/ para ver si redirige a https. Además, indique cuándo caduca su certificado y cómo tiene organizada la renovación.
Para saber más
- Activar, renovar y solucionar problemas del certificado SSL
- Curso gratuito de DNS 5.2: CAA: ¿quién puede emitir certificados?
- Let's Encrypt, Challenge Types: https://letsencrypt.org/docs/challenge-types/
- Let's Encrypt, Rate Limits: https://letsencrypt.org/docs/rate-limits/
- Let's Encrypt, Decreasing Certificate Lifetimes to 45 Days: https://letsencrypt.org/2025/12/02/from-90-to-45
- Instrucciones de certbot (nginx): https://certbot.eff.org/instructions?ws=nginx&os=snap
