Instalar Let's Encrypt en Nginx Ubuntu: HTTPS gratis en 10 minutos

Aprende a instalar Let's Encrypt en Nginx Ubuntu 24.04 con Certbot, renovación automática y HTTPS validado A+ en SSL Labs.

Los certificados SSL/TLS dejaron de ser un lujo hace mucho tiempo — Chrome marca cualquier sitio HTTP como “No seguro” desde 2018, los navegadores móviles ni siquiera permiten hacer POST sin TLS, y Google penaliza HTTP en el ranking de búsqueda. Let’s Encrypt resolvió el problema del costo (certificados gratuitos) y de la operación (renovación automática), pero la configuración correcta en Nginx todavía deja fuera a mucha gente por detalles de DNS, orden de los comandos y cipher suites desactualizadas.

Este tutorial muestra cómo instalar y configurar Let’s Encrypt en Nginx ejecutándose en Ubuntu 24.04 LTS, desde cero hasta un grado A+ en SSL Labs. Cubrimos la parte que suele omitirse: validación previa del DNS, redirect HTTP→HTTPS sin loop, renovación probada con --dry-run, y hook de reload para que Nginx tome el cert nuevo sin intervención manual.

Tiempo estimado: 10 a 15 minutos si el DNS ya está propagado. Si acabas de crear el registro A, espera a que la propagación se complete antes de empezar — en caso contrario el desafío HTTP-01 falla y gastas cuota de rate limit innecesariamente.

Prerrequisitos

Lo que necesitas antes de empezar

Servidor Ubuntu 24.04 LTS con acceso sudo, Nginx instalado y en ejecución, un dominio registrado apuntando a la IP pública del servidor (registro A en el DNS), puertos 80 y 443 abiertos en el firewall y propagación de DNS completa. Sin esto, Certbot falla en el desafío HTTP-01.

Sistema Ubuntu 24.04 LTS
Servidor web Nginx 1.24+
Puertos necesarios 80 y 443 (TCP)
Espacio en disco ~50 MB para certbot

Antes de continuar, valida que tu dominio resuelva a la IP correcta. Ejecuta dig +short tudominio.com en tu máquina local — el resultado debe ser la IP pública del servidor. Si viene vacío o una IP distinta, el problema está en el DNS y ningún paso de este tutorial va a funcionar hasta que se arregle ahí.

Instalando Certbot

Certbot es el cliente oficial de Let’s Encrypt y la forma recomendada de emitir y renovar certificados. Ubuntu 24.04 trae una versión en apt, pero la Electronic Frontier Foundation recomienda instalar vía snap para garantizar actualizaciones automáticas — el cliente evoluciona rápido y versiones antiguas pueden romperse con cambios en el protocolo ACME.

01

Actualiza el índice de paquetes e instala snapd si todavía no lo tienes:

sudo apt update
sudo apt install -y snapd

En Ubuntu 24.04 LTS, snapd ya viene preinstalado en la mayoría de las imágenes de servidor, pero en VPS minimalistas puede estar ausente. El comando es idempotente — no causa problemas ejecutarlo de nuevo.

02

Elimina cualquier versión antigua de Certbot que esté instalada vía apt, para evitar conflictos:

sudo apt remove -y certbot python3-certbot-nginx

Si apt responde “Package ‘certbot’ is not installed”, ignóralo — significa que no había versión antigua para eliminar.

03

Instala Certbot vía snap y crea el enlace simbólico para que el comando quede disponible en el PATH:

sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

La flag --classic es necesaria porque Certbot necesita acceder a directorios fuera del confinamiento estándar de snap (específicamente /etc/letsencrypt y /etc/nginx).

04

Confirma la versión instalada:

certbot --version

Debes ver algo como certbot 2.x.x. Las versiones 1.x todavía funcionan pero están obsoletas — si aparece 1.x, repite los pasos anteriores.

Configurando Nginx para el desafío HTTP-01

Let’s Encrypt valida la posesión del dominio mediante un archivo que debe servirse en http://tudominio.com/.well-known/acme-challenge/. El plugin --nginx de Certbot edita tu vhost automáticamente, pero para eso necesita un server block válido escuchando en el puerto 80 con el server_name correcto.

05

Crea un vhost básico en /etc/nginx/sites-available/tudominio.com:

server {
    listen 80;
    listen [::]:80;
    server_name tudominio.com www.tudominio.com;

    root /var/www/tudominio.com;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Reemplaza tudominio.com por tu dominio real en todas las apariciones. Si estás hospedando una aplicación dinámica (Node, PHP-FPM, Python), el location / cambia — pero mantén el server_name exacto.

06

Activa el vhost creando el symlink en sites-enabled y prueba la sintaxis:

sudo ln -s /etc/nginx/sites-available/tudominio.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

nginx -t reporta errores de configuración sin aplicarlos — ejecútalo siempre antes del reload. Si aparece un error de symlink ya existente (en caso de repetir el tutorial), elimínalo con sudo rm /etc/nginx/sites-enabled/tudominio.com antes de recrearlo.

Cuidado con el default_server

Si tienes un vhost default en el puerto 80 (generalmente /etc/nginx/sites-enabled/default), asegúrate de que NO capture peticiones a tu dominio. Nginx elige vhost por server_name, pero si ninguno coincide cae en el default_server. Elimina el default o ajusta el server_name _ a un valor que nunca coincida.

Emitiendo el certificado

Con Nginx sirviendo el dominio en el puerto 80, Certbot puede completar el desafío. El comando siguiente emite el certificado, instala las directivas SSL en el vhost y configura el redirect HTTP→HTTPS automáticamente.

07

Ejecuta Certbot con el plugin nginx:

sudo certbot --nginx -d tudominio.com -d www.tudominio.com

Certbot te preguntará:

  • Email para notificaciones de expiración (usa un email que leas — es el canal de alerta si la renovación falla)
  • Aceptación de los términos de Let’s Encrypt (responde Y)
  • Si quieres compartir el email con la EFF (opcional, responde N si prefieres privacidad)
  • Si quieres redirigir tráfico HTTP a HTTPS (responde 2 para activar — recomendado)

Tras unos segundos, el cert se emite y Nginx ya está sirviendo HTTPS.

08

Verifica que el certificado fue instalado abriendo https://tudominio.com en el navegador. Debes ver el candado verde sin warnings. Si el navegador se queja de cert inválido, comprueba:

  • El server_name del vhost coincide exactamente con el dominio accedido
  • Incluiste www. en Certbot si accedes vía www
  • El DNS ya propagó (verifica con dig)
Modo staging para pruebas

Antes de emitir el cert real, ejecuta con --staging para validar la configuración sin quemar rate limit. El cert staging no es confiable para el navegador (dará warning) pero confirma que el desafío funciona. Después elimina el --staging y ejecuta de nuevo para emitir el cert de producción.

Configurando la renovación automática

Los certificados Let’s Encrypt expiran en 90 días. El snap de Certbot ya crea un timer systemd que intenta renovar dos veces al día — pero es prudente validar que está funcionando y añadir el hook de reload de Nginx.

09

Confirma que el timer systemd de Certbot está activo:

sudo systemctl list-timers | grep certbot

Debes ver snap.certbot.renew.timer listado con la próxima ejecución programada. Si no aparece, actívalo manualmente:

sudo systemctl enable --now snap.certbot.renew.timer
10

Configura el hook de deploy para recargar Nginx tras cada renovación exitosa:

sudo mkdir -p /etc/letsencrypt/renewal-hooks/deploy
echo '#!/bin/bash
systemctl reload nginx' | sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

Sin este hook, el cert renovado queda en disco pero Nginx sigue sirviendo el antiguo hasta el próximo restart manual. Con el hook, la operación es totalmente sin intervención.

11

Prueba la renovación en modo dry-run para validar que todo funciona sin tocar el cert real:

sudo certbot renew --dry-run

Output esperado: Congratulations, all simulated renewals succeeded. Si da error, lee el mensaje con atención — generalmente es firewall cerrado en el puerto 80 o DNS roto.

Verificación final

Con todo configurado, valida el nivel de seguridad de tu HTTPS en SSL Labs. Accede a https://www.ssllabs.com/ssltest/analyze.html?d=tudominio.com y espera 1-2 minutos a que el análisis termine. El grado esperado es A. Para llegar a A+, edita tu vhost y añade en la sección server (ya existente, creada por Certbot) los headers de seguridad:

add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;

Recarga Nginx con sudo systemctl reload nginx y vuelve a hacer el test en SSL Labs.

HSTS con preload es una decisión permanente

La directiva preload en HSTS añade tu dominio a la lista de Chrome embebida en el binario del navegador. Revertir lleva meses. Solo actívalo si tienes la certeza de que TODO subdominio de tu sitio va a servir HTTPS para siempre. En entorno de pruebas, omite preload y ajusta max-age a un valor menor (ej: 300 segundos).

Resolución de problemas

Error “Connection refused” en el desafío HTTP-01

Significa que Certbot no pudo acceder al puerto 80 de tu servidor. Confirma con sudo ufw status si el firewall está liberando el puerto, y comprueba si algún otro servicio (Apache, otro Nginx) está en conflicto. Mata el conflicto con sudo ss -tlnp | grep :80.

Error “DNS problem: NXDOMAIN looking up A”

El DNS todavía no propagó o el registro A no existe. Confirma localmente con dig +short tudominio.com @8.8.8.8 (usa el DNS público de Google). Si viene vacío, ve al panel de tu registrador y crea el registro A apuntando a la IP del servidor.

El cert se renovó pero el navegador todavía muestra el antiguo

Confirma que el hook de reload es ejecutable y está funcionando. Fuerza la renovación ignorando el cooldown con sudo certbot renew --force-renewal y observa el output. Si el hook no se ejecuta, el problema está en /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh — verifica los permisos con ls -la.

Próximos pasos

Con HTTPS en ejecución, considera los siguientes hardenings: configurar OCSP Stapling para reducir la latencia de la verificación de revocación, añadir Content Security Policy para mitigar XSS, y activar HTTP/2 o HTTP/3 en Nginx (ya viene habilitado por defecto en la rama 1.25+). Para producción seria, monitorea la expiración del certificado con Uptime Robot o similar — alerta independiente del cron de renovación.

Si estás poniendo una aplicación crítica en producción, una VPS Hostini entrega snapshots automáticos, IPv6 nativo y firewall de red ya configurado para reducir el camino entre apt install nginx y el sitio en el aire con grado A+.

Preguntas frecuentes

¿Puedo emitir un certificado Let's Encrypt sin tener un dominio?

No. Let's Encrypt valida la posesión mediante el desafío HTTP-01 o DNS-01, y ambos exigen un nombre registrado apuntando al servidor. Para desarrollo local usa mkcert o una CA interna; para IPs públicas sin dominio no existe autoridad pública gratuita que emita certificado.

¿Cuál es la diferencia entre Certbot --nginx y --webroot?

El plugin --nginx edita tu nginx.conf automáticamente para insertar las directivas ssl_certificate y ejecutar el desafío. El --webroot solo coloca el archivo de validación en un directorio existente y te deja configurar el vhost manualmente. Usa --nginx en hosts simples y --webroot cuando tu Nginx ya está en producción con configuración personalizada que no quieres que Certbot toque.

¿Cuántos certificados puedo emitir por dominio?

Let's Encrypt aplica un rate limit de 50 certificados por dominio registrado por semana y 5 certificados duplicados por semana. Si estás probando, usa el entorno staging (--staging) que tiene límites mucho mayores y emite certs no confiables para el navegador — perfecto para validar la configuración sin quemar cuota.

¿Por qué mi certificado se renovó pero Nginx todavía muestra el antiguo?

Certbot actualiza los archivos en /etc/letsencrypt/live/ pero Nginx mantiene el cert antiguo en memoria hasta recibir la señal de reload. El hook deploy --deploy-hook 'systemctl reload nginx' resuelve esto. Sin él, solo verás el nuevo cert tras un reload manual o restart del servicio.

¿Es seguro abrir el puerto 80 solo para Certbot y cerrarlo después?

No recomendado. La renovación automática cada 60 días necesita el puerto 80 para completar el desafío HTTP-01. Deja el 80 abierto pero configura un redirect 301 permanente al 443 — esto atiende a Certbot y fuerza todo el tráfico a HTTPS sin exponer contenido en texto claro.

¿Puedo usar Let's Encrypt en un entorno de producción crítica?

Sí. Let's Encrypt emite más de 350 millones de certificados activos para sitios como Reddit, Shopify y parte de la CDN de Cloudflare. El detalle es operacional: necesitas asegurar que la renovación automática funciona (probar con --dry-run) y monitorear la expiración con alertas, porque un certificado expirado rompe el sitio silenciosamente desde el punto de vista del visitante.

Temas:
Próximos pasos Cloud Ryzen con NVMe y protección DDoS siempre activa.Pon en producción en un VPS Hostini →
¿Te resultó útil este tutorial?
Hablar por WhatsApp