Redirigir HTTP a HTTPS con .htaccess (redirección 301)

Publicado el Actualizado el 4 min de lectura

¿Tus visitantes siguen llegando a la versión sin cifrar? Con unas pocas líneas en el archivo .htaccess envías cada petición HTTP a HTTPS de forma permanente, con una redirección 301.

¿Tu servidor ya entrega el sitio web por HTTPS, pero las visitas siguen aterrizando en la versión HTTP sin cifrar? Entonces falta una redirección. En esta guía configuras, con un archivo .htaccess, una redirección permanente (código de estado 301) de HTTP a HTTPS.

Una redirección 301 también es la opción correcta desde el punto de vista del SEO: los buscadores traspasan así el posicionamiento de la antigua dirección HTTP a la dirección HTTPS, en lugar de tratar ambas variantes como páginas separadas.

Requisitos

  • En tu servidor corre Apache. Con nginx la configuración es distinta, lo vemos más abajo.
  • Ya tienes instalado un certificado SSL válido. Si no es así, encontrarás la guía correspondiente en el artículo Configurar un certificado SSL gratuito con Let's Encrypt.
  • Tienes acceso al directorio web de tu servidor, por SSH o por FTP.

Importante: configura la redirección solo cuando HTTPS ya funcione. De lo contrario, enviarás a tus visitantes a una dirección que les muestra una advertencia de certificado.

Activar mod_rewrite y permitir el archivo .htaccess

La redirección se apoya en el módulo de Apache mod_rewrite. Actívalo y reinicia Apache:

a2enmod rewrite
systemctl restart apache2

Para que Apache llegue siquiera a leer el archivo .htaccess, el VirtualHost tiene que permitirlo. Comprueba en la configuración, bajo /etc/apache2/sites-available/, si AllowOverride All está definido para tu directorio:

<Directory /var/www/MiDominio.com>
    AllowOverride All
    Require all granted
</Directory>

Si ahí pone AllowOverride None, tu archivo .htaccess se ignora en silencio. Después de modificar el archivo del VirtualHost hace falta reiniciar Apache.

Crear el archivo .htaccess

Cámbiate al directorio donde está tu sitio web:

cd /var/www/<TU-DIRECTORIO-WEB>

Abre el archivo .htaccess en el editor. Si todavía no existe, el comando lo crea:

nano .htaccess

Añade las siguientes líneas. Esta variante comprueba directamente si la conexión está cifrada y añade al destino la ruta completa que se ha solicitado:

RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Guarda el archivo con "CTRL + X", después "Y" y "Enter".

Alternativa a través del puerto del servidor

En configuraciones antiguas, en las que la variable HTTPS no se define, funciona en su lugar la consulta del puerto:

RewriteEngine On
RewriteCond %{SERVER_PORT} !^443$
RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L]

Variante detrás de un reverse proxy o un load balancer

Si delante de tu Apache hay un reverse proxy o un load balancer que termina el cifrado por su cuenta, a Apache le llega una petición sin cifrar. La regla anterior redirigiría entonces sin parar. En ese caso, evalúa la cabecera que envía el proxy:

RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Probar la redirección

Abre tu dominio en el navegador a través de http://. Deberías aterrizar de inmediato en https://. Desde la línea de comandos compruebas el código de estado directamente:

curl -I http://MiDominio.com

En la salida tiene que aparecer HTTP/1.1 301 Moved Permanently, además de una línea Location con la dirección HTTPS. Si en su lugar aparece un código de estado 302, comprueba que la regla contenga realmente R=301.

Activar HSTS (opcional)

Con HTTP Strict Transport Security le indicas al navegador que no vuelva a llamar a tu dominio por HTTP. Así desaparece la primera petición sin proteger. Activa primero el módulo necesario:

a2enmod headers
systemctl restart apache2

A continuación, completa el archivo .htaccess:

<IfModule mod_headers.c>
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</IfModule>

Ten en cuenta una cosa: HSTS es un compromiso para un año entero. Mientras el valor siga guardado en el navegador, el dominio ya no será accesible por HTTP. Añade la cabecera solo cuando HTTPS funcione de forma fiable y todos los subdominios tengan también un certificado válido.

Errores frecuentes

  • Bucle infinito ("too many redirects"): casi siempre es consecuencia de un proxy situado por delante. Usa la variante con X-Forwarded-Proto.
  • No pasa nada: o bien mod_rewrite no está activo, o bien el VirtualHost no permite ningún archivo .htaccess (AllowOverride None).
  • Error 500 después de guardar: una errata en el archivo .htaccess. El motivo exacto está en el log de errores de Apache, en /var/log/apache2/error.log.
  • Contenido mixto: la página sí carga por HTTPS, pero sigue incluyendo imágenes o scripts por HTTP. Corrige esas direcciones en tu código fuente o en la base de datos.
  • El archivo no aparece: el archivo .htaccess empieza por un punto y por eso está oculto. Con ls -la lo verás.

Redirección sin .htaccess

Un archivo .htaccess se vuelve a leer en cada petición. Si tienes acceso a la configuración del servidor, es más rápido dejar las reglas directamente en el VirtualHost. Para el VirtualHost de HTTP basta con esto:

<VirtualHost *:80>
    ServerName MiDominio.com
    Redirect permanent / https://MiDominio.com/
</VirtualHost>

Si usas nginx en lugar de Apache, no existen los archivos .htaccess. Ahí la redirección se declara en el bloque server del puerto 80:

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

Preguntas frecuentes

¿Por qué una redirección 301 y no una 302?
El código 301 indica una redirección permanente. Los buscadores traspasan así la valoración de la antigua dirección HTTP a la dirección HTTPS. Un 302 se considera temporal y no transmite esas señales.
Mi archivo .htaccess se ignora. ¿A qué se debe?
O bien mod_rewrite no está activado, o bien el VirtualHost no permite overrides. Define AllowOverride All para tu directorio y reinicia Apache después.
¿Por qué acabo en un bucle infinito?
Casi siempre ocurre cuando un reverse proxy o un load balancer termina el cifrado por delante de Apache. Evalúa entonces la cabecera X-Forwarded-Proto en lugar de la variable HTTPS.
¿Funciona también con nginx?
No, nginx no conoce los archivos .htaccess. Ahí la redirección se declara directamente en el bloque server del puerto 80, con la línea return 301 https://$host$request_uri.
¿Debería activar HSTS además?
HSTS aumenta la seguridad, pero te compromete durante el plazo indicado. Actívalo solo cuando HTTPS funcione de forma fiable en el dominio y en todos los subdominios.

.htaccess Redirección Redirección 301 HTTPS Apache mod_rewrite HSTS