Redirigir HTTP a HTTPS en Nginx: Mejores Prácticas
Configura una redirección confiable de HTTP a HTTPS en Nginx usando un bloque dedicado en el puerto 80, evita bucles de redirección, elige el código de redirección correcto y agrega HSTS cuando estés listo.
Redirigir HTTP a HTTPS en Nginx: Mejores Prácticas
Redirigir HTTP a HTTPS en Nginx asegura que los visitantes usen la versión cifrada de tu sitio, incluso si escriben la antigua URL http:// o siguen un enlace desactualizado. Una configuración de redirección limpia mejora la seguridad, evita URLs duplicadas y brinda a los usuarios un punto de entrada consistente.
El mejor enfoque suele ser simple: mantener el puerto 80 abierto solo el tiempo suficiente para redirigir el tráfico y servir el sitio real en el puerto 443 con un certificado TLS válido.
Los detalles importan porque las redirecciones son fáciles de hacer casi correctamente. Una redirección que pierde la ruta rompe los marcadores. Una redirección que preserva el nombre de host incorrecto puede crear URLs canónicas duplicadas. Una redirección detrás de un balanceador de carga puede generar un bucle infinito si Nginx no entiende dónde termina TLS.
Piensa en la redirección como parte de tu API pública. Las personas pegan enlaces en chats, los motores de búsqueda los rastrean, los sistemas de monitoreo los golpean y los correos electrónicos antiguos los mantienen vivos durante años. Si la redirección es estable, nadie nota. Si es descuidada, los usuarios ven advertencias de certificado, rutas rotas o errores de demasiadas redirecciones antes de que tu aplicación reciba una solicitud.
Por Qué Importan las Redirecciones HTTPS
HTTPS protege el tráfico entre el navegador y tu servidor mediante cifrado TLS. Sin él, los datos pueden ser inspeccionados o modificados por las redes entre el usuario y tu sitio. Esto importa para inicios de sesión, formularios, cookies, áreas de administración, APIs e incluso la navegación ordinaria.
Las redirecciones también ayudan con la consistencia. Los motores de búsqueda y los usuarios no deberían ver http://example.com/page y https://example.com/page como dos destinos separados. Una redirección permanente les dice a los clientes que HTTPS es la versión preferida.
El patrón estándar de Nginx es un bloque de servidor dedicado en el puerto 80:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
Luego, tu bloque de servidor HTTPS maneja el sitio real:
server {
listen 443 ssl http2;
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;
root /var/www/example.com;
index index.html;
}
La directiva return 301 es eficiente y clara. Le dice a Nginx que envíe una redirección permanente sin procesar ubicaciones adicionales. $request_uri preserva la ruta y la cadena de consulta, por lo que /docs?page=2 se convierte en https://example.com/docs?page=2.
Para una configuración TLS completa, consulta asegurando Nginx con HTTPS.
Para la mayoría de los sitios, evita poner lógica de aplicación en el bloque del puerto 80. No debería servir archivos estáticos, hacer proxy a la aplicación ni contener un gran conjunto de ubicaciones. Mantenlo aburrido:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://example.com$request_uri;
}
Ese pequeño bloque es más fácil de auditar y menos propenso a desviarse de la configuración HTTPS.
Elegir entre Redirecciones 301 y 302
Usa 301 para una redirección permanente de HTTP a HTTPS en un sitio de producción. Los navegadores y motores de búsqueda entienden que la URL HTTPS debe reemplazar la URL HTTP.
Usa 302 o 307 solo cuando la redirección sea temporal. Por ejemplo, podrías usar una redirección temporal durante las pruebas antes de que los certificados y nombres de host estén finalizados. Una vez que el sitio HTTPS esté listo, cambia a una redirección permanente.
Ten cuidado durante la configuración inicial. Los navegadores pueden almacenar en caché las redirecciones 301 de manera agresiva. Si accidentalmente rediriges al nombre de host incorrecto, el navegador puede seguir usando la redirección incorrecta incluso después de que arregles Nginx. Prueba con curl, ventanas de navegador privadas y nombres de host que no sean de producción cuando sea posible.
Un flujo de implementación práctico se ve así:
- Confirma que el bloque de servidor HTTPS funcione directamente.
- Confirma que el certificado coincida con cada nombre de host.
- Agrega el bloque de servidor de redirección HTTP.
- Prueba varias rutas y cadenas de consulta.
- Cambia las redirecciones temporales a permanentes solo cuando el comportamiento sea correcto.
También debes decidir el nombre de host canónico. Si tanto example.com como www.example.com funcionan, elige uno como el nombre de host público preferido. De lo contrario, los usuarios pueden saltar entre nombres de host o los motores de búsqueda pueden indexar ambos.
Por ejemplo, para redirigir todo el tráfico HTTP al nombre de host HTTPS sin www:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://example.com$request_uri;
}
Eso es diferente de https://$host$request_uri, que preserva el host que el usuario solicitó.
También puedes dividir las redirecciones de nombre de host de las redirecciones de esquema si deseas que el comportamiento sea explícito:
server {
listen 80;
server_name www.example.com;
return 301 https://example.com$request_uri;
}
server {
listen 80;
server_name example.com;
return 301 https://example.com$request_uri;
}
Esto es más verboso, pero hace que el destino final sea obvio. En un sitio pequeño, cualquiera de los estilos está bien. En un sitio más grande con muchos alias, los bloques de servidor explícitos pueden reducir la confusión durante cambios posteriores.
Evitar Bucles de Redirección y Problemas de Certificado
Los bucles de redirección ocurren cuando Nginx, un balanceador de carga o una aplicación siguen enviando una solicitud de vuelta a una URL que desencadena otra redirección. Esto es común cuando TLS termina antes de Nginx, como en un balanceador de carga en la nube o CDN.
En una configuración simple de un solo servidor, Nginx recibe HTTPS directamente, por lo que la redirección es directa. En una cadena de proxy, Nginx puede recibir HTTP simple del balanceador de carga incluso si el usuario se conectó con HTTPS. Si tu aplicación luego intenta forzar HTTPS basándose en el esquema de conexión local, puede causar un bucle.
La solución depende de tu arquitectura. Generalmente, el balanceador de carga debe pasar encabezados como X-Forwarded-Proto, y la aplicación o la configuración de Nginx deben confiar en ellos solo desde direcciones de proxy conocidas.
Por ejemplo, si Nginx está detrás de un balanceador de carga confiable y solo recibe HTTP interno, es posible que no quieras que Nginx redirija cada solicitud HTTP local. En su lugar, el balanceador de carga puede manejar la redirección pública de HTTP a HTTPS, mientras que Nginx sirve tráfico desde la red privada. Si Nginx debe tomar la decisión, necesita información confiable de protocolo reenviado del proxy que tiene delante. No confíes en X-Forwarded-Proto de clientes de internet arbitrarios.
También asegúrate de que los certificados cubran cada nombre de host redirigido. Si un usuario visita http://www.example.com y rediriges a https://www.example.com, el certificado debe ser válido para www.example.com. Si rediriges todo a https://example.com, el certificado para el sitio final debe cubrir example.com.
Prueba con:
curl -I http://example.com/some/path?x=1
Busca:
HTTP/1.1 301 Moved Permanently
Location: https://example.com/some/path?x=1
Luego prueba la URL HTTPS:
curl -I https://example.com/some/path?x=1
La respuesta HTTPS debe devolver el estado real de la página, no otra redirección de vuelta a HTTP.
También prueba ambos nombres de host si ambos existen:
curl -I http://www.example.com/
curl -I https://www.example.com/
curl -I http://example.com/
curl -I https://example.com/
Estás buscando una cadena corta y predecible. Una redirección de HTTP a la URL HTTPS canónica es buena. Múltiples saltos, como HTTP sin www a HTTPS sin www a HTTPS con www y viceversa, son una señal de que Nginx, la aplicación, las reglas de CDN o el reenvío a nivel de DNS están peleando entre sí.
Puedes inspeccionar toda la cadena con:
curl -IL http://www.example.com/some/path
La bandera -L sigue las redirecciones. En una configuración limpia, la salida debe mostrar la respuesta HTTP inicial y luego la respuesta HTTPS final. Si ves tres o cuatro encabezados Location, simplifica las reglas hasta que haya una ruta clara a la URL canónica.
HSTS y Otras Mejores Prácticas
Después de que tu configuración HTTPS sea estable, puedes considerar HTTP Strict Transport Security, generalmente llamado HSTS. HSTS les dice a los navegadores que usen HTTPS automáticamente para visitas futuras.
Un encabezado común se ve así:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
No agregues esto a la ligera. Si incluyes subdominios, cada subdominio debe soportar HTTPS. Si luego rompes HTTPS, los navegadores que hayan visto el encabezado HSTS pueden negarse a acceder a la versión HTTP. Comienza con un max-age más corto durante las pruebas, luego auméntalo una vez que estés seguro.
Otras mejores prácticas:
- Mantén el bloque del puerto 80 simple.
- Preserva las rutas y cadenas de consulta a menos que tengas una razón para no hacerlo.
- Elige un nombre de host canónico.
- Prueba las redirecciones con
curl, no solo con un navegador. - Renueva los certificados automáticamente y monitorea las fallas de renovación.
- Mantén la lógica de redirección en Nginx cuando sea posible en lugar de duplicarla en la aplicación.
Las reglas de redirección simples son más fáciles de razonar y menos propensas a romperse durante cambios posteriores en el sitio.
Errores Comunes
El error más común es usar rewrite para una redirección simple:
rewrite ^ https://example.com$request_uri permanent;
Eso puede funcionar, pero return 301 ... es más claro y evita procesamiento adicional de reescritura. Usa rewrite cuando realmente necesites coincidencia de patrones, no para una redirección básica de esquema.
Otro error es redirigir a $server_name sin entender lo que contiene. $host proviene del encabezado de host de la solicitud, mientras que $server_name se basa en el nombre de servidor de Nginx coincidente. Para redirecciones canónicas, un nombre de host literal suele ser la opción menos sorprendente:
return 301 https://example.com$request_uri;
También debes evitar redirigir las rutas de desafío ACME HTTP si tu herramienta de certificados las necesita en el puerto 80. Muchas configuraciones de Let's Encrypt manejan esto automáticamente, pero las configuraciones personalizadas pueden necesitar una excepción:
location /.well-known/acme-challenge/ {
root /var/www/letsencrypt;
}
location / {
return 301 https://example.com$request_uri;
}
Solo agrega esa excepción si tu cliente de certificados la usa. Si tus certificados se renuevan mediante validación DNS o un servidor temporal administrado por herramientas, mantén el bloque de redirección simple.
Un Patrón de Implementación Seguro
Para un sitio de producción, realiza el cambio en etapas:
- Confirma que el bloque de servidor HTTPS sirva el sitio correctamente.
- Confirma que la renovación del certificado funcione o esté monitoreada.
- Agrega una redirección temporal en el puerto 80 si aún estás probando nombres de host.
- Prueba URLs comunes con
curl -Iycurl -IL. - Cambia a
301una vez que el destino de la redirección sea final. - Espera antes de habilitar HSTS de larga duración.
Ese período de espera es útil. Te da tiempo para detectar subdominios olvidados, URLs de webhook antiguas, enlaces http:// codificados o una regla de CDN que no era visible desde tu primera máquina de prueba.
También ten en cuenta el monitoreo. Si tu verificación de disponibilidad aún apunta a http://example.com, decide si debe esperar un 301 o seguir las redirecciones y verificar la página HTTPS final. Ambos pueden ser válidos, pero el monitor debe coincidir con el comportamiento que realmente deseas.
Ejemplo: Sitio Estático y Proxy Inverso
Para un sitio estático, el bloque HTTPS puede ser solo una raíz de documentos:
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
root /var/www/example.com;
index index.html;
}
Para una aplicación detrás de Nginx, el bloque de redirección sigue siendo el mismo, pero el bloque HTTPS hace proxy del tráfico:
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
El punto importante es la separación. El puerto 80 decide a dónde debe ir el navegador. El puerto 443 sirve el sitio. Mezclar esas tareas hace que el comportamiento de redirección sea más difícil de razonar, especialmente cuando se agrega otro proxy o CDN más adelante.
Después de editar, siempre ejecuta:
sudo nginx -t
sudo systemctl reload nginx
Si la prueba falla, no recargues. Primero corrige el error de sintaxis, luego prueba de nuevo.
Una verificación final vale la pena hacerla desde fuera del servidor, no solo a través de SSH en el host. Un firewall, CDN o balanceador de carga puede cambiar lo que ven los usuarios reales. Ejecuta las mismas comprobaciones curl -I desde tu laptop, una ubicación de monitoreo o una instancia temporal en la nube. Si el resultado externo difiere de localhost, el problema de redirección probablemente está en la capa de red frente a Nginx, no en el bloque del servidor en sí. Verifica eso antes de reescribir una configuración que funciona.
Cuándo Buscar Ayuda
Busca ayuda de un ingeniero DevOps si tu sitio está detrás de una CDN, balanceador de carga en la nube, ingress de Kubernetes o múltiples proxies inversos. Las redirecciones HTTPS en infraestructura en capas dependen de dónde termina TLS y en qué encabezados se confía.
También debes pedir ayuda antes de habilitar HSTS a largo plazo en muchos subdominios. Una configuración incorrecta puede bloquear a los usuarios de servicios que no están listos para HTTPS.
Redirigir HTTP a HTTPS en Nginx es un pequeño cambio de configuración con un gran impacto en la seguridad. Usa un bloque de redirección dedicado en el puerto 80, preserva la URI de la solicitud, verifica los certificados y prueba los bucles antes de darlo por terminado.