A Simple .htaccess Recipe for HTTPS Redirect + HSTS

I like to get at least one blog post in a year — this one is coming in just under the wire!

One of the phone screen questions I like to ask junior frontend candidates (and occasionally more experienced frontend candidates) is:

Imagine you’re creating a website that doesn’t have any login capabilities, shopping carts, or anything other than static articles. Would you go to the effort of setting up HTTPS? Why or why not?”

The answers I’m hoping to hear are along the lines of, “to make sure that people are actually connecting to your site,” or “to prevent a man-in-the-middle from tampering with your site.” Which then sometimes leads into an interesting discussion about TLS and what the candidate understands about networking.

Important stuff! Which makes it at least a little bit embarrassing to admit that it was only this year that I got around to adding proper HTTPS with redirects to my own website. Now, at least, I can ask my interview question without feeling like a giant hypocrite.

To make this post more about utility and less about self-flagellation, here’s the configuration I used. I’m on an old shared host, so this configuration is oriented towards people like myself, who are stuck hand-editing .htaccess files like a peasant. Interestingly, when you search for “redirect HTTP to HTTPS”, there aren’t actually that many pages that cover HTTPS redirects and HSTS in the same place, so perhaps this will be useful to somebody:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{SERVER_PORT} 80 
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>

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

Notes:

  • If you’re not on a shared host and forced to use .htaccess, the Apache documentation recommends using Redirect instead mod_rewrite.
  • The Strict-Transport-Security heading should be set only for HTTPS traffic. In this case, we’re in the clear because Header set applies to normal 2xx responses. If I had used Header always set, this would also set the heading on 3xx responses, which would be incorrect.
  • I haven’t configured HSTS preload yet, but you might consider doing that.