Implementing SSL on Amazon S3 Static Websites

Since this post was written, Amazon has launched AWS Certificate Manager, which provides certificates at no cost and substantially simplifies managing them for use in the AWS context. We recommend that readers investigate the AWS Certificate Manager product before following the guidance in this post.

Every day, more and more websites are serving their pages using HTTPS. This can lead to warnings or complete failures when those sites want to embed content from other sites. Until recently, that included embedding work created with Knight Lab's TimelineJS and StoryMapJS. We recently implemented HTTPS to solve this problem, but it was less straightforward than we would have liked. Hopefully this guide will help others who are trying to do the same.


Many of Knight Lab's sites, including the CDN which serves our publishing tools, are served as static websites using Amazon's S3 service. Amazon S3 has always supported SSL using the domain name (e.g., However, using that means that if we ever wanted to switch away from Amazon for the service, pages using those URLs would break.

It would be better to use a custom domain name — to serve pages from — so that we could move that service if we ever want to. Until recently, setting this up involved a $600/month fee for a dedicated IP address. Last year, Amazon added the ability to use your own SSL certificates with Amazon CloudFront at no additional charge with Server Name Indication (SNI). While Amazon's guides to SSL for S3 mention that SNI is not universally supported in browsers, it is so widely supported that we saw no reason for concern.

Making it happen

There are five basic steps. Some of them get a little involved.

  1. Obtain an SSL certificate
  2. Upload your SSL certificate
  3. Configure your S3 bucket
  4. Create a CloudFront "Web" distribution
  5. Point your domain name to the CloudFront domain name.

Obtain an SSL certificate

Some of these details will vary based on the certificate authority you choose for your SSL certificate. Generally, the cost for certificates varies based on the strength of encryption and the lengths to which the authority goes to verify details about the organization making the request. Since we don't conduct e-commerce or handle highly sensitive data, we chose a relatively inexpensive option: we purchased a PostiveSSL Wildcard SSL certificate from Namecheap. ("Wildcard" means we can use a single certificate to secure multiple subdomain names.)

No matter which authority you choose, you must generate a Certificate Signing Request (CSR). This request is a formal way of indicating that your organization controls the domain name for the site where the certificate will be installed. We followed these directions for generating a new private key and a CSR using OpenSSL. You would want to replace domain_com with something that is relevant to you and helps you manage these files.

openssl req -nodes -newkey rsa:2048 -keyout domain_com.key -out domain_com.csr

Once you have a CSR, you must submit it to the authority to have it signed. For Namecheap, go through the purchasing process, and then go to your SSL Certificates list page. Click the "Activate Now" link next to your certificate. Select "Apache + OpenSSL" and paste the contents of the CSR file you generated. You will receive an email with a link to approve the certificate.

After approval, you will get another email with a zip attachment containing your four certificate files. The name of the last file will be different based on the name of the file you uploaded in the previous step.

  • AddTrustExternalCARoot.crt (Root CA Certificate)
  • COMODORSAAddTrustCA.crt (Intermediate CA Certificate)
  • COMODORSADomainValidationSecureServerCA.crt (Intermediate CA Certificate)
  • STAR_domain_com.crt (PositiveSSL Wildcard Certificate)

These four SSL certificates, from the root certificate to the end-user certificate, represent the SSL certificate chain. You must bundle the intermediate and root certificates and install them along with your end-user certificate.

Create the bundle by combining the root and intermediate .crt files into a single file. The order of concatenation is important:

cat COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt AddTrustExternalCARoot.crt >

Upload your SSL certificate to AWS IAM

To use your SSL certificate with CloudFront, you need to upload it to AWS IAM, which must be done using the AWS Command Line Interface tools. I already had Python 2.7 and pip installed, so I installed the tools using pip:

sudo pip install awscli

and configured the tools using the configure command:

aws configure

Then, upload your certificate:

aws iam upload-server-certificate \
--server-certificate-name \
--certificate-body file://STAR_domain_com.crt \
--private-key file://domain_com.key \
--certificate-chain file:// \
--path /cloudfront/

For more information about each parameter, run:

aws iam upload-server-certificate help

Configure your bucket

You need to set a policy on your S3 bucket so that CloudFront can read the content. In the S3 Management Console, select the bucket and open the Properties tab.

Amazon AWS console for configuring bucket properties.

Under Permissions, click "Add bucket policy". Enter the following policy (changing "your-bucket-name" to the name of your bucket) and save it.

"Principal": {
"AWS": "*"

While you're here, make a note of the "Endpoint" listed under the "Static Website Hosting" section. You will need this to set the origin for your CloudFront distribution.

Create a CloudFront "Web" distribution

Before creating your CloudFront distribution, you need to decide how long you want your objects to stay in the CloudFront cache before CloudFront forwards a request to your origin. You have many options.

Since we update our origins fairly often and want those changes to become effective within a short period of time, we decided to control caching using Cache-Control headers on our S3 objects.

  • Origin Domain Name = the bucket endpoint listed under "Static Web Hosting" in S3.
  • Origin Protocol Policy = HTTP Only. This specifies how CloudFront will contact your S3 website, and S3 website hosting only supports serving content over HTTP.
  • Viewer Protocol Policy = HTTP and HTTPS - we didn't want existing HTTP links to break
  • Forward Headers = Since we need CORS support, we whitelisted the "Origin" header.
  • Object Caching = Use Origin Cache Headers. This is where the decision on your cache policy comes into play.
  • Alternate Domain Names (CNAMEs) = Enter the domain name(s) that people will actually use to visit your website (e.g.
  • SSL Certificate = Chose "Custom SSL Certificate", and then select the certificate that you uploaded to IAM.
  • Custom SSL Client Support = Only Clients that Support Server Name Indication (SNI)
  • Default Root Object = index.html

Create the distribution and wait until the Status column shows it is deployed. It took up to 30 minutes for each of our distributions to be created.

Point your domain name to the CloudFront domain name

After it is deployed, the distribution info will list a domain name (e.g. You will need to point your human-friendly domain name to this domain name (e.g. create a CNAME record in Route53 for

Latest Posts

  • Introducing StorylineJS

    Today we're excited to release a new tool for storytellers.

    StorylineJS makes it easy to tell the story behind a dataset, without the need for programming or data visualization expertise. Just upload your data to Google Sheets, add two columns, and fill in the story on the rows you want to highlight. Set a few configuration options and you have an annotated chart, ready to embed on your website. (And did we mention, it looks great on phones?) As with all of our tools, simplicity...

    Continue Reading

  • Join us in October: NU hosts the Computation + Journalism 2017 symposium

    An exciting lineup of researchers, technologists and journalists will convene in October for Computation + Journalism Symposium 2017 at Northwestern University. Register now and book your hotel rooms for the event, which will take place on Friday, Oct. 13, and Saturday, Oct. 14 in Evanston, IL. Hotel room blocks near campus are filling up fast! Speakers will include: Ashwin Ram, who heads research and development for Amazon’s Alexa artificial intelligence (AI) agent, which powers the...

    Continue Reading

  • Bringing Historical Data to Census Reporter

    A Visualization and Research Review

    An Introduction Since Census Reporter’s launch in 2014, one of our most requested features has been the option to see historic census data. Journalists of all backgrounds have asked for a simplified way to get the long-term values they need from Census Reporter, whether it’s through our data section or directly from individual profile pages. Over the past few months I’ve been working to make that a reality. With invaluable feedback from many of you,......

    Continue Reading

  • How We Brought A Chatbot To Life

    Best Practice Guide

    A chatbot creates a unique user experience with many benefits. It gives the audience an opportunity to ask questions and get to know more about your organization. It allows you to collect valuable information from the audience. It can increase interaction time on your site. Bot prototype In the spring of 2017, our Knight Lab team examined the conversational user interface of Public Good Software’s chatbot, which is a chat-widget embedded within media partner sites.......

    Continue Reading

  • Stitching 360° Video

    For the time-being, footage filmed on most 360° cameras cannot be directly edited and uploaded for viewing immediately after capture. Different cameras have different methods of outputting footage, but usually each camera lens corresponds to a separate video file. These video files must be combined using “video stitching” software on a computer or phone before the video becomes one connected, viewable video. Garmin and other companies have recently demonstrated interest in creating cameras that stitch......

    Continue Reading

  • Publishing your 360° content

    Publishing can be confusing for aspiring 360° video storytellers. The lack of public information on platform viewership makes it nearly impossible to know where you can best reach your intended viewers, or even how much time and effort to devote to the creation of VR content. Numbers are hard to come by, but were more available in the beginning of 2016. At the time, most viewers encountered 360° video on Facebook. In February 2016, Facebook......

    Continue Reading

Storytelling Tools

We build easy-to-use tools that can help you tell better stories.

View More