Tema
SSL con Let's Encrypt
Hoy ningún sitio profesional puede estar sin HTTPS: los navegadores marcan como "No seguro" los sitios HTTP, Google los posiciona peor y muchas APIs del navegador (geolocalización, cámara, service workers) solo funcionan con HTTPS. La buena noticia: con Let's Encrypt y Certbot los certificados son gratis y se renuevan solos.
Concepto
- TLS (antes SSL) cifra la comunicación entre navegador y servidor. HTTPS = HTTP + TLS.
- Un certificado demuestra que el servidor realmente es dueño del dominio. Lo emite una autoridad certificadora (CA).
- Let's Encrypt es una CA gratuita y automatizada. Sus certificados duran 90 días (y la industria se mueve hacia periodos aún más cortos), por eso la renovación automática es obligatoria.
- Certbot es el programa que pide, instala y renueva los certificados.
Cómo comprueba Let's Encrypt que el dominio es tuyo
| Método | Cómo funciona | Cuándo usarlo |
|---|---|---|
| HTTP-01 | Certbot coloca un archivo en http://tudominio.com/.well-known/acme-challenge/... y Let's Encrypt lo descarga. | El caso normal. Requiere puerto 80 abierto y DNS apuntando al servidor. |
| DNS-01 | Creas un registro TXT _acme-challenge en el DNS. | Certificados wildcard (*.tudominio.com) o servidores sin puerto 80. |
Requisitos previos
- [ ] El dominio (y
www) apunta a la IP del servidor:dig +short tudominio.com. - [ ] Puertos 80 y 443 abiertos:
sudo ufw status. - [ ] Nginx o Apache sirviendo el sitio por HTTP con el
server_name/ServerNamecorrecto.
Paso 1: instalar Certbot
El método recomendado oficialmente es con snap:
bash
sudo snap install core
sudo snap refresh core
sudo snap install --classic certbot
sudo ln -sf /snap/bin/certbot /usr/bin/certbot
certbot --versionAlternativa con apt
También funciona sudo apt install certbot python3-certbot-nginx (o python3-certbot-apache). La versión de apt puede ser un poco más antigua, pero es perfectamente válida en Ubuntu 24.04.
Paso 2: obtener el certificado
bash
sudo certbot --nginx -d tudominio.com -d www.tudominio.combash
sudo certbot --apache -d tudominio.com -d www.tudominio.comCertbot te pedirá un correo (para avisos de expiración), aceptar términos y listo: edita tu configuración automáticamente para usar el certificado y redirigir HTTP a HTTPS.
Los archivos quedan en:
txt
/etc/letsencrypt/live/tudominio.com/
├── fullchain.pem ← certificado + cadena (el que usa el servidor)
├── privkey.pem ← llave privada (¡secreta!)
├── cert.pem
└── chain.pemVarios dominios a la vez
bash
sudo certbot --nginx \
-d clientea.com -d www.clientea.com \
-d api.clientea.comSolo obtener el certificado (sin tocar la configuración)
bash
sudo certbot certonly --nginx -d tudominio.com
# o con el modo webroot, indicando la carpeta pública
sudo certbot certonly --webroot -w /var/www/tudominio.com/public -d tudominio.comAsí queda la configuración de Nginx
Esto es lo que Certbot genera (lo puedes escribir tú a mano también):
nginx
# Redirección HTTP → HTTPS
server {
listen 80;
listen [::]:80;
server_name tudominio.com www.tudominio.com;
return 301 https://tudominio.com$request_uri;
}
# Sitio con HTTPS
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name tudominio.com www.tudominio.com;
ssl_certificate /etc/letsencrypt/live/tudominio.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/tudominio.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# HSTS: el navegador solo usará HTTPS durante 1 año
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
root /var/www/tudominio.com/public;
index index.html;
location / {
try_files $uri $uri.html $uri/ =404;
}
}http2 en versiones nuevas de Nginx
Ubuntu 24.04 trae Nginx 1.24, que usa listen 443 ssl http2;. Desde Nginx 1.25.1 la forma recomendada es listen 443 ssl; más una línea http2 on; (la forma antigua sigue funcionando, solo muestra un aviso en nginx -t).
Y en Apache
apache
<VirtualHost *:80>
ServerName tudominio.com
ServerAlias www.tudominio.com
Redirect permanent / https://tudominio.com/
</VirtualHost>
<VirtualHost *:443>
ServerName tudominio.com
ServerAlias www.tudominio.com
DocumentRoot /var/www/tudominio.com/public
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/tudominio.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/tudominio.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
<Directory /var/www/tudominio.com/public>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>Requiere sudo a2enmod ssl headers.
Paso 3: renovación automática
Certbot instala un temporizador que intenta renovar dos veces al día (solo renueva lo que vence en menos de 30 días).
bash
# Ver el temporizador (instalación con snap)
systemctl list-timers | grep certbot
# Simular una renovación: si no hay errores, la renovación real funcionará
sudo certbot renew --dry-run
# Ver certificados y fechas de expiración
sudo certbot certificatesSi necesitas recargar el servidor tras cada renovación (por ejemplo, para otros servicios que usan el certificado), agrega un hook:
bash
sudo tee /etc/letsencrypt/renewal-hooks/deploy/recargar-nginx.sh > /dev/null <<'EOF'
#!/bin/sh
systemctl reload nginx
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/recargar-nginx.shCertificado wildcard (DNS-01)
Para *.tudominio.com (útil en plataformas multi-cliente: cliente1.tuapp.com, cliente2.tuapp.com):
bash
sudo certbot certonly --manual --preferred-challenges dns \
-d "tudominio.com" -d "*.tudominio.com"Certbot te mostrará un valor para crear un registro TXT en _acme-challenge.tudominio.com. Créalo, verifica con dig +short TXT _acme-challenge.tudominio.com y continúa.
El modo manual no se renueva solo
Con --manual tendrás que repetir el proceso cada 90 días. Para automatizar usa un plugin DNS de tu proveedor, por ejemplo Cloudflare:
bash
sudo snap set certbot trust-plugin-with-root=ok
sudo snap install certbot-dns-cloudflare
# Token de API de Cloudflare con permiso Zone:DNS:Edit
sudo mkdir -p /root/.secrets
echo "dns_cloudflare_api_token = TU_TOKEN" | sudo tee /root/.secrets/cloudflare.ini
sudo chmod 600 /root/.secrets/cloudflare.ini
sudo certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
-d "tudominio.com" -d "*.tudominio.com"Comprobar tu HTTPS
- SSL Labs Server Test: calificación completa (apunta a A o A+).
- Security Headers: revisa cabeceras como HSTS.
- Desde terminal:
bash
curl -I https://tudominio.com
# Ver fechas del certificado
echo | openssl s_client -connect tudominio.com:443 -servername tudominio.com 2>/dev/null | openssl x509 -noout -datesErrores comunes
| Error | Causa | Solución |
|---|---|---|
DNS problem: NXDOMAIN | El dominio no existe o no tiene registro A. | Revisa el DNS con dig. |
Timeout during connect | Puerto 80 cerrado. | sudo ufw allow 80/tcp; revisa el firewall del proveedor. |
unauthorized ... 404 | El dominio apunta a otro servidor o el server_name no coincide. | Verifica la IP y la configuración. |
too many certificates already issued | Límite de emisiones de Let's Encrypt. | Usa --dry-run o --staging para probar; espera. |
| Bucle de redirecciones con Cloudflare | Cloudflare en modo SSL "Flexible". | Cambia a Full (strict). |
Buena práctica con Cloudflare
Si el dominio usa el proxy de Cloudflare (nube naranja), el reto HTTP-01 suele funcionar igual, pero lo más robusto es usar el plugin DNS de Cloudflare o un Origin Certificate de Cloudflare. Ver Rendimiento y CDN.
HSTS con cuidado
Strict-Transport-Security obliga al navegador a usar HTTPS durante el tiempo indicado. Si activas includeSubDomains y algún subdominio no tiene HTTPS, dejará de funcionar. Empieza con max-age=300 y súbelo cuando estés seguro.
Ejercicios
- Escribe el comando para obtener certificado en Nginx para
tienda.com,www.tienda.comyadmin.tienda.com. - ¿Cómo compruebas que la renovación automática funcionará sin esperar 60 días?
- Un cliente tiene 50 subdominios dinámicos. ¿Qué tipo de certificado y reto usarías?
Ver solución
bash
sudo certbot --nginx -d tienda.com -d www.tienda.com -d admin.tienda.comsudo certbot renew --dry-run.- Un certificado wildcard (
*.tienda.com) con reto DNS-01, idealmente con un plugin DNS (Cloudflare, Route 53, DigitalOcean) para que se renueve solo.
Resumen
- HTTPS es obligatorio; Let's Encrypt lo da gratis y Certbot lo automatiza.
- Requisitos: DNS apuntando y puertos 80/443 abiertos.
certbot --nginx/--apacheobtiene, instala y configura la redirección.- Los certificados duran 90 días: verifica la renovación con
renew --dry-run. - Wildcard requiere DNS-01; con Cloudflare usa SSL Full (strict).
- Siguiente: Docker y docker-compose.