Asegurando Nginx con HTTPS: Una Guía Paso a Paso

Aprende a asegurar tu servidor web Nginx con HTTPS en esta guía completa paso a paso. Cubrimos la obtención de certificados SSL/TLS gratuitos de Let's Encrypt usando Certbot, la configuración de Nginx para conexiones cifradas y la implementación de medidas de seguridad esenciales como HSTS. Protege tus datos, genera confianza en los usuarios y mejora el SEO con una configuración HTTPS adecuada.

Asegurando Nginx con HTTPS: Una Guía Paso a Paso

Asegurar Nginx con HTTPS suele ser un trabajo pequeño, pero es uno de esos trabajos donde los pequeños errores son ruidosos. Un archivo de certificado faltante impide que Nginx se recargue. Una regla de firewall olvidada hace que el sitio parezca caído. Una cabecera HSTS apresurada puede bloquear a los usuarios en una configuración HTTPS rota por más tiempo del previsto.

La buena noticia es que el camino normal es simple. Apuntas el DNS al servidor, te aseguras de que Nginx responda en el puerto 80, usas Certbot para solicitar un certificado de Let's Encrypt, pruebas la configuración generada de Nginx, recargas y luego verificas la renovación. Ese es el camino que sigue esta guía.

Usaré example.com y www.example.com a continuación. Reemplázalos con tus nombres reales y no te saltes las comprobaciones antes de recargar Nginx.

Antes de Solicitar un Certificado

Antes de tocar Certbot, confirma las piezas aburridas. La mayoría de los problemas de certificados provienen de DNS, firewalls o un bloque de servidor que no responde por el dominio solicitado.

Verifica el DNS desde algún lugar fuera del servidor:

dig +short example.com
dig +short www.example.com

Ambos nombres deben resolverse a la dirección pública que llega a tu host Nginx o balanceador de carga.

Asegúrate de que los puertos 80 y 443 estén abiertos en cada capa: grupo de seguridad en la nube, firewall del host, firewall de red y cualquier balanceador de carga frente al host.

sudo ss -tulnp | grep nginx
sudo ufw status

En una máquina virtual en la nube, también verifica la consola del proveedor. He visto muchas configuraciones limpias de Nginx fallar porque el firewall de la instancia permitía el 443 pero el grupo de seguridad en la nube aún lo bloqueaba.

Finalmente, confirma que Nginx ya sirve el dominio a través de HTTP simple:

curl -I http://example.com
curl -I http://www.example.com

La respuesta no necesita ser bonita. Puede ser una página de marcador de posición. Solo necesita probar que las solicitudes para ese nombre de host llegan a este servidor Nginx.

Instalar Certbot

Para Debian/Ubuntu:

sudo apt update
sudo apt install certbot python3-certbot-nginx

Para sistemas compatibles con RHEL:

sudo dnf install certbot python3-certbot-nginx

Los sistemas CentOS más antiguos pueden usar yum y pueden necesitar EPEL habilitado primero. Los nombres de los paquetes también varían según la versión de la distribución, así que usa la documentación de paquetes de tu distribución si esos comandos no encuentran el plugin.

Solicitar el Certificado

El plugin de Nginx puede solicitar el certificado y editar el bloque de servidor correspondiente:

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

Certbot pedirá una dirección de correo electrónico, aceptación de los términos y, a veces, si redirigir HTTP a HTTPS. Para un sitio web público normal, elige la redirección. Para una API o servicio interno, verifica primero a los clientes. Algunos clientes antiguos o comprobaciones de salud aún pueden llamar a http:// y esperar una respuesta específica.

Si Certbot dice que no puede encontrar un bloque de servidor coincidente, verifica server_name. Un bloque como este le da a Certbot algo claro con lo que trabajar:

server {
    listen 80;
    server_name example.com www.example.com;

    root /var/www/example.com/public;
    index index.html;

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

Ejecuta una verificación de sintaxis antes de pedirle a Certbot que edite algo:

sudo nginx -t

Si la configuración actual ya está rota, arréglala primero.

Cómo Debería Verse la Configuración de Nginx

Después de una ejecución exitosa, generalmente verás un bloque HTTP que redirige y un bloque HTTPS que sirve el sitio:

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

server {
    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;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    root /var/www/example.com/public;
    index index.html;

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

No copies esto ciegamente sobre una configuración de producción. Conserva tus reglas location existentes, configuraciones de proxy, registros y límites de subida. Las partes importantes son el listen 443 ssl, las rutas de los certificados y el comportamiento de redirección en el puerto 80.

Probar, Recargar y Verificar

Siempre prueba antes de recargar:

sudo nginx -t

Luego recarga:

sudo systemctl reload nginx

Verifica desde la línea de comandos:

curl -I http://example.com
curl -I https://example.com
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates

La solicitud HTTP debería redirigir si elegiste esa opción. La solicitud HTTPS debería devolver el estado esperado. El comando openssl debería mostrar un certificado cuyo asunto o nombres alternativos del asunto cubran el dominio y cuyas fechas sean actuales.

Las pruebas en el navegador aún importan. Abre el sitio en una ventana privada y haz clic en el icono del candado para inspeccionar el certificado. Si tu sitio carga activos desde URLs antiguas http://, la página puede mostrar advertencias de contenido mixto aunque el certificado principal esté bien. Arregla esas URLs de activos en la aplicación, CMS o capa de plantillas.

Renovación

Los certificados de Let's Encrypt tienen una vida corta, por lo que la renovación debe funcionar sin que tú lo recuerdes. Certbot normalmente instala un timer de systemd o un trabajo cron. Verifícalo:

systemctl list-timers | grep certbot
sudo certbot renew --dry-run

La ejecución en seco es la parte útil. Realiza una simulación de renovación y detecta problemas comunes como validación HTTP rota, cambios en DNS, plugins faltantes o una configuración que no puede recargarse.

Si terminas TLS en un balanceador de carga o CDN en lugar de directamente en el host Nginx, la renovación puede necesitar un desafío DNS o una ruta de implementación diferente. No asumas que el desafío HTTP predeterminado funcionará si el tráfico público nunca llega a este servidor.

Configuraciones TLS que Vale la Pena Verificar

Para la mayoría de los sitios públicos modernos, TLS 1.2 y TLS 1.3 son la línea base práctica:

ssl_protocols TLSv1.2 TLSv1.3;

Evita ajustar manualmente las listas de cifrado a menos que sepas por qué. El options-ssl-nginx.conf incluido de Certbot y el Generador de Configuración SSL de Mozilla son mejores puntos de partida que una cadena de cifrado copiada de una publicación de blog antigua. La guía de cifrados cambia con el tiempo, y los requisitos de compatibilidad difieren entre un sitio de marketing público y una API heredada interna.

HSTS es útil, pero merece precaución:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Comienza con un valor corto durante las pruebas:

add_header Strict-Transport-Security "max-age=300" always;

Solo usa includeSubDomains cuando cada subdominio pueda servir HTTPS válido. Si old.example.com, mail.example.com o un subdominio específico de un cliente no está listo, esa opción puede afectar a usuarios reales.

Fallos Comunes

Si Certbot no puede verificar el dominio, verifica primero el DNS, luego el puerto 80, luego el bloque de servidor de Nginx. El desafío HTTP-01 necesita que Let's Encrypt alcance un token bajo /.well-known/acme-challenge/. Las redirecciones están bien cuando se configuran correctamente, pero un proxy, CDN o bloque catch-all pueden enviar accidentalmente el desafío a otro lugar.

Si Nginx falla al recargar después de los cambios de Certbot, ejecuta:

sudo nginx -t
sudo journalctl -u nginx -n 80 --no-pager

La prueba de sintaxis generalmente te dice el archivo y la línea exactos. Las causas comunes son bloques listen 443 ssl duplicados, una ruta de certificado eliminada o un snippet incluido desde una ruta que no existe en este servidor.

Si HTTPS funciona localmente pero no para los usuarios, verifica la ruta pública. Un balanceador de carga puede seguir apuntando a un grupo objetivo antiguo. Un CDN puede haber almacenado en caché una redirección. El DNS IPv6 puede apuntar a un host diferente que IPv4. Prueba ambos:

curl -4 -I https://example.com
curl -6 -I https://example.com

La configuración HTTPS más limpia es aburrida: DNS apunta al lugar correcto, Nginx tiene un bloque de servidor obvio para el dominio, la renovación de Certbot pasa en una ejecución en seco y las cabeceras se agregan solo después de que lo básico funciona.