Cambiar tema

Nginx SSL/TLS en la práctica: del certificado HTTPS al endurecimiento A+

Easton editorial illustration: container packing dock

Sonó la alarma de monitorización. Miré el móvil: el certificado del sitio había caducado — un certificado gratuito de 90 días olvidado por completo. La advertencia roja de «No seguro» en el navegador colgaba en la portada del blog como una bandera burlona.

Tras ese incidente, dediqué una semana a repasar la configuración SSL/TLS de Nginx de arriba abajo. De F en SSL Labs a A+, de renovación manual a totalmente automática, y de cuello de botella de rendimiento a handshake por debajo de 100 ms.

HTTPS no es solo el candado en la barra de direcciones. Google deja claro que HTTPS es un factor de posicionamiento; una configuración correcta puede aumentar el tráfico orgánico entre un 15 y un 20 %. Más importante aún: impide la escucha en mitad de camino. Sin HTTPS, es como gritar la contraseña del banco en público.

Este artículo te guía para configurar HTTPS en Nginx desde cero: solicitud de certificado Let’s Encrypt, endurecimiento TLS 1.3, plantilla para A+ en SSL Labs y renovación automática imprescindible en producción. Toda la configuración se puede copiar y usar directamente.


Capítulo 1: Conceptos básicos de HTTPS y elección del tipo de certificado

1.1 Por qué todo sitio necesita HTTPS

HTTP transmite en texto plano: cada página que visitas y cada formulario que envías viajan desnudos por la red. El WiFi del café, la salida de red de la oficina, el equipo del operador en tu barrio — cualquier nodo intermedio puede ver qué enviaste.

HTTPS añade una capa TLS entre HTTP y TCP. Los datos se cifran al salir y se descifran al llegar; quien intercepte en el camino solo ve ruido.

TLS no solo cifra. También autentica — confirma que accedes al example.com real y no a un sitio de phishing tras un secuestro DNS. Por eso el navegador muestra advertencias rojas con certificados caducados o dominios que no coinciden: te avisa de que «este sitio puede no ser quien dice ser».

1.2 Los tres tipos de certificado SSL: DV, OV y EV

Los certificados se clasifican según el nivel de verificación:

TipoVerificaciónPrecioCaso de uso
DV (Domain Validation)Propiedad del dominioGratis - bajoBlog personal, entorno de pruebas, proyectos pequeños
OV (Organization Validation)Dominio + identidad de la organizaciónMedioWeb corporativa, producto SaaS
EV (Extended Validation)Verificación de identidad estrictaAltoFinanzas, pagos, organismos públicos

Para la mayoría de proyectos personales y equipos pequeños, un certificado DV basta. El DV gratuito de Let’s Encrypt dura 90 días y los navegadores lo confían igual que uno de pago. La única «desventaja» es renovar cada 90 días — con renovación automática, deja de serlo.

OV y EV destacan sobre todo en lo que muestran en la barra de direcciones. EV mostraba el nombre de la empresa (por ejemplo, «Industrial and Commercial Bank of China»), pero los navegadores ya no lo enfatizan tanto; Chrome ni siquiera muestra el nombre por defecto. Sumado a precios de cientos o miles, la relación calidad-precio es baja.

1.3 Let’s Encrypt: la mejor opción gratuita

Let’s Encrypt es una CA sin ánimo de lucro operada por ISRG (Internet Security Research Group). Ventajas principales:

  • Totalmente gratuito: certificados DV gratis para siempre
  • Automatización: emisión y renovación vía protocolo ACME
  • Amplia confianza: todos los navegadores y sistemas operativos principales lo aceptan
  • Validez de 90 días: certificados de corta duración más seguros e impulsan la automatización

También tiene límites: solo DV, no OV/EV; los wildcard exigen verificación DNS (un poco más laboriosa). Para el 99 % de proyectos personales y sitios medianos, no son problema.

A continuación usamos Certbot — cliente oficial de Let’s Encrypt — para solicitar el certificado.


Capítulo 2: Solicitud de certificado Let’s Encrypt en la práctica

2.1 Instalar Certbot

La instalación depende del sistema operativo. En Ubuntu es sencilla:

# Ubuntu 20.04+ / Debian 10+
sudo apt update
sudo apt install certbot python3-certbot-nginx

En CentOS/RHEL hay que habilitar antes el repositorio EPEL:

# CentOS 8 / RHEL 8
sudo dnf install epel-release
sudo dnf install certbot python3-certbot-nginx

Tras instalar, comprueba la versión con certbot --version. Si todo cuadra, el siguiente paso es solicitar el certificado.

2.2 Solicitar el certificado

Certbot admite varios métodos de verificación; los más usados son standalone y webroot. Si Nginx ya está en marcha, conviene webroot:

# Modo webroot: cuando el sitio ya está activo
sudo certbot certonly --webroot -w /var/www/example.com -d example.com -d www.example.com

-w indica la raíz del sitio; -d el dominio. Puedes incluir varios dominios en una sola solicitud.

Si Nginx aún no arranca o pruebas en un servidor temporal, usa standalone:

# Modo standalone: requiere ocupar temporalmente el puerto 80
sudo certbot certonly --standalone -d example.com -d www.example.com

Certbot levanta un servidor HTTP temporal, verifica y lo cierra. Necesitas el puerto 80 libre; si Nginx ya corre, deténlo antes.

También existe el plugin de Nginx, que modifica la configuración automáticamente:

# Modo automático: Certbot ajusta la configuración de Nginx
sudo certbot --nginx -d example.com -d www.example.com

Solicita el certificado, configura HTTPS y la redirección. Útil para empezar rápido; en producción suele preferirse configuración manual para controlar mejor los parámetros SSL.

2.3 Estructura de archivos del certificado

Tras una solicitud correcta, los archivos quedan en /etc/letsencrypt/live/example.com/:

/etc/letsencrypt/live/example.com/
├── cert.pem        # Certificado del dominio
├── chain.pem       # Cadena de certificados intermedios
├── fullchain.pem   # Cadena completa (cert + chain)
└── privkey.pem     # Clave privada

Nginx necesita dos archivos: fullchain.pem (ssl_certificate) y privkey.pem (ssl_certificate_key). privkey.pem es sensible; permisos 600 y nunca filtrarlo.


Capítulo 3: Configuración básica SSL en Nginx

3.1 La configuración HTTPS mínima

Con el certificado en mano, toca configurar HTTPS en Nginx. Lo más simple:

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;

    # Otras directivas...
    root /var/www/example.com;
    index index.html;
}

HTTPS funciona, pero apenas alcanzaría una D. No se fijan versiones TLS; por defecto pueden quedar TLS 1.0 y 1.1, ya considerados inseguros.

3.2 Redirigir HTTP a HTTPS

Configurar HTTPS no basta: algunos usuarios entran por HTTP. Hay que redirigir todo a HTTPS:

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

    # Redirección permanente a HTTPS
    return 301 https://$server_name$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;

    # Otras directivas...
}

return 301 es redirección permanente; el navegador la cachea. La próxima vez que escriban http://, irán directo a https:// sin una petición extra.

3.3 Un error de configuración frecuente

Muchos escriben listen 443 ssl http2;. Desde Nginx 1.25.1, HTTP/2 va en la directiva http2:

# Sintaxis nueva en Nginx 1.25.1+
server {
    listen 443 ssl;
    http2 on;  # Directiva http2 independiente
    server_name example.com;

    # ...
}

En versiones recientes conviene la sintaxis nueva para evitar avisos. Comprueba con nginx -v.


Capítulo 4: Endurecimiento con TLS 1.3

4.1 Elección de versión TLS

Hay cuatro versiones: 1.0, 1.1, 1.2 y 1.3. La 1.0 y la 1.1 están obsoletas; los navegadores principales dejaron de soportarlas en 2020.

VersiónSeguridadRendimientoCompatibilidadRecomendación
TLS 1.0InseguraLentaAmpliaDeshabilitar
TLS 1.1InseguraLentaAmpliaDeshabilitar
TLS 1.2SeguraMediaCasi universalMantener
TLS 1.3MáximaMás rápidaNavegadores modernosObligatorio

La ventaja clave de TLS 1.3 es el rendimiento: handshake de 2-RTT a 1-RTT, la mitad de latencia teórica. En pruebas reales suele quedar por debajo de 100 ms.

En Nginx se fija con ssl_protocols:

ssl_protocols TLSv1.2 TLSv1.3;

No conviene solo TLS 1.3. En 2026 casi todos los navegadores lo soportan, pero algunos clientes HTTP antiguos (herramientas API, dispositivos embebidos) pueden no hacerlo. Mantener TLS 1.2 como respaldo es más prudente.

4.2 Configuración de Cipher Suite

El Cipher Suite define algoritmos de cifrado, intercambio de claves y MAC. Una mala elección deja HTTPS casi inútil.

Lista recomendada para TLS 1.3 en 2026:

ssl_protocols TLSv1.2 TLSv1.3;

# Ciphers TLS 1.3 (Nginx usa la lista por defecto de OpenSSL)
# Esta línea puede omitirse
ssl_ciphers TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;

# Ciphers TLS 1.2 (compatibilidad hacia atrás)
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;

# Priorizar ciphers del servidor
ssl_prefer_server_ciphers on;

Puntos clave:

  • ECDHE: intercambio elíptico, más seguro y rápido que RSA
  • AES-GCM: cifrado autenticado, más seguro que CBC
  • CHACHA20-POLY1305: mejor en móviles sin aceleración AES por hardware

Si dudas, genera configuración con Mozilla SSL Configuration Generator: https://ssl-config.mozilla.org/

4.3 HSTS: forzar acceso HTTPS

HSTS (HTTP Strict Transport Security) indica al navegador: «este sitio solo acepta HTTPS». Aunque el usuario escriba http://, el navegador redirige localmente a https:// sin una petición de red.

# Cabecera HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

Parámetros:

  • max-age=31536000: validez de 1 año (segundos)
  • includeSubDomains: incluye todos los subdominios
  • preload: entrada en HSTS Preload List (requiere envío en hstspreload.org)

Atención: HSTS se cachea mucho tiempo. Si aún pruebas HTTP, no uses preload de entrada o acorta max-age.


Capítulo 5: Optimización del rendimiento SSL

5.1 SSL Session Cache

Cada handshake TLS implica intercambio de claves y verificación del certificado. Session Cache permite reutilizar sesiones durante un tiempo y evitar el handshake completo.

# Configuración Session Cache
ssl_session_cache shared:SSL:10m;  # 10 MB, ~40 000 sesiones
ssl_session_timeout 1d;            # Validez de sesión 1 día
ssl_session_tickets off;           # Desactivar Session Ticket (más seguro)

shared:SSL:10m es una zona compartida entre workers. ~4000 sesiones por MB; 10 MB bastan para sitios medianos.

ssl_session_tickets off por seguridad: Session Ticket cifra tickets con una clave del servidor; si se filtra, podrían descifrarse sesiones antiguas. Desactivarlo aumenta carga pero mejora la seguridad en entornos exigentes.

5.2 OCSP Stapling

Al validar un certificado, el navegador comprueba si fue revocado. Lo clásico es una consulta OCSP al CA, con petición extra y exposición de qué sitios visitas.

OCSP Stapling hace que el servidor consulte OCSP, cachee el resultado y lo envíe al cliente. Más privacidad y menos latencia.

# Configuración OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

resolver indica servidores DNS para resolver el host OCSP. 8.8.8.8 y 8.8.4.4 de Google son habituales.

Tras configurar, prueba con OpenSSL:

openssl s_client -connect example.com:443 -status < /dev/null 2>&1 | grep -A 17 "OCSP response"

Si aparece «OCSP Response Status: successful», OCSP Stapling funciona.

5.3 Ajuste de ssl_buffer_size

ssl_buffer_size controla el tamaño del registro TLS. Por defecto 16 KB; para respuestas pequeñas (API, blog) es excesivo y empeora el TTFB.

ssl_buffer_size 4k;  # Adecuado para respuestas pequeñas

Para descargas de archivos grandes, mantén 16 KB o sube a 32 KB.


Capítulo 6: Renovación automática del certificado

6.1 Comando de renovación de Certbot

Los certificados Let’s Encrypt duran 90 días; hay que renovarlos. Certbot ofrece renew:

# Probar renovación (sin renovar de verdad)
sudo certbot renew --dry-run

# Renovación real
sudo certbot renew

renew revisa la caducidad y solo renueva si quedan menos de 30 días. Puedes ejecutarlo a diario sin gastar cuota de rate limit innecesariamente.

6.2 Tarea programada con crontab

Lo más fiable es crontab:

# Editar crontab de root
sudo crontab -e

Añade estas líneas:

# Comprobación a las 3:00 y a las 15:00 cada día
0 3 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"
0 15 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"

--quiet reduce salida. --post-hook "systemctl reload nginx" recarga Nginx tras renovar para aplicar el certificado nuevo.

¿Por qué dos veces al día? A veces falla la renovación (DNS temporal, etc.); más comprobaciones aumentan las probabilidades de éxito.

6.3 Prueba de renovación y resolución de problemas

Los fallos quedan en /var/log/letsencrypt/letsencrypt.log. Problemas habituales:

  1. Puerto ocupado: standalone necesita el 80 libre
  2. DNS incorrecto: comprueba que el dominio apunta al servidor
  3. Rate limit: máximo 5 solicitudes del mismo certificado por semana; usa --dry-run en pruebas
  4. Permisos: Certbot debe leer/escribir en /etc/letsencrypt/

Flujo de prueba completo:

# 1. dry-run
sudo certbot renew --dry-run

# 2. Si ok, renovación real
sudo certbot renew

# 3. Comprobar validez
sudo certbot certificates

# 4. Recargar Nginx
sudo systemctl reload nginx

Plantilla de configuración completa

Plantilla lista para producción con puntuación A+ en SSL Labs:

# Redirección HTTP
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$server_name$request_uri;
}

# Servicio HTTPS
server {
    listen 443 ssl;
    http2 on;
    server_name example.com www.example.com;

    # Certificados
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # Versiones TLS
    ssl_protocols TLSv1.2 TLSv1.3;

    # Cipher Suite
    ssl_ciphers TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
    ssl_prefer_server_ciphers on;

    # Cabeceras de seguridad
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    add_header X-Frame-Options SAMEORIGIN always;
    add_header X-Content-Type-Options nosniff always;
    add_header X-XSS-Protection "1; mode=block" always;

    # Session Cache
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

    # Rendimiento
    ssl_buffer_size 4k;

    # Sitio
    root /var/www/example.com;
    index index.html index.htm;

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

Tras configurar, prueba en SSL Labs: https://www.ssllabs.com/ssltest/


Resumen

Configurar HTTPS es fácil al principio — unas líneas y funciona. Llegar a A+ en SSL Labs equilibrando rendimiento y compatibilidad exige entender TLS, Cipher Suite, Session Cache y OCSP Stapling.

Puntos clave:

  1. Certificado: Let’s Encrypt gratuito; Certbot automatiza
  2. Versiones TLS: TLS 1.2 + 1.3; deshabilitar 1.0 y 1.1
  3. Cipher Suite: priorizar ECDHE y AES-GCM; incluir CHACHA20
  4. HSTS: forzar HTTPS y reducir redirecciones
  5. Rendimiento: Session Cache y OCSP Stapling imprescindibles
  6. Renovación: crontab doble y recarga automática de Nginx

Copia la plantilla, ajusta dominio y rutas de certificado y listo. Después prueba en SSL Labs y cuéntame el resultado en comentarios — apuesto a A+.

Configurar Nginx SSL/TLS para obtener A+ en seguridad

Flujo completo desde la solicitud del certificado hasta el endurecimiento de seguridad

⏱️ Estimated time: 30 min

  1. 1

    Step 1: Instalar Certbot y solicitar el certificado

    Usa Certbot para solicitar un certificado SSL gratuito de Let's Encrypt:

    • Ubuntu/Debian: sudo apt install certbot python3-certbot-nginx
    • CentOS/RHEL: sudo dnf install certbot python3-certbot-nginx
    • Solicitar certificado: sudo certbot certonly --webroot -w /var/www/example.com -d example.com
    • Directorio de certificados: /etc/letsencrypt/live/example.com/
    • Necesitas dos archivos: fullchain.pem y privkey.pem
  2. 2

    Step 2: Configurar HTTPS básico en Nginx

    Añade el certificado SSL y la redirección HTTP en la configuración de Nginx:

    • listen 443 ssl; para escuchar HTTPS
    • http2 on; para habilitar HTTP/2 (Nginx 1.25.1+)
    • ssl_certificate apunta a fullchain.pem
    • ssl_certificate_key apunta a privkey.pem
    • return 301 https://$server_name$request_uri; redirige HTTP a HTTPS
  3. 3

    Step 3: Configurar TLS 1.3 y Cipher Suite

    Habilita versiones TLS seguras y suites de cifrado:

    • ssl_protocols TLSv1.2 TLSv1.3; deshabilita versiones antiguas
    • ssl_ciphers configura ECDHE + AES-GCM + CHACHA20
    • ssl_prefer_server_ciphers on; prioriza la selección del servidor
    • add_header Strict-Transport-Security habilita HSTS
  4. 4

    Step 4: Optimizar el rendimiento SSL

    Configura Session Cache y OCSP Stapling para mejorar el rendimiento:

    • ssl_session_cache shared:SSL:10m; caché de sesiones compartida
    • ssl_session_timeout 1d; validez de sesión de 1 día
    • ssl_stapling on; habilita OCSP Stapling
    • ssl_buffer_size 4k; optimizado para respuestas pequeñas
  5. 5

    Step 5: Configurar la renovación automática del certificado

    Usa crontab para configurar la renovación automática con Certbot:

    • sudo crontab -e para editar la tarea programada
    • 0 3 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"
    • Comprobación dos veces al día (madrugada y tarde)
    • --post-hook recarga Nginx tras renovar el certificado
  6. 6

    Step 6: Probar la seguridad de la configuración SSL

    Verifica que la configuración alcance A+:

    • Visita https://www.ssllabs.com/ssltest/ para probar la configuración SSL
    • Usa openssl s_client -connect example.com:443 -status para probar OCSP
    • Comprueba certbot certificates para confirmar la validez del certificado
    • Asegúrate de que HSTS, OCSP Stapling y Session Cache estén activos

FAQ

¿Cuánto dura un certificado de Let's Encrypt? ¿Hay que renovarlo manualmente?
Los certificados de Let's Encrypt tienen una validez de 90 días. Se recomienda configurar la renovación automática con crontab, comprobando dos veces al día y recargando Nginx tras renovar. Con la renovación automática bien configurada, no hace falta intervención manual.
¿Cómo probar la seguridad de la configuración SSL en Nginx?
Se recomienda la prueba en línea de SSL Labs: https://www.ssllabs.com/ssltest/

• A+ es la puntuación máxima e indica configuración segura y buen rendimiento
• También puedes probar OCSP Stapling en local con openssl s_client
• Comando de prueba: openssl s_client -connect example.com:443 -status
¿HTTPS afecta al rendimiento del sitio? ¿Cómo optimizarlo?
HTTPS añade coste de handshake TLS, pero con optimización el impacto es mínimo:

• TLS 1.3 reduce el handshake de 2-RTT a 1-RTT, la mitad de latencia
• Session Cache permite reutilizar sesiones y evitar el handshake completo
• OCSP Stapling reduce las peticiones de verificación del certificado
• Tras optimizar, el handshake puede mantenerse por debajo de 100 ms
¿Qué hacer si falla la renovación del certificado? ¿Cómo diagnosticarlo?
Causas habituales de fallo en la renovación y soluciones:

• Puerto ocupado: el modo standalone requiere el puerto 80 libre
• Fallo de resolución DNS: comprueba que el dominio apunta a la IP del servidor
• Límite de tasa: Let's Encrypt permite como máximo 5 solicitudes del mismo certificado por semana
• Revisa el log: /var/log/letsencrypt/letsencrypt.log
¿Qué diferencia hay entre TLS 1.2 y TLS 1.3? ¿Por qué habilitar ambos?
TLS 1.3 ofrece ventajas claras frente a TLS 1.2:

• Rendimiento: handshake de 2-RTT a 1-RTT, la mitad de latencia
• Seguridad: elimina algoritmos de cifrado inseguros
• Compatibilidad: habilitar ambos permite soportar clientes antiguos; TLS 1.2 actúa como opción de compatibilidad
¿Qué hay que tener en cuenta al configurar HSTS?
Precauciones al configurar HSTS:

• max-age se recomienda en 31536000 (1 año)
• includeSubDomains afecta a todos los subdominios
• preload requiere envío en hstspreload.org para surtir efecto
• En la primera configuración conviene un max-age corto para probar antes de alargarlo
¿Cómo elegir el tipo de certificado SSL? ¿Qué diferencia hay entre DV, OV y EV?
Recomendaciones para elegir tipo de certificado:

• DV: gratuito, valida la propiedad del dominio, ideal para blogs personales y proyectos pequeños
• OV: valida la identidad de la organización, muestra datos de la empresa, adecuado para sitios corporativos
• EV: validación estricta, Chrome ya no muestra el nombre de la empresa, poca relación calidad-precio
• En el 99% de los casos se recomienda el certificado DV gratuito de Let's Encrypt

11 min de lectura · Publicado el: 20 abr 2026 · Actualizado el: 21 ago 2026

Comentarios

Inicia sesión con GitHub para dejar un comentario

Easton BlogEaston Blog