Adding HSTS To Your Website

Adding HSTS To Your Website

So you’ve moved your website to use SSL/TLS and that’s it? Not quite! Your next step should to test your site and enable HSTS (HTTP Strict Transport Security).

19Dec2017 – Originally posted
5Apr2018 – Added speed difference verbiage between server config and functions.php or .htaccess for high volume websites

Testing via Qualys SSL Labs

I *love* the SSL Labs server test from Qualys. It’s free and it does a fantastic job of testing (and subsequently grading) your website for cipher suites, protocols (SSL/TLS versions), etc. IMO, it should be one of the first checks performed after standing up a website and then periodically checked every X number of months after that. The beauty of the tests is that pretty much everyone understands the grading system so if your site receives a B, you are going to wonder how you could make that an A… Unless you are just a classic underachiever! 😉

Simply go to the website below, type in your hostname (example:, click submit, and wait a bit.

SSL Labs hostname

There are a ton of possible issues why you might not get a ‘B’ score or worse such as cipher suites, protocols, etc. I won’t go into each of those because 1) there really are a million reasons why and 2) they are easily understood/explained. One common issue that isn’t quite so obvious is why your website is stuck at an ‘A’ and an ‘A+’ score remains elusive. Fortunately, it is most likely a rather simple solution involving HSTS.

What is HSTS?

HSTS protects your website against against protocol downgrade attacks. A protocol downgrade attack would allow a man-in-the-middle to send an unknowing user to an http version of your site instead of an https version. To combat this, when someone goes to your site, it receives a “Strict-Transport-Security” response header which it then caches based on the “max-age” setting. Thus, on subsequent visits it knows the site should be https even if someone is trying to perform the downgrade attack. Because it requires MiTM, it’s not a common attack vector most would worry about, but if you enabled https on your site you might as well make sure your users are using it. Going back to the results from SSL Labs, if you scroll down and look under “Protocol Details” you will see a couple of references to HSTS. Assuming HSTS is not enabled, you will see ‘No’ as in the example below.


There are several ways to add HSTS to your site. Make sure you only add it one way or you may receive unexpected results.

Option 1: Adding HSTS via WordPress plug-in

WordPress also has a plug-in available for this and it works ok if you are adverse to modifying files by hand. Simply go to Add Plugins, search for HSTS, and install the one below. After clicking ‘install’ and ‘activate’ you are done!

Adding HSTS to WordPress

One issue with this approach is that your website will only have HSTS on the URL in the WordPress Address (Settings -> General), but not the forwarded site. For example, would show HSTS is enabled, but would not. If you flip-flop and change the WordPress Address to, then wouldn’t be HSTS.

WordPress Address - HSTS

Maybe that isn’t a big deal? If not, leave well enough alone. Another minor caveat is that by default, the plug-in also has the max-age as 15984000. This means you can’t apply for inclusion into the pre-load list (discussed below in the “Going further” section).

Option 2: Adding HSTS via WordPress functions.php file <- my preferred way

Another way to add HSTS in WordPress is via the functions.php file for your theme. If you use cPanel, go to file manager and then select web root as shown below.

cPanel file manager

From there, go to wp-content, themes, double-click your theme name, select functions.php and then click edit.

If you don’t have cPanel, no problem. You can navigate to the functions.php file in a similar fashion, although your initial folder might be slightly different depending on your install.

Sample path: /public_html/wp-content/themes/<your theme name>/functions.php
The lines below are what you need to add to the functions.php file. I prefer to add it at the very bottom to ensure you don’t get caught in a function and/or other code. Note the max-age is also set to 31536000, which is the equivalent of one year and necessary for inclusion on the pre-load list. If you are just starting out, you might consider making the “max-age” much lower and slowly increasing it after you determine there aren’t some unintended side effects.
if (is_ssl()) {
 header('Strict-Transport-Security:max-age=31536000; includeSubdomains; preload');

Also note the if statement checks whether the page is SSL. The “if” is not 100% necessary, but the HSTS pre-load website complains if you don’t have it via the warning below “unnecessary HSTS header over HTTP.”


Keep in mind that since the change was made to the theme, if your website theme ever changes, you will need to re-add the code above to the functions.php file. Alternatively, you could add any of the code below to your web server instead of modifying the functions.php file.

If you have a high-volume website, I would suggest using the respective server configurations below instead of the functions.php or .htaccess methods. Unfortunately, the server configuration file isn’t accessible in many hosted environments.

Option 3: Adding HSTS on Apache

You can add the following to your .htaccess file in the public_html directory. If you have access to the Apache configuration file, you should make this change in the VirtualHost section instead of using .htaccess. The reason for this is because .htaccess is often regarded as slow and in most cases, it should be avoided. Don’t forget that if the server configuration is modified, a restart of Apache is needed.

Header set Strict-Transport-Security "max-age=31536000" env=HTTPS

Option 4: Adding HSTS on nginx

Simply add this to the server block of your HTTPS config. Restart nginx.

add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";

Option 5: Adding HSTS on IIS

Open the Internet Information Services (IIS) Manager (Start → Administrative Tools → IIS Manager). Click on HTTP Response Headers, then click on Add (in the Actions panel). Add the following values in the Add Custom HTTP Response Headers dialog box and restart IIS.

Name: Strict-Transport-Security
Value: max-age=31536000


You can go back to SSL Labs and test to ensure HSTS is properly enabled. If the SSL Labs site query comes back quickly and HSTS still says no, make sure you click ‘Clear cache’ so it re-runs the test.


Alternatively, you can test from the command line.

# curl -s -D- |grep -i "strict-"
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
# curl -s -D- |grep -i "strict-" 
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Neither of the http queries should return the header.

# curl -s -D- |grep -i "strict-"
# curl -s -D- |grep -i "strict-"

Going further

If you are really worried about security and https/HSTS, then I would strongly suggest you look at HSTS preloading. Preloading adds your site to a pre-installed “local” list where it is *not* dependent on the first visit as described above. Most of the major browsers such as Chrome, Firefox, and Edge support it. The website below does a fantastic job of preparing you for this change and understanding exactly what it encompasses.

HSTS preload website

Adding submitting, you will receive a “success” message back stating your website is pending approval in the HSTS preload list.

HSTS Preload Success

4 thoughts on “Adding HSTS To Your Website

  1. Great article!
    I especially like the functions.php solution, which I saw nowhere else. Do you believe it would be equally fast with the .htaccess solution?

    And how about the .htaccess for Nginx


    1. Thanks! The functions.php script is something I wrote as I worked through adding HSTS to WordPress sites. The error message about the unnecessary HSTS header over HTTP bugged me when I submitted sites for HSTS pre-loading. If you are working with high volume sites, I would definitely recommend adding the headers in the respective server configurations instead of in .htaccess or the functions.php as you will likely see a slight speed increase. I’ll add this recommendation to the write-up. Also, based on documentation from the website regarding .htaccess, “You can’t do this. You shouldn’t. If you need .htaccess, you’re probably doing it wrong.” 😉

Leave a Reply

Your email address will not be published. Required fields are marked *