Configuration Tutorial: Hosting an Ember App on S3 and CloudFront

iRonin IT Team - Experts in software development
devops, web, ember, javascript

You have your Ember web app. You know you want to use CloudFront for your CDN and S3 for storage. But how do you put all the pieces together? This article from our DevOps experts guides you through all the code and commands necessary for configuration and deployment.

When your web application or website goes live you want it to perform well, load quickly and operate in the manner expected by your visitors. This can all be possible with the combination of Ember, Amazon S3, and the CloudFront CDN.

In this post we will show you how you how to host an Ember application on Amazon S3 with Amazon’s CloudFront CDN in front of it, as part of your DevOps configuration. Ember is a JavaScript framework that’s used in projects worldwide and as a fully featured framework contains all the elements necessary for developers to ship new features quickly. Amazon S3 is Amazon’s cloud storage and their CloudFront CDN allows you to distribute your web app over servers around the world to give your visitors the speediest, smoothest web experience available. You can do this by choosing server locations closest to your visitors - which we set up in this tutorial. For the speediest serving, all static assets(JavaScript, CSS, image files) should be cached (by using long TTL) so on their next visit these elements will be served directly from the disk.

In short, this Ember.js hosting configuration will allow you to serve your Ember-crafted content in a fast, secure manner worldwide.

Note: For the purposes of this article, we are going to assume that your app uses ember-cli.

Let’s get started using CDN with Ember.js!

Application configuration

You need to install ember-cli-deploy with a few additional add-ons for deploying to S3:

ember install ember-cli-deploy
ember install ember-cli-deploy-build
ember install ember-cli-deploy-display-revisions
ember install ember-cli-deploy-revision-data
ember install ember-cli-deploy-s3
ember install ember-cli-deploy-s3-index
ember install ember-cli-deploy-manifest
ember install ember-cli-deploy-gzip

As a bit of a background, ember-cli-deploy is base skeleton to customize deployment, with additional add-ons like build (to build the app), s3 (to push app to S3) and s3-index (to create versionized index.html files).

display-revisions and revision-data are required dependencies for s3-index. ember-cli-deploy-manifest will allow us to upload only those files that have changed since our last deployment (differential upload) and ember-cli-deploy-gzip will make sure our assets are compressed.

Now we need to the create configuration file for deployment:

// config/deploy.js
module.exports = function(deployTarget) {
  var ENV = {
    pipeline: {
      activateOnDeploy: true
    }
  };

  ENV.cloudfront = {
    accessKeyId: 'AWS_ACCESS_KEY',
    secretAccessKey: 'AWS_SECRET_KEY',
    distribution: 'CLOUDFRONT_DISTRIBUTION_ID'
  };

  ENV['s3'] = {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
    bucket: 'my-ember-app',
    region: 'us-east-1'
  };

  ENV['s3-index'] = {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
    bucket: 'my-ember-app',
    region: 'us-east-1'
  };
  return ENV;
};

Note: Even if the settings for s3 and s3-index are the same, do not assign them to the same JavaScript object - it will produce an error which will be difficult to trace (GitHub issue).

If you need to support additional environments (like staging) add them to the config/deploy.js file as well:

if (deployTarget === 'staging') {
  ENV.build.environment = 'staging';
  ENV.s3.bucket = ENV['s3-index'].bucket = 'my-ember-staging-app';
  ENV.s3.region = ENV['s3-index'].region = 'us-east-2';
  ENV.cloudfront.distribution = 'CLOUDFRONT_STAGING_DISTRIBUTION_ID';
}

if (deployTarget === 'production') {
  ENV.build.environment = 'production';
  ENV.s3.bucket = ENV['s3-index'].bucket = 'my-ember-prod-app';
  ENV.s3.region = ENV['s3-index'].region = 'us-east-1';
  ENV.cloudfront.distribution = 'CLOUDFRONT_PRODUCTION_DISTRIBUTION_ID';
}

Now if you run ember deploy {production|staging}, your app will be built and pushed to your S3 bucket.

S3 bucket configuration

Add the following policy and CORS configuration for your bucket:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AddPerm",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::my-ember-app/*"
        }
    ]
}
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>http://www.my-ember-app.com</AllowedOrigin>
        <AllowedOrigin>https://www.my-ember-app.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>HEAD</AllowedMethod>
    </CORSRule>
</CORSConfiguration>

Remember to replace http://www.my-ember-app.com and https://www.my-ember-app.com with your own domain.

Also turn on Static Website Hosting and provide index.html as Index Document.

Using history location

If your app uses history-api for nice urls, you will need additional configuration for your S3 bucket:

  1. Set index.html as Error Document in Static Website Hosting
  2. Add the following Redirection Rules:
<RoutingRules>
    <RoutingRule>
        <Condition>
            <HttpErrorCodeReturnedEquals>403</HttpErrorCodeReturnedEquals>
        </Condition>
        <Redirect>
            <HostName>www.my-ember-app.com</HostName>
            <ReplaceKeyPrefixWith>#/</ReplaceKeyPrefixWith>
        </Redirect>
    </RoutingRule>
</RoutingRules>

The above redirect rules are not necessary if you are going to use the app via CloudFront only. However for some environments i.e. preview, you might not need CloudFront and access via direct a S3 link is more than enough.

Deploy user configuration

Below you can find a minimal policy that will allow your AWS user to deploy files to the previously created S3 bucket:

{
    "Statement": [
        {
            "Action": [
                "s3:ListAllMyBuckets",
                "s3:GetBucketLocation"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:PutObjectACL"
            ],
            "Resource": [
                "arn:aws:s3:::my-ember-app/*"
            ]
        }
    ]
}

Ember.js on CloudFront configuration

  1. Create a CloudFront distribution with your bucket s3 endpoint as an origin and index.html as Default Root Object. It’s very important to use the endpoint instead of the bucket name i.e. your-bucket-name.s3-website-us-west-2.amazonaws.com - otherwise you can receive 403 errors when you try reload the page.
  2. In the Alternate Domain Names (CNAMEs) field, provide the domain you will use for your app.
  3. Create a Custom Error Response in your Error Pages (inside Distribution ID settings):
    1. HTTP Error Code: 404: Not Found
    2. Customized Error Response: Yes
    3. Response Page Path: /index.html
    4. HTTP Response Code: 200: OK
  4. Point your subdomain to Domain Name value from the CloudFront page (as CNAME)

Now your configuration should be ready and the app will respond under your domain name after deployment.

Deployment

To deploy your Ember app on S3 simply run the ember deploy production command.

Other useful commands

Here are a few extra commands that you may find useful:

// Deploy
ember deploy staging
ember deploy production

// List available revisions
ember deploy:list staging
ember deploy:list production

// Activate revision manually
ember deploy:activate staging --revision xyz
ember deploy:activate production --revision xyz

If you would like to see more info about the deployment process pass the --verbose flag to the command, i.e. ember deploy staging --verbose.

We help companies all over the world with managing and deploying their web applications in the most efficient and effective ways - utilizing the best in breed cloud services, including Amazon’s suite of platforms. We also offer custom web application in Ember and JavaScript, along with a host of other technologies. Could your business benefit from more stable, dynamic software or more frictionless infrastructure? Contact our team to find out how iRonin can help to supercharge your ongoing and new projects.

Author's Bio
iRonin IT Team

Experts in software development

We are a 100% remote team of software development experts, providing web & mobile application development and DevOps services for international clients.

Similar articles
Comments

Bulletproof your development with remote team augmentation

Read how
This page is best viewed in portrait mode
Our websites and web services use cookies. We use cookies and collected data to enhance your experience, provide additional communication channels, improve marketing materials and enhance our offer. IRONIN SP. Z O.O. SP. K. is committed to protecting all the data that we collect or process in any way, especially data of personal nature. By accepting these terms you agree to our usage of cookies and processing your data, according to our Privacy Policy, and you declare that your browser settings reflect your preferences. Read more You have the right to revoke this agreement at any time, based on the terms of our Privacy Policy. You can change cookies settings in your browser. If you do not agree with us using cookies and processing your data, please change your cookies settings in your web browser and reject these terms. You can find more information about cookies, your data privacy This site uses cookies. By continuing to browse the site, you are agreeing to our use of cookies. data processing, and your rights in our Privacy Policy.