Reindirizzare HTTP su HTTPS con .htaccess (redirect 301)

Pubblicato il Aggiornato il 4 min di lettura

I visitatori arrivano ancora sulla versione non cifrata? Bastano poche righe nel file .htaccess per reindirizzare ogni chiamata HTTP su HTTPS in modo permanente, con un redirect 301.

Il tuo server pubblica già il sito via HTTPS, ma i visitatori continuano ad arrivare sulla versione HTTP non cifrata? Allora manca un reindirizzamento. In questa guida configuri un redirect permanente (codice di stato 301) da HTTP a HTTPS con un file .htaccess.

Un redirect 301 è la scelta giusta anche dal punto di vista SEO: i motori di ricerca trasferiscono così il posizionamento del vecchio indirizzo HTTP sull'indirizzo HTTPS, invece di trattare le due varianti come pagine separate.

Requisiti

  • Sul tuo server gira Apache. Per nginx vale una configurazione diversa, ne parliamo più avanti.
  • Un certificato SSL valido è già configurato. In caso contrario trovi la guida adatta nell'articolo Configurare gratuitamente un certificato SSL con Let's Encrypt.
  • Hai accesso alla directory web del tuo server, via SSH oppure via FTP.

Importante: configura il reindirizzamento solo quando HTTPS funziona davvero. Altrimenti mandi i visitatori su un indirizzo che mostra un avviso sul certificato.

Attivare mod_rewrite e consentire il file .htaccess

Il reindirizzamento si appoggia al modulo Apache mod_rewrite. Attivalo e riavvia Apache:

a2enmod rewrite
systemctl restart apache2

Perché Apache legga davvero il file .htaccess, il VirtualHost deve consentirlo. Controlla nella configurazione sotto /etc/apache2/sites-available/ se per la tua directory è impostato AllowOverride All:

<Directory /var/www/MioDominio.it>
    AllowOverride All
    Require all granted
</Directory>

Se lì trovi AllowOverride None, il tuo file .htaccess viene ignorato in silenzio. Dopo una modifica al file del VirtualHost serve un riavvio di Apache.

Creare il file .htaccess

Spostati nella directory in cui si trova il tuo sito:

cd /var/www/<TUA-DIRECTORY-WEB>

Apri il file .htaccess nell'editor. Se non esiste ancora, il comando lo crea:

nano .htaccess

Inserisci le righe seguenti. Questa variante verifica direttamente se la connessione è cifrata e aggiunge alla destinazione l'intero percorso richiamato:

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

Salva il file con "CTRL + X", poi "Y" e "Invio".

Alternativa tramite la porta del server

Sulle configurazioni più vecchie, dove la variabile HTTPS non viene impostata, funziona invece l'interrogazione della porta:

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

Variante dietro un reverse proxy o un load balancer

Se davanti al tuo Apache si trova un reverse proxy o un load balancer che termina lui stesso la cifratura, ad Apache arriva una richiesta non cifrata. La regola qui sopra reindirizzerebbe all'infinito. In questo caso valuta l'header che il proxy inoltra:

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

Testare il reindirizzamento

Richiama il tuo dominio nel browser tramite http://. Dovresti finire subito su https://. Da riga di comando verifichi il codice di stato direttamente:

curl -I http://MioDominio.it

Nell'output deve comparire HTTP/1.1 301 Moved Permanently, più una riga Location con l'indirizzo HTTPS. Se invece appare un codice di stato 302, controlla che nella regola ci sia davvero R=301.

Attivare HSTS (opzionale)

Con HTTP Strict Transport Security dici al browser di non richiamare più il tuo dominio via HTTP. In questo modo sparisce anche la prima chiamata non protetta. Attiva per prima cosa il modulo necessario:

a2enmod headers
systemctl restart apache2

Poi aggiungi nel file .htaccess:

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

Attenzione: HSTS è un impegno per un anno intero. Finché il valore resta memorizzato nel browser, il dominio non è più raggiungibile via HTTP. Imposta l'header solo quando HTTPS funziona in modo affidabile e anche tutti i sottodomini hanno un certificato valido.

Errori frequenti

  • Loop infinito ("too many redirects"): quasi sempre la conseguenza di un proxy posto davanti al server. Usa la variante con X-Forwarded-Proto.
  • Non succede nulla: o mod_rewrite non è attivo, oppure il VirtualHost non consente alcun file .htaccess (AllowOverride None).
  • Errore 500 dopo il salvataggio: un errore di battitura nel file .htaccess. Il motivo esatto si trova nel log degli errori di Apache, sotto /var/log/apache2/error.log.
  • Contenuti misti: la pagina si carica sì via HTTPS, ma richiama ancora immagini o script via HTTP. Correggi questi indirizzi nel tuo codice sorgente oppure nel database.
  • Il file non si trova: il file .htaccess inizia con un punto ed è quindi nascosto. Con ls -la lo vedi.

Reindirizzamento senza .htaccess

Un file .htaccess viene riletto a ogni singola richiesta. Se hai accesso alla configurazione del server, è più veloce inserire le regole direttamente nel VirtualHost. Per il VirtualHost HTTP basta questo:

<VirtualHost *:80>
    ServerName MioDominio.it
    Redirect permanent / https://MioDominio.it/
</VirtualHost>

Se usi nginx al posto di Apache, i file .htaccess non esistono. Lì inserisci il reindirizzamento nel blocco server per la porta 80:

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

Domande frequenti

Perché un redirect 301 e non un 302?
301 indica un reindirizzamento permanente. I motori di ricerca trasferiscono così la valutazione del vecchio indirizzo HTTP sull'indirizzo HTTPS. Un 302 vale come temporaneo e non trasmette questi segnali.
Il mio file .htaccess viene ignorato. Da cosa dipende?
O mod_rewrite non è attivato, oppure il VirtualHost non consente alcun override. Imposta AllowOverride All per la tua directory e riavvia Apache subito dopo.
Perché finisco in un loop infinito?
Succede quasi sempre quando davanti ad Apache un reverse proxy o un load balancer termina la cifratura. In quel caso valuta l'header X-Forwarded-Proto invece della variabile HTTPS.
Funziona anche con nginx?
No, nginx non conosce i file .htaccess. Lì inserisci il reindirizzamento direttamente nel blocco server per la porta 80, con la riga return 301 https://$host$request_uri.
Conviene attivare anche HSTS?
HSTS aumenta la sicurezza, ma ti vincola per tutta la durata indicata. Attivalo solo quando HTTPS funziona in modo affidabile sul dominio e su tutti i sottodomini.

.htaccess Reindirizzamento Redirect 301 HTTPS Apache mod_rewrite HSTS