Canonical Host and HTTPS

A Canonical Host and HTTPS Block, Explained Line by Line

This block sends every variant of the site to https://example.com in one hop, keeping path and query string. With access to the vhosts, a port-80 Redirect permanent (mod_ssl and HTTPS) is simpler.

A canonical host and HTTPS blockApache config
# /var/www/example/.htaccess: one public origin, https://example.com
# Needs: mod_rewrite; AllowOverride FileInfo; Options FollowSymLinks
RewriteEngine On
# Rule 1: any host other than the canonical one, on either scheme
RewriteCond %{HTTP_HOST} !^example\.com(:\d+)?$ [NC]
RewriteRule ^ https://example.com%{REQUEST_URI} [R=301,L]
# Rule 2: the canonical host over plain HTTP, with no TLS proxy in front
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP:X-Forwarded-Proto} !=https
RewriteRule ^ https://example.com%{REQUEST_URI} [R=301,L]

Line 3 has no <IfModule> wrapper, so a server without mod_rewrite fails with a 500 rather than silently serving duplicates. Line 5 matches any other Host (www, an IP address, an old domain), and line 6 sends it straight to HTTPS, so http://www costs one hop. Lines 8 and 9 catch plain HTTP unless a TLS-terminating load balancer says otherwise; delete line 9 if none sits in front, since any client can send that header. Query strings pass through:

Output of 51
http://example.com/?id=7         301 https://example.com/?id=7
http://www.example.com/?id=7     301 https://example.com/?id=7
https://WWW.Example.com/         301 https://example.com/
https://example.com/             200 
http://www.example.com/caf%C3%A9 301 https://example.com/caf%c3%a9
http://example.com/ (proxied)    200

Leave off the NE flag many copies add: %{REQUEST_URI} is decoded, and mod_rewrite re-encodes it (the café line) unless NE is set; with it, /a%20b produced Location: https://example.com/a b. Let's Encrypt 1,144 's HTTP-01 check follows redirects to HTTPS, so renewals need no exemption. Add HSTS once every name serves HTTPS (Canonical HTTPS Block).