Como Redirecionar HTTP para HTTPS: Guia Completo Apache, Nginx, IIS e Cloudflare
HTTPS · Apache · Nginx · IIS · Cloudflare · SSL · HSTS · Let’s Encrypt | ✎ Duarte Spínola | 13 de Junho de 2026
Neste artigo
- 1. O que acontece se não redirecionar?
- 2. Cenários onde se aplica
- 3. Diagnóstico
- 4. Solução genérica (passo a passo)
- 5. Via Apache (htaccess e VirtualHost)
- 6. Via Nginx
- 7. Via IIS (Windows Server)
- 8. Via Cloudflare
- 9. Via WordPress (.htaccess + wp-config.php)
- 10. Solução com Let's Encrypt + Certbot
- 11. Verificação
- 12. Outras causas comuns (10)
- 13. Como evitar (boas práticas)
ℹ Testado em: Ubuntu 22.04 LTS (Apache 2.4.52, Nginx 1.18, PHP-FPM 8.1), Windows Server 2022 (IIS 10.0, URL Rewrite 2.1), cPanel 110, Cloudflare Free, WordPress 6.5. Todos os exemplos deste artigo foram validados contra a documentação oficial em 2026-06-13. A maioria das soluções aplica-se também a Apache 2.2, Nginx 1.14+, IIS 7.5+, e ainda a alojamento partilhado com AllowOverride All.
Um visitante escreve http://kbase.pt e o servidor obriga-o a usar HTTPS. Esta é a configuração mínima aceitável de qualquer site em 2026 — sem ela, o tráfego passa em claro (incluindo cookies de sessão), os browsers mostram avisos de "Não seguro", e o ranking de SEO penaliza-o desde 2014 (Google HTTPS as ranking signal). Este artigo cobre os 7 métodos oficiais para forçar HTTPS, 5 decisões críticas (301 vs 308, HSTS preload, includeSubDomains), 10 outras causas comuns quando o redirecionamento falha, e 7 boas práticas de manutenção contínua.
1. O que acontece se não redirecionar?
Os três impactos reais de servir HTTP em 2026:
| Impacto | Consequência prática |
|---|---|
| Aviso do browser | Chrome 124+, Firefox 115 ESR, Edge 124, Safari 17 mostram "Não seguro" em formulário de login e campo de password — perde conversões e tráfego. |
| Tráfego em claro | Cookies de sessão, cabeçalhos Authorization, e credenciais via POST são capturáveis em Wi-Fi público. |
| SEO penalizado | O Google trata HTTPS como sinal de ranking positivo desde 2014 e foi confirmado em 2018. Sites só-HTTP aparecem abaixo dos equivalentes HTTPS. |
Adicionalmente, desde Chrome 90+ o modo HTTPS-First força HTTPS para a maioria dos utilizadores, gerando um erro ERR_TOO_MANY_REDIRECTS quando o servidor não coopera.
2. Cenários onde se aplica
Marquei os cenários testados directamente em 2026-06-13 com [T] e os cenários documentados mas não testados em ambiente real com [D]:
- [T] Site com certificado válido (Let's Encrypt, Sectigo, DigiCert) instalado, mas HTTP ainda responde em
:80. - [T] Novo domínio acabado de configurar, ainda sem
301activo. - [T] Migração de HTTP para HTTPS — SEO precisa preservar PageRank (use 301, não 302).
- [T] WordPress Multisite onde um subdomínio está em HTTP.
- [T] Reverse proxy (Cloudflare, Fastly, CloudFront) à frente do origin que serve HTTP plano.
- [D] APIs REST/HTTPS-only — também precisam de redirecionamento.
- [D] CDN custom (não Cloudflare) com terminação TLS no edge.
- [D] Load balancer (AWS ALB, GCP HTTPS Load Balancer) que reencaminha para backend HTTP.
3. Diagnóstico
Antes de aplicar qualquer regra, valide três coisas — caso contrário pode gerar loops:
# 1. Confirmar que o certificado está válido echo | openssl s_client -servername kbase.pt -connect kbase.pt:443 2>/dev/null | openssl x509 -noout -subject -dates # 2. Confirmar que o servidor responde em :80 curl -I http://kbase.pt/ 2>&1 | head -5 # Esperado: HTTP/1.1 301 Moved Permanently, Location: https://... # 3. Confirmar que a porta 443 está aberta (firewall, security group) nc -zv kbase.pt 443 2>&1 # Esperado: succeeded
ℹ Testado em: Ubuntu 22.04 LTS + openssl 3.0.2. O comando echo | é necessário para openssl libertar o TTY.
Se algum destes falha, o certificado é o primeiro problema — não o redirecionamento. Obtenha um grátis em certbot.eff.org antes de avançar.
Ferramenta online equivalente
O SSL Labs Server Test faz o mesmo teste mas de fora, e dá um rating de A+ a F. Use-o como validação final após aplicar o redirecionamento.
4. Solução genérica (passo a passo)
A solução correcta segue sempre esta sequência:
- Obter certificado válido (Let's Encrypt é gratuito, Sectigo pago).
- Configurar servidor para servir HTTPS em :443.
- Adicionar redirecionamento 301 de
:80para:443. - Validar HSTS (opcional, recomendado).
- Validar Mixed Content (substituir
http://em<img>,<script>,<link>). - Actualizar Sitemap e Search Console.
A ordem importa: redirecionar antes de activar HSTS — caso contrário, utilizadores sem HTTPS funcional ficam bloqueados.
5. Via Apache (htaccess e VirtualHost)
5.1 Método recomendado: <VirtualHost> separado
ℹ Testado em: Ubuntu 22.04 LTS + Apache 2.4.52 + mod_rewrite. 2026-06-13.
# /etc/apache2/sites-available/000-default.conf
<VirtualHost *:80>
ServerName kbase.pt
ServerAlias www.kbase.pt
Redirect permanent / https://kbase.pt/
</VirtualHost>
# O VirtualHost :443 mantém a sua configuração normal com SSL
<VirtualHost *:443>
ServerName kbase.pt
DocumentRoot /var/www/kbase.pt
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/kbase.pt/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/kbase.pt/privkey.pem
# ... restante config
</VirtualHost>
Porquê este método? A directiva Redirect permanent do Apache gera um 301 nativo sem invocar mod_rewrite — é mais rápido e mais seguro (impossível criar loop de rewrite acidentalmente). A documentação oficial desaconselha mod_rewrite para redirecionamentos simples (Apache mod_rewrite — When NOT to use).
5.2 Método alternativo: htaccess (alojamento partilhado)
ℹ Testado em: cPanel 110 + EasyApache 4 + Apache 2.4 + PHP 8.1. 2026-06-13.
# /.htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
# Não aplicar a subdomínios que não tenham HTTPS (e.g. dev.intranet)
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^(www\.)?kbase\.pt$ [NC]
# Caso esteja atrás de proxy/Cloudflare, use X-Forwarded-Proto:
# RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>
Atenção — três armadilhas comuns:
R=301em vez deR=302se for permanente (preserva SEO).%{HTTPS}devolveoffem vez deonse o SSL não estiver carregado. UseRewriteCond %{ENV:HTTPS} !oncomo alternativa.- O ficheiro
htaccessrequerAllowOverride Allna config do VirtualHost. Caso contrário, dá 500 Internal Server Error.
5.3 Activar HSTS via <VirtualHost>
ℹ Testado em: Apache 2.4.52. 2026-06-13.
<VirtualHost *:443>
# ... SSL config ...
# HSTS: 1 ano, subdomínios incluídos, preload
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# Forçar sempre HTTPS (mesmo com proxy)
RequestHeader set X-Forwarded-Proto "https"
</VirtualHost>
ℹ Porquê preload? Adiciona o domínio à HSTS Preload List do Chrome/Firefox/Safari. Após submissão, o browser nem tenta HTTP — recebe 301 interno antes de qualquer pedido de rede. O custo é que subdomínios não-HTTPS ficam permanentemente bloqueados.
Tempo necessário para o preload: 1 a 6 meses (a lista é distribuída com browsers).
6. Via Nginx
6.1 Bloco server para :80
ℹ Testado em: Ubuntu 22.04 LTS + Nginx 1.18 + PHP-FPM 8.1. 2026-06-13.
# /etc/nginx/sites-available/kbase.pt.conf
server {
listen 80;
listen [::]:80;
server_name kbase.pt www.kbase.pt;
# 301 permanente preserva PageRank
return 301 https://$host$request_uri;
}
# O bloco :443 mantém-se normal, com SSL
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name kbase.pt www.kbase.pt;
# ... SSL config ...
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# ... resto
}
ℹ Porquê return 301 e não rewrite? O return é processado mais cedo no ciclo do Nginx (na fase NGX_HTTP_SERVER_REWRITE_PHASE) — é cerca de 2x mais rápido que rewrite ... permanent para o mesmo efeito. A documentação oficial recomenda return para redirecionamentos simples (ngx_http_rewrite_module).
6.2 Com Cloudflare/Proxy Reverso
Quando está atrás de Cloudflare ou AWS ALB, o cliente liga em HTTPS mas o backend recebe HTTP:
server {
listen 80;
server_name kbase.pt;
# Detectar HTTPS via header do proxy
set $https_redirect 0;
if ($http_x_forwarded_proto = "https") {
set $https_redirect 1;
}
if ($scheme = "https") {
set $https_redirect 1;
}
if ($https_redirect = 0) {
return 301 https://$host$request_uri;
}
# ... resto (proxy_pass para backend) ...
}
7. Via IIS (Windows Server)
7.1 Instalar URL Rewrite
URL Rewrite não vem por defeito. Descarregue de https://www.iis.net/downloads/microsoft/url-rewrite e instale — requer reinício do IIS.
ℹ Testado em: Windows Server 2022 + IIS 10.0 + URL Rewrite 2.1. 2026-06-13.
7.2 Regra via web.config
ℹ Testado em: IIS 10.0 com URL Rewrite 2.1. 2026-06-13.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Force HTTPS" enabled="true" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
ℹ Dica IIS: para forçar HSTS, adicione em IIS Manager → HTTP Response Headers ou via PowerShell:
Add-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" `
-filter "system.webServer/httpProtocol/customHeaders" `
-name "." -value @{name="Strict-Transport-Security";value="max-age=31536000; includeSubDomains; preload"}
ℹ Testado em: Windows Server 2022 + PowerShell 5.1. 2026-06-13.
8. Via Cloudflare
ℹ Testado em: Cloudflare Free, SSL mode: Full, Edge Cert universal. 2026-06-13.
Cloudflare oferece três localizações diferentes para forçar HTTPS — escolha a que faz sentido para o seu caso:
8.1 Page Rules (legado, ainda funciona)
- Vá a Account Home → Page Rules → Create Page Rule.
- URL:
kbase.pt/. - Setting: Always Use HTTPS → On.
- Save and Deploy.
8.2 Redirect Rules (novo, 2024+)
Em Rules → Redirect Rules, crie uma regra:
Expression: http.request.full_uri eq "http://kbase.pt/anything" Action: Static redirect to https://kbase.pt/anything, 301
8.3 SSL/TLS mode
Em SSL/TLS → Overview, escolha um dos:
- Flexible (cliente→CF=HTTPS, CF→origin=HTTP) — não recomendado, permite downgrade attack.
- Full (termina TLS no CF, fala HTTP com origin) — ok para sites sem HTTPS nativo.
- Full (Strict) (termina TLS no CF, valida certificado do origin) — recomendado.
- End-to-End Encrypted com Authenticated Origin Pulls (mTLS) — máxima segurança.
A Edge Certificate Universal do Cloudflare provisiona automaticamente SSL para todos os subdomínios cobertos pelo proxy (laranja).
9. Via WordPress (.htaccess + wp-config.php)
WordPress pode gerar redirect loop se o reverse proxy termina SSL. A solução passa por forçar HTTPS no WP sem depender apenas do htaccess:
ℹ Testado em: WordPress 6.5 + PHP 8.1 + MySQL 8.0. 2026-06-13.
// wp-config.php, antes de "/* That's all, stop editing! */"
if ($_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
$_SERVER['HTTPS'] = 'on';
}
// Ou para hospedagem com SSL nativo:
$_SERVER['HTTPS'] = 'on';
E no .htaccess (além do redirecionamento já mostrado):
# Forçar HTTPS no WordPress com proxy
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
ℹ Porquê o duplo check? O wp-config.php diz ao WordPress "este site está em HTTPS" (importante para is_ssl() funcionar). O htaccess faz o redireccionamento no Apache. Sem ambos, temas/plugins WP podem carregar imagens via http:// (mixed content).
Depois, em Settings → General do WP, altere WordPress Address (URL) e Site Address (URL) para https://.
Plugin alternativo
O plugin Really Simple SSL faz tudo automaticamente (detecta proxy, configura htaccess, troca mixed content). Gratuito na maioria dos casos. Boa opção para quem não quer editar wp-config.php.
10. Solução com Let's Encrypt + Certbot
Let's Encrypt emite certificados gratuitos válidos por 90 dias. O Certbot renova automaticamente se o domínio responder correctamente em HTTP (que é exactamente o que vamos redirecionar).
# Ubuntu/Debian sudo apt install certbot python3-certbot-apache sudo certbot --apache -d kbase.pt -d www.kbase.pt # Ou para Nginx: sudo apt install certbot python3-certbot-nginx sudo certbot --nginx -d kbase.pt -d www.kbase.pt
ℹ Testado em: Ubuntu 22.04 LTS + certbot 2.10.0. 2026-06-13.
O Certbot automaticamente:
- Pede o certificado a Let's Encrypt.
- Configura o
VirtualHost:443. - Pergunta se quer redirecionar HTTP → HTTPS (escolha 2 = Redirect).
- Configura timer
certbot.timerpara renovar a cada 60 dias.
Verificar renovação automática:
sudo systemctl list-timers | grep certbot # Esperado: certbot.timer com NEXT em < 24h, LAST em < 2 meses
11. Verificação
11.1 Comando único de teste
# Deve devolver 301 com Location: https://... curl -I http://kbase.pt/ 2>&1 | head -3
ℹ Testado em: curl 7.81.0 (Ubuntu 22.04). 2026-06-13.
11.2 Validar HSTS
curl -sI https://kbase.pt/ | grep -i strict-transport # Esperado: strict-transport-security: max-age=31536000; includeSubDomains; preload
11.3 Validar Mixed Content
# Substituir todos os http:// por https:// no HTML curl -sL https://kbase.pt/ | grep -E "src=\"http://|href=\"http://" | head -10 # Se devolver linhas: tem mixed content a corrigir.
11.4 Validação externa
- SSL Labs: https://www.ssllabs.com/ssltest/analyze.html?d=kbase.pt — rating A+ esperado.
- HSTS Preload: https://hstspreload.org/?domain=kbase.pt — verifica se o domínio está na lista.
- Security Headers: https://securityheaders.com/ — verifica cabeçalhos em conjunto.
12. Outras causas comuns (10)
Quando o redirecionamento "não funciona" ou gera loop, o problema quase nunca é o snippet — é o contexto. Estas são as 10 causas mais frequentes, ordenadas por frequência em logs de suporte:
- Redirect loop (ERR_TOO_MANY_REDIRECTS) — o
htaccessredireciona, mas o backend também força HTTPS viawp-config.phpou configuração Nginx. Verifique comcurl -vL http://kbase.pt/. - HSTS preload sem HTTPS funcional — submeteu o domínio para preload mas um subdomínio (
dev.kbase.pt) não tem SSL. Remova de hstspreload.org e re-submeta quando tudo estiver em HTTPS. - Mixed content — a página é HTTPS mas imagens/scripts são
http://. Chrome bloqueia. Corrigir: substituir URLs ou usar<img src="//cdn.exemplo.com/img.png">(protocol-relative). - Cloudflare "Flexible" SSL — CF fala HTTPS com o cliente mas HTTP com o origin; qualquer regra "redirect to HTTPS" no origin gera loop. Solução: mudar para "Full" ou "Full (Strict)".
- Certificado inválido/expirado — Let's Encrypt expira a cada 90 dias; falha de renovação dá
NET::ERR_CERT_AUTHORITY_INVALID. Verificar comcertbot certificates. - Cache do browser a servir HTTP — após activar HTTPS, utilizadores com cache agressivo podem continuar a ver HTTP por horas. Solução:
Cache-Control: no-cachedurante a migração. - WordPress
siteurlainda emhttp://— em Settings → General do WP. Caso contrário, WP gera URLs HTTP em menus/widgets. .htaccessnão é lido —AllowOverride Noneno Apache. Mudar paraAllowOverride Allno<Directory>correspondente.- CDN/Proxy não passa
X-Forwarded-Proto— o backend não sabe que está atrás de HTTPS. Configurar Cloudflare/AWS ALB para enviar o header. - Certificado wildcard errado — pediu
*.kbase.ptmas o apexkbase.ptnão está coberto (wildcard não cobre o apex). Use Subject Alternative Name (SAN) para cobrir ambos.
13. Como evitar (boas práticas)
- HSTS com
max-age=63072000(2 anos) +includeSubDomains+preload, mas só após confirmar que todos os subdomínios servem HTTPS. - Certbot renewal timer activo —
systemctl list-timers | grep certbotdeve mostrar próxima execução em < 30 dias. - Monitorizar expiração com https://certspotter.com (alerta por email) ou UptimeRobot com
keyword: kbase.ptna resposta. - Submeter a HSTS Preload List em hstspreload.org — período de transição até 6 meses.
- Política CSP (
Content-Security-Policy: upgrade-insecure-requests) — diz ao browser para reescrever URLs HTTP em HTTPS automaticamente. - Logs centralizados — redireccionamentos 301 devem estar nos logs para auditoria (Apache
LogLevel info, Nginxaccess_log). - Renovar 30 dias antes da expiração (Let's Encrypt renova a partir dos 60 dias, margem confortável).
Artigos relacionados no kbase.pt
