Posted on

Table of Contents

Shameless advert

Join our open fedi relay! relay.disobey.net

Introduction

I run the disobey.net and nautical.social Mastodon instances. I self-host these as standalone servers built from source, not Docker.

Why HSTS-preload?

Mastodon admins should care about their domain being HSTS-preloaded to enhance user security and protect against targeted network attacks, but also enhances defences for users from sweeping network surveillance in the future leading to internet censorship.

  • Yes, your nginx config should automatically upgrade any HTTP requets to HTTPS during any visit. That's after a potential HTTP handshake is sent.

  • Yes, the default HSTS (non-preload) header set by Mastodon/Rails, and by Let's Encrypt Certbot in nginx (non-preload), will make it so any second visit to the domain from a user's browser will only ever send TLS handshakes before sending clear-text HTTP handshakes. Again, that's after an HTTP handshake is sent during a first visit.

  • And, yes, modern browsers should all default to trying HTTPS first even if a user only enters "disobey.net" into their address bar. But what if a browser or Mastodon app fails the user?

By being HSTS-preloaded, your Mastodon domain will be on a list of HSTS domains built into their web browser. This means even first-time visitors are protected from MitM attacks because clear-text HTTP headers will never be sent to the web server.

This has even more value once TLS Encrypted Client Hello (ECH) becomes mainstream, particularly for people living behind government surveillance and censorship. If a user is observed going to a censored Mastodon domain the first time, there might not be a first visit, let alone a second or third visit.

Pre-config validation

In a terminal window, I can see that my strict-transport-security header does not have the preload option:

curl -I https://disobey.net |grep strict

The last line shows:

strict-transport-security: max-age=63072000; includeSubDomains

We can see that there is no "preload" flag at the end, and this is with an nginx config that explicitly, presumably adds HSTS-preload:

add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";

Obviosuly setting this in nginx is not enough. The problem is Rails.

Mastodon changes

All file editing below is from my Mastodon root directory, "~/live".

You will only need to edit this one file:

vim config/environments/production.rb

Find the "config.ssl_options" line. Immediately under it, add:

hsts: { preload: true },

It should be indented the same as the line below it:

added hsts preload line

Save and quit, if you're using vim:

:wq

As the mastodon user:

RAILS_ENV=production bundle exec rails assets:precompile

As root user:

systemctl restart mastodon-web mastodon-sidekiq mastodon-streaming

Post-config validation

In a terminal window, I can see that my strict-transport-security header is now set correctly:

curl -I https://disobey.net |grep strict

The last line shows:

strict-transport-security: max-age=63072000; includeSubDomains; preload

Add your domain to the HSTS-preload list

Now you can add your domain to Google's HSTS-preload list: https://hstspreload.org