I was recently researching static / serverless website hosting options for my current site and wanted to share my notes. I've always been an S3 kind of guy (many of my current projects, including Maru, use S3), so this guide will focus on options to get S3 set up with HTTPS.

Background: Why Go Static?

Static websites offer a number of key advantages over traditional dynamic websites:

  • They are more secure (there are fewer moving parts on the server-side)
  • They are fast because pages are pre-rendered (think compiled vs. interpreted languages) and they scale well (stateless systems like static files scale horizontally with no effort)
  • They are cheap to host (no application servers, databases, etc.)
  • They are simple (just deploy static files)

Of course, the downside is that not all apps are suitable for a purely static approach. But I would argue that even when you have a truly dynamic app, you can neatly separate the dynamic modules into backend APIs that can be called by client-site scripts shipped with your static frontend—so you still have a static part of your system that can benefit from the advantages above.

Basics

One more thing: before we start, so we're on the same page, let's break down the pieces we need to get a static website over HTTPS up and running:

  1. A domain name registrar for managing your custom domain
  2. A host for your content
  3. A certificate authority (CA) to issue your SSL/TLS certificate for HTTPS
  4. (optional) A content delivery network (CDN) to cache your content

We will focus on the host and CDN for this guide because—as you will see shortly—S3 is closely tied with Amazon CloudFront, AWS's CDN offering.

S3

.--------------.   
| viewer       |   
'--------------'   
             | HTTP
        .----|-.   
        | S3 x |   
        '------'   

You can't go wrong with the tried-and-true S3 bucket.

It's as simple as uploading your website content to an S3 bucket, marking your objects world-readable, and enabling static website hosting. S3 will act like your web server and serve your bucket content in response to HTTP requests.

The static bucket endpoints are a great option for quick prototypes, and you can easily use a custom domain by creating a CNAME record in your DNS setup that points to your static bucket endpoint.

One big problem though: a pure S3 approach does not support HTTPS; for that, we need to throw in Amazon CloudFront.

S3 + CloudFront

.--------------.    
| viewer       |    
'--------------'    
             | HTTPS
.------------|-.    
| CloudFront | |    
'--------------'    
             | HTTPS
        .----|-.    
        | S3 x |    
        '------'    

You can use Amazon's CloudFront CDN in front of your S3 bucket to enable HTTPS. You will need to upload a SSL/TLS certificate from your CA of choice [1]. This is the way to go for hosting a static website out of S3 securely.

As mentioned previously, S3 does not support HTTPS when configured as a simple static bucket endpoint, so you'll need to turn off static website hosting to enforce HTTPS to your origin S3 bucket.

There are some nuances to be aware of when you take this approach. Since CloudFront sits in between the viewer and your S3 bucket, there are two SSL/TLS negotiations that have to happen with this stack:

  1. The viewer requests content from CloudFront over HTTPS.
  2. If CloudFront has the content in it's cache, CloudFront immediately satisfies the HTTPS request using the SSL/TLS certificate you uploaded.
  3. If CloudFront does not have the content in it's cache, CloudFront requests the content from your origin S3 bucket over HTTPS using Amazon S3's own SSL/TLS certificate, adds the content to the CloudFront cache, and returns the content to the viewer.

S3 + Cloudflare (or some other CDN)

.--------------.    
| viewer       |    
'--------------'    
             | HTTPS
.------------|-.    
| Cloudflare | |    
'--------------'    
             |  HTTP
        .----|-.    
        | S3 x |    
        '------'    

You could decide that you want to use an alternative CDN to CloudFront in front of S3.

For instance, I've been seeing a lot of recommendations in the hackersphere for using the Cloudflare CDN in front of S3—probably because Cloudflare offers a generous free tier with unlimited domains, and features a one-click shared SSL/TLS certificate that works with S3 buckets configured for static hosting called "Flexible SSL".

The problem is, "Flexible SSL" isn't really secure—connections from Cloudflare to your S3 bucket are over normal HTTP. This can be misleading since a viewer may think your site is secure, when it really isn't [2].

Remember, S3 in static web hosting mode does not support HTTPS, so whichever CDN you use, you will be limited to HTTP requests back to your S3 origin...unless you stack on CloudFront.

S3 + CloudFront + Cloudflare (or some other CDN)

.--------------.    
| viewer       |    
'--------------'    
             | HTTPS
.------------|-.    
| Cloudflare | |    
'--------------'    
             | HTTPS
.------------|-.    
| CloudFront | |    
'--------------'    
             | HTTPS
        .----|-.    
        | S3 x |    
        '------'    

All is not lost if you really want to use Cloudflare—or any other CDN for that matter—with S3 securely; just use the S3 + CloudFront stack.

Cloudflare, for example, does offer a "Full SSL (Strict)" option that really is secure that you should be able to get working with the S3 + CloudFront stack [3]. Note that you will have back-to-back CDNs, which seems somewhat silly for most sites.

Beyond S3

Although I focused on S3, the hosting landscape has evolved significantly in the past few years and there's quite a few more options to choose from now. Here are some alternatives that are worth considering [4]:

The list of providers continues to grow as serverless stacks become more popular. It looks like static web hosting will soon become—if it isn't already—a commodity.


Footnotes

  1. Since you're already using AWS, you can easily use AWS Certificate Manager to issue a free certificate.
  2. I wonder how many "HTTPS" websites out in the wild are using this setup because it's easy to get working?
  3. See this blog post for example.
  4. I actually switched my website over to GitHub Pages now because it is free and offers painless HTTPS for custom domains with Let's Encrypt.