Skip to main content
Test Double company logo
Services
Services Overview
Holistic software investment consulting
Software Delivery
Accelerate quality software development
Product Management
Launch modern product orgs
Legacy Modernization
Renovate legacy software systems
DevOps
Scale infrastructure smoothly
Upgrade Rails
Update Rails versions seamlessly
Technical Recruitment
Build tech & product teams
Technical Assessments
Uncover root causes & improvements
Case Studies
Solutions
Accelerate Quality Software
Software Delivery, DevOps, & Product Delivery
Maximize Software Investments
Product Performance, Product Scaling, & Technical Assessments
Future-Proof Innovative Software
Legacy Modernization, Product Transformation, Upgrade Rails, Technical Recruitment
About
About
What's a test double?
Approach
Meeting you where you are
Founder's Story
The origin of our mission
Culture
Culture & Careers
Double Agents decoded
Great Causes
Great code for great causes
EDI
Equity, diversity & inclusion
Insights
All Insights
Hot takes and tips for all things software
Leadership
Bold opinions and insights for tech leaders
Developer
Essential coding tutorials and tools
Product Manager
Practical advice for real-world challenges
Say Hello
Test Double logo
Menu
Services
BackGrid of dots icon
Services Overview
Holistic software investment consulting
Software Delivery
Accelerate quality software development
Product Management
Launch modern product orgs
Legacy Modernization
Renovate legacy software systems
Cycle icon
DevOps
Scale infrastructure smoothly
Upgrade Rails
Update Rails versions seamlessly
Technical Recruitment
Build tech & product teams
Technical Assessments
Uncover root causes & improvements
Case Studies
Solutions
Solutions
Accelerate Quality Software
Software Delivery, DevOps, & Product Delivery
Maximize Software Investments
Product Performance, Product Scaling, & Technical Assessments
Future-Proof Innovative Software
Legacy Modernization, Product Transformation, Upgrade Rails, Technical Recruitment
About
About
About
What's a test double?
Approach
Meeting you where you are
Founder's Story
The origin of our mission
Culture
Culture
Culture & Careers
Double Agents decoded
Great Causes
Great code for great causes
EDI
Equity, diversity & inclusion
Insights
Insights
All Insights
Hot takes and tips for all things software
Leadership
Bold opinions and insights for tech leaders
Developer
Essential coding tutorials and tools
Product Manager
Practical advice for real-world challenges
Say hello
Developers
Developers
Developers
DevOps & security

Deploy Ember app on AWS with SSL and CloudFront

Looking to secure your Ember app with SSL? Check out this step-by-step guide on deploying your Ember app on AWS using S3 and CloudFront. It's easier than you think!
Kevin Pfefferle
|
November 2, 2015
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

I am working on a side project in Ember, and I want to serve the application with SSL. This application will be interacting with 3rd party APIs and authenticating using 3rd party OAuth, so I want to serve it to users with HTTPS encryption.

I’ve been deploying the application on Heroku with heroku-buildpack-ember-cli. The Heroku approach is quick and easy to get up and running, but Heroku would charge $7/month to keep the application awake and $20/month to use SSL. I don’t want to spend $27/month on a side project if I don’t have to.

I’ve been taking a look at Amazon Web Services (AWS) as an alternative. I already pay AWS each month to host remote backups on S3, and I’ve used S3 and CloudFront before as a CDN for Rails application assets. Here are the steps I am taking to deploy my static Ember application on AWS:

Step 1: Deploy ember-cli to S3 with ember-cli-deploy

Create a bucket on S3

Most of the steps I’m following to set up AWS are well-documented:

  1. Open the AWS S3 Console
  2. Click Create a Bucket
  3. Set the Bucket Name. I’ve set mine to match the app subdomain I am using: app.[appdomain].com
  4. Select a Region close to the app’s expected users (for me, this is US Standard)
  5. Click Create

Edit bucket permissions

I need to edit the bucket permissions to allow public read access to the files that I upload:

  1.  Open the AWS S3 Console
  2.  Select the app.[appdomain].com bucket, click Properties, click Permissions, and click Add bucket policy
  3.  Copy and paste the following policy into the Bucket Policy Editor (change app.[appdomain].com to match the name of the bucket) then click Save
    {
      "Version":"2012-10-17",
      "Statement": [{
        "Sid": "Allow Public Access to All Objects",
        "Effect": "Allow",
        "Principal": "*",
        "Action": "s3:GetObject",
        "Resource": "arn:aws:s3:::app.[appdomain].com/*"
      }]
    }

Create AWS access keys

I need to create a set of access keys that allow upload access to S3:

  1.  Open the AWS IAM Console
  2.  Click Users, then click Create New Users
  3.  In box 1, type a name for the user (I used the name of my Ember app), then click Create
  4.  Click Show User Credentials and copy the Access Key ID and Secret Access Key into a file named .env.deploy.production in the root of the ember-cli app
    AWS_KEY=[Access Key ID]
    AWS_SECRET=[Secret Access Key]
    AWS_BUCKET=app.[appdomain].com
    AWS_REGION=us-east-1
  1.  Click close (and again to confirm) to return to the list of users
  2.  Click on the new user, click the Permissions tab, and click Attach Policy
  3.  Select the policy named AmazonS3FullAccess and click Attach Policy

Install the ember-cli-deploy addon

I’ve admired the ember-cli-deploy project from a distance since Luke Melia’s great talk on deploying Ember apps at EmberConf. This seems like a great chance to try it out:

$ ember install ember-cli-deploy

I’m going to deploy everything (including my index.html) to S3, so I’ve installed the following ember-cli-deploy plugins:

$ ember install ember-cli-deploy-build
$ ember install ember-cli-deploy-gzip
$ ember install ember-cli-deploy-manifest
$ ember install ember-cli-deploy-s3

I need to add the following configuration to config/deploy.js to load the variables that I set in .env.deploy.production as well as tell ember-cli-deploy to upload all files (including index.html):

ENV.s3 {
  accessKeyId: process.env.AWS_KEY,
  secretAccessKey: process.env.AWS_SECRET,
  bucket: process.env.AWS_BUCKET,
  region: process.env.AWS_REGION,
  filePattern: "*"
}

Now I can upload my Ember application build to S3 with one command:

$ ember deploy production

Enable static site hosting on S3

To use the application from S3, I need to enable static site hosting on my S3 bucket:

  1. Open the AWS S3 Console
  2. Select the app.[appdomain].com bucket, click Properties, then click Static Website Hosting
  3. Click Enable Website Hosting
  4. Set Index Document to index.html
  5. Click Save

Step 2: Distribute S3 assets via CloudFront

At this point, I could change my DNS settings to point app.[appdomain].com at the S3 bucket since it’s set up for static site hosting (and the bucket name matches the subdomain). However, there are two reasons that I want to distribute my Ember application through CloudFront instead. First, S3 does not support SSL for custom domains. Second, CloudFront gives my application assets the speed boost that comes with being distributed to and delivered from CloudFront’s edge locations around the world.

  1. Open the AWS CloudFront Console
  2. Under Web, click Get Started
  3. Fill Origin Domain Name with the S3 Hosting Endpoint (NOT the name of the bucket). This is the app.[appdomain].com.s3-website-us-east-1.amazonaws.com address that I was testing in the browser at the end of my S3 setup
  4. Leave most of the settings in this form set to their defaults, but set Default Root Object to index.html. This will load my application when I visit the CloudFront root path
  5. Click Create Distribution

Add CloudFront custom error response

  1. Open the AWS CloudFront Console
  2. Click on the [Distribution ID]
  3. Click the Error Pages tab
  4. Click Create Custom Error Response
  5. Set HTTP Error Code to 404: Not Found
  6. Under Customize Error Response, click Yes
  7. Set Response Page Path to /index.html
  8. Set HTTP Response Code to 200: OK
  9. Click Create

It takes up to 15 minutes to create the CloudFront distribution. Once the Status column in the CloudFront list switches from “In Progress” to “Deployed”, the distribution is complete. I visit the CloudFront domain name at [cloudfrontcode].cloudfront.net, and my Ember application works here just as it did at the S3 Endpoint.

Step 3: Use custom domain for CloudFront

Now that my Ember application is being served by CloudFront, I want to access it using app.[appdomain].com instead of the unattractive [cloudfrontcode].cloudfront.net:

  1. Open the AWS CloudFront Console
  2. Select the CloudFront distribution I just created, then click Distribution Settings
  3. On the General tab, click Edit
  4. In Alternate Domain Names (CNAMEs), enter the app.[appdomain].com custom domain that I want to use
  5. Click Yes, Edit to save this change

It takes some time for this change to take effect. Once again, I watch for the Status column to change from “In Progress” to “Deployed”. In the meantime, I set the DNS for app.[appdomain].com to point at CloudFront:

  1. Open the domain’s DNS settings (mine are managed on DNSimple)
  2. Create a CNAME record that sets app.[appdomain].com as an alias for the CloudFront distribution at [cloudfrontcode].cloudfront.net

I visit app.[appdomain].com, and I see my Ember application delivered via CloudFront.

Step 4: Add SSL to CloudFront

I finally am reaching my ultimate goal: serving my Ember application over SSL. First, I obtain an SSL certificate through AWS Certificate Manager:

  1. Open the AWS Certificate Manager Console
  2. Click Get started if no certificates exist or Request a certificate if there are existing certificates
  3. Under Domain name, enter the application subdomain app.[appdomain].com that will be used
  4. Click Review and request
  5. Review the domain name, then click Confirm and request
  6. Check the email address associated with the domain registration for a certificate approval email; in the email, click the link to Amazon Certificate Approvals
  7. On the approval page, click I Approve

I tell CloudFront to use the new SSL certificate for my custom CloudFront domain:

  1. Open the AWS CloudFront Console
  2. Select the CloudFront distribution, then click Distribution Settings
  3. On the General tab, click Edit
  4. Under SSL Certificate, choose Custom SSL Certificate (example.com)
  5. In the dropdown, I select the ACM certificate for app.[appdomain].com
  6. Under Custom SSL Client Support, make sure that Only Clients that Support Server Name Indication (SNI) is selected; this option supports all modern browsers and does not add to the cost of using CloudFront
  7. Click Yes, Edit to save this change

Once again, it takes CloudFront a short while to update this change throughout its network. Now that I am serving my Ember application over SSL, I want to be make HTTPS the default:

  1. Open the AWS CloudFront Console
  2. Select the CloudFront distribution, then click Distribution Settings
  3. Click the Behaviors tab, select the Default behavior, then click the Edit button
  4. Change the Viewer Pretocol Policy setting to Redirect HTTP to HTTPS
  5. Click Yes, Edit to save this change

After CloudFront updates this change through its network, anyone accessing my Ember application over HTTP is automatically redirected to the HTTPS version.

Step 5: Deploying future revisions

When I make changes to my Ember application that are ready to be deployed, I can easily deploy them with the ember-cli-deploy command:

$ ember deploy production

Fingerprinted assets like the app’s CSS and JavaScript have unique names, so I don’t worry about CloudFront caching for these objects. I do, however, need to invalidate the CloudFront cache for my index.html. I can do this with the AWS CLI (replace [distributionid] with the proper CloudFront ID):

// This first command only needs to be run once per aws-cli installation to enable the preview CloudFront commands
$ aws configure set preview.cloudfront true

$ aws cloudfront create-invalidation --distribution-id [distributionid] --invalidation-batch "{\"CallerReference\": \"$(uuidgen)\", \"Paths\":{\"Quantity\":1,\"Items\":[\"/index.html\"]}}"

[Note: This command assumes that your aws-cli user has CloudFront permissions.]

Next steps

  • I really don’t like having to run that ugly CLI command at the end to invalidate my index.html, so I’m working on an ember-cli-deploy plugin to automate this step
  • Once I’ve got the CloudFront invalidation step automated, I plan on creating an ember-cli-deploy plugin pack that contains all of the plugins needed for this deployment strategy

‍

UPDATE (11/10/2015): These two enhancements are now available!

UPDATE (2/9/2016): Updated this post to use CloudFront custom error pages instead of S3 routing rules to handle loading non-root URLs without a hash-based redirect

UPDATE (2/19/2016): Updated this post to use AWS Certificate Manager to obtain an SSL certificate for CloudFront

Related Insights

🔗
A practical guide to AWS Lambda and serverless
🔗
How to set up Rails app on AWS Elastic Beanstalk
🔗
DevOps best practices using AWS and Terraform

Explore our insights

See all insights
Leadership
Leadership
Leadership
The business of AI: Solve real problems for real people

After participating in the Perplexity AI Business Fellowship, one thing became clear: the AI hype cycle is missing the business fundamentals. Here are 3 evidence-based insights from practitioners actually building or investing in AI solutions that solve real problems.

by
Cathy Colliver
Leadership
Leadership
Leadership
Pragmatic approaches to agentic coding for engineering leaders

Discover essential practices for AI agentic coding to enhance your team’s AI development learning and adoption, while avoiding common pitfalls of vibe coding.

by
A.J. Hekman
by
Aaron Gough
by
Alex Martin
by
Dave Mosher
by
David Lewis
Developers
Developers
Developers
16 things software developers believe, per a Justin Searls survey

Ruby on Rails developer Justin Searls made a personality quiz, and more than 7,000 software developers filled it out. Here's what it revealed.

by
Justin Searls
Letter art spelling out NEAT

Join the conversation

Technology is a means to an end: answers to very human questions. That’s why we created a community for developers and product managers.

Explore the community
Test Double Executive Leadership Team

Learn about our team

Like what we have to say about building great software and great teams?

Get to know us
Test Double company logo
Improving the way the world builds software.
What we do
Services OverviewSoftware DeliveryProduct ManagementLegacy ModernizationDevOpsUpgrade RailsTechnical RecruitmentTechnical Assessments
Who WE ARE
About UsCulture & CareersGreat CausesEDIOur TeamContact UsNews & AwardsN.E.A.T.
Resources
Case StudiesAll InsightsLeadership InsightsDeveloper InsightsProduct InsightsPairing & Office Hours
NEWSLETTER
Sign up hear about our latest innovations.
Your email has been added!
Oops! Something went wrong while submitting the form.
Standard Ruby badge
614.349.4279hello@testdouble.com
Privacy Policy
© 2020 Test Double. All Rights Reserved.