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

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 301 activo.
  • [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:

  1. Obter certificado válido (Let's Encrypt é gratuito, Sectigo pago).
  2. Configurar servidor para servir HTTPS em :443.
  3. Adicionar redirecionamento 301 de :80 para :443.
  4. Validar HSTS (opcional, recomendado).
  5. Validar Mixed Content (substituir http:// em <img>, <script>, <link>).
  6. 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=301 em vez de R=302 se for permanente (preserva SEO).
  • %{HTTPS} devolve off em vez de on se o SSL não estiver carregado. Use RewriteCond %{ENV:HTTPS} !on como alternativa.
  • O ficheiro htaccess requer AllowOverride All na 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)

  1. Vá a Account Home → Page Rules → Create Page Rule.
  2. URL: kbase.pt/.
  3. Setting: Always Use HTTPS → On.
  4. 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:

  1. Pede o certificado a Let's Encrypt.
  2. Configura o VirtualHost :443.
  3. Pergunta se quer redirecionar HTTP → HTTPS (escolha 2 = Redirect).
  4. Configura timer certbot.timer para 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

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:

  1. Redirect loop (ERR_TOO_MANY_REDIRECTS) — o htaccess redireciona, mas o backend também força HTTPS via wp-config.php ou configuração Nginx. Verifique com curl -vL http://kbase.pt/.
  2. 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.
  3. 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).
  4. 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)".
  5. Certificado inválido/expirado — Let's Encrypt expira a cada 90 dias; falha de renovação dá NET::ERR_CERT_AUTHORITY_INVALID. Verificar com certbot certificates.
  6. 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-cache durante a migração.
  7. WordPress siteurl ainda em http:// — em Settings → General do WP. Caso contrário, WP gera URLs HTTP em menus/widgets.
  8. .htaccess não é lidoAllowOverride None no Apache. Mudar para AllowOverride All no <Directory> correspondente.
  9. 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.
  10. Certificado wildcard errado — pediu *.kbase.pt mas o apex kbase.pt não está coberto (wildcard não cobre o apex). Use Subject Alternative Name (SAN) para cobrir ambos.

13. Como evitar (boas práticas)

  1. HSTS com max-age=63072000 (2 anos) + includeSubDomains + preload, mas só após confirmar que todos os subdomínios servem HTTPS.
  2. Certbot renewal timer activosystemctl list-timers | grep certbot deve mostrar próxima execução em < 30 dias.
  3. Monitorizar expiração com https://certspotter.com (alerta por email) ou UptimeRobot com keyword: kbase.pt na resposta.
  4. Submeter a HSTS Preload List em hstspreload.org — período de transição até 6 meses.
  5. Política CSP (Content-Security-Policy: upgrade-insecure-requests) — diz ao browser para reescrever URLs HTTP em HTTPS automaticamente.
  6. Logs centralizados — redireccionamentos 301 devem estar nos logs para auditoria (Apache LogLevel info, Nginx access_log).
  7. Renovar 30 dias antes da expiração (Let's Encrypt renova a partir dos 60 dias, margem confortável).

Este artigo foi útil?

Duarte Spínola

Deixe um Comentário