HSTS Preloading using Nginx, Letsencrypt and Capistrano.😎
Tags: devops, security, browsers, https
Published: 2018-10-15 14:40:36

---
title: "HSTS Preloading using Nginx, Letsencrypt and Capistrano.😎"
published: true
description: A way to serve your site on `https` only and hardcode that fact into browsers using HSTS preloading.
tags: devops, security, browsers, https. 
---

Quick tip: HSTS stands for [HTTPS Strict Transport Security](https://tools.ietf.org/html/rfc6797). 

HSTS is a security policy mechanism that protects against protocol downgrade attacks. In simple terms it means forcing the browsers to always use `https` over `http` for your website. HSTS also protects against cookie hijacking but we'll leave that discussion out for another post. 

In the post below we talk about how to quickly configure your web-server (nginx) to imply HSTS on all subsequent requests and then *hardcode* this rule into Chrome and other major browsers to default on `https` for your website using HSTS preloading. 

We're doing this on [Bubblin Superbooks](https://bubblin.io) now. 😇

I recommend reading the following blog by Scott Helme to learn more about <a href="https://scotthelme.co.uk/hsts-preloading/" rel="nofollow"> HSTS preloading</a>.


> …a list of hosts that wish to enforce the use of SSL/TLS on their site is built into a browser. This list is compiled by Google and is utilised by Chrome, Firefox and Safari. These sites do not depend on the issuing of the HSTS response header to enforce the policy, instead the browser is already aware that the host requires the use of SSL/TLS before any connection or communication even takes place.

The ‘preloading’ part here is a way for site administrators to tell the vendors in advance that their site is on `https` only. This way browsers can skip trying downgraded requests over insecure http altogether.

### HSTS directive for Nginx

Now we use the old boy <a href="https://capistranorb.com/" rel="nofollow">Capistrano</a> for automatic deployments of Bubblin and serve books  over https only, so configuring `nginx` over to strict `https` with preloads was super easy. I edited the template picked up by the <a href="https://github.com/treenewbee/capistrano3-nginx" rel="nofollow">capistrano3-nginx</a> gem for http --> https redirection and added the following directive at the end of the file to what is now our [latest nginx config template](https://gist.github.com/marvindanig/0bdd7d8768cbf5eab2fc4782803df87d). 



```ruby

# Path to ./config/deploy/templates/nginx_conf.erb on your rails app
# Jump over to the last line!
… 

server {
    listen 80;
    listen [::]:80 ipv6only=on; 
    server_name <%= fetch(:nginx_server_name) %> www.<%= fetch(:nginx_server_name) %>;
    rewrite ^(.*) https://$host$1$request_uri permanent;
}
 
server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;  
  server_name www.<%= fetch(:nginx_server_name) %>;


  # Redirection from http --> https is mandatory.
  rewrite ^ https://<%= fetch(:nginx_server_name) %>$request_uri permanent; 

}

server {
  server_name <%= fetch(:nginx_server_name) %>;
  root <%= current_path %>/public;
  try_files $uri/index.html $uri @puma_<%= fetch(:nginx_config_name) %>;

  …
  …

  # Plenty of nginx configuration here.

  # SSL is mandatory for HSTS. We're using 
  # Certbot to manage Letsencrypt for us.

  listen 443 ssl http2; # managed by Certbot
  listen [::]:443 ssl http2;
  
  

  # Add HSTS header with preload. This is the line that does it.
  add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";

}

```


The HSTS directive `add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";` at the bottom does it and tells the user's browser to always use `https` for your site. 

Commit the changes and then re-deploy ($ cap production deploy). Now head over to <a href="https://hstspreload.org" rel="nofollow">hstspreload.org</a>. 

This is where we submit our site for inclusion in Chrome's HTTP Strict Transport Security (HSTS) _preload list_. The list of sites that are hardcoded into Chrome as being `https` only. Most major browsers like Firefox, Opera, Safari, IE 11 and Edge also have HSTS preload lists based on the list compiled by Chrome. In order to be accepted to and remain on the HSTS preload list through this form, your site must satisfy the following set of requirements perpetually:

	1. Serve a valid certificate.
	2. Redirect from HTTP to HTTPS on the same host, if you are listening on port 80.
	3. Serve all subdomains over HTTPS.
		In particular, you must support HTTPS for the www subdomain if a DNS record for that subdomain exists.
	4. Serve an HSTS header on the base domain for HTTPS requests:
		i. The max-age must be at least 31536000 seconds (1 year).
		ii. The includeSubDomains directive must be specified.
		iii. The preload directive must be specified.
		iv. If you are serving an additional redirect from your HTTPS site, that redirect must still have the HSTS header (rather than the page it redirects to).



It should also be noted here that hardcoding HSTS preloading into browsers doesn't automatically mean that all aspects of security have been taken care of. It surely helps with security and plus there is a small improvement in speed and performance of your web-server because it no longer has to determine and switch between secure and insecure protocols.


That's all there is to it with HSTS folks. ❤️

---

I'm Sonica Arora, CTO of Bubblin Superbooks and you can follow me here on [Twitter](https://twitter.com/marvindanig).

**P.S.:** Did you know that [Bubblin](https://bubblin.io) is a cool new way to read books on your iPad?