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

  • Prototyping Augmented Reality

    Something that really frustrates me is that, while I’m excited about the potential AR has for storytelling, I don’t feel like I have really great AR experiences that I can point people to. We know that AR is great for taking a selfie with a Pikachu and it’s pretty good at measuring spaces (as long as your room is really well lit and your phone is fully charged) but beyond that, we’re really still figuring...

    Continue Reading

  • Capturing the Soundfield: Recording Ambisonics for VR

    When building experiences in virtual reality we’re confronted with the challenge of mimicking how sounds hit us in the real world from all directions. One useful tool for us to attempt this mimicry is called a soundfield microphone. We tested one of these microphones to explore how audio plays into building immersive experiences for virtual reality. Approaching ambisonics with the soundfield microphone has become popular in development for VR particularly for 360 videos. With it,...

    Continue Reading

  • How to translate live-spoken human words into computer “truth”

    Our Knight Lab team spent three months in Winter 2018 exploring how to combine various technologies to capture, interpret, and fact check live broadcasts from television news stations, using Amazon’s Alexa personal assistant device as a low-friction way to initiate the process. The ultimate goal was to build an Alexa skill that could be its own form of live, automated fact-checking: cross-referencing a statement from a politician or otherwise newsworthy figure against previously fact-checked statements......

    Continue Reading

  • Northwestern is hiring a CS + Journalism professor

    Work with us at the intersection of media, technology and design.

    Are you interested in working with journalism and computer science students to build innovative media tools, products and apps? Would you like to teach the next generation of media innovators? Do you have a track record building technologies for journalists, publishers, storytellers or media consumers? Northwestern University is recruiting for an assistant or associate professor for computer science AND journalism, who will share an appointment in the Medill School of Journalism and the McCormick School...

    Continue Reading

  • 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

Storytelling Tools

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

View More