Deploy your AngularJS app to AWS S3 with SSL

It was some time ago that we needed to provide an AngularJS webpage. Our first approach was to make a deploy to Heroku using a Node JS server. It worked for some time but the setup had not the greatest outcomes as there were a few memory issues with the server when trying to scale the app. We also had issues every time we wanted to install the node dependencies in the server. Most of them were cached, but quite frequently when we wanted to deploy a new node package, the connection to the node providers failed, which was very frustrating to say the least. We heard a few times that some people uploaded to the server the whole node_modules folder with all the dependencies already downloaded. That could be a solution but proved to have many issues. For example:

  • Every time someone clones the project. They have gigas of code to download.
  • Pull requests on Github could end up being quite annoying every time someone changes a library version or adds a new one.
  • Good luck if you have a conflict in your code because of a change in a library

…and I’m pretty sure I could continue adding cons for a while.

We tried to think about other solutions and so we went back to the basics, providing a static Angular JS app. We came up with several solutions but we were pretty confident we could achieve a combination of Amazon S3, some gulp tasks and CloudFront for managing CDN and SSL.

So I will give you the details in the same order we made them:

  1. Create Gulp tasks
  2. Amazon S3 Configuration
  3. Upload a Certificate
  4. CloudFront Configuration
See also: Dynamic environments for your gulp tasks

1. Gulp Tasks

Gulp allows you to create tasks for different things in a simple way. Some tasks could be:

  • Precompile assets
  • Integrate your code with CI

And so on…

So we needed something like this to generate tasks that prepare our code for deploy.

First we added a gulp task to publish our files to aws.

The code is quite simple. First we get all the sensitive data from another script, that you’ll see below, and then we created a new task using the Gulp AWSPublish plugin. The buildSrc is the path where we have all our precompiled files. The build:production tasks precompiles all the necessary files we need.

The sensitive data is exported like this:

Don’t forget to add this file to the .gitignore to avoid exposing your sensitive data.

You can see more of our tasks in our public frontend-bootstrap for angular here. Enjoy!

See also: Building Apps with Parse BaaS

2. Amazon S3 Configuration

We used Amazon S3 to host the precompiled files we got from the gulp tasks above. To continue with this section, you will need to create an S3 Bucket. That’s quite simple, just provide a name and a region of your choice. After this simple setup, comes the fun part:

The first issue we faced after having all the files in S3 was getting rid of the # in the url that Angular provides. We hate it, so we found a workaround for this. In the AngularJS code you achieve this by adding the following line to a config file:


Then go back to the S3 bucket you just created, select the Properties Tab and then in the Static Website Hosting check the Enable website Hosting and add the following Redirection Rules:

Where your-app-dns is the URL you choose for your app.

This rule will redirect all those requests that go to invalid urls to the root of our app.

Then we need to edit the permissions rules. Go to the Permissions tab in properties and leave it like this:

And in that same view go to Edit the Bucket Policy and add the following:

Where bucket-name is the bucket name you choose before, not the url!.

You can read more information about all of that here

Now if you go to the Endpoint url that you can find in the Static Website Hosting tab you will see your AngularJS app working like a charm! Well done!

Now we are missing two more things to have everything working:

  • Upload a certificate for SSL
  • Setup CDN
See also: Image Processing in Rails using AWS Lambda

3. Upload a certificate

For our https connection to work we need to setup our certificate.

Amazon provides us a service called IAM (Identity and Access Management) to set up this easily. To start, you need to install the command line interface. You can read more about this here.

Once you manage to have IAM working you need to upload your certificate following the script below and you are done!

The script contemplates chained certificates and when you are done, your certificate should be available for CloudFront.

See also: Dynamic environments for your gulp tasks

4. CloudFront Configuration

Why do we need CloudFront? It’s the only way to have our https connection working with the S3 bucket. For this we need to create a CloudFront distribution:

Go to the CloudFront Service. Then click on Create Distribution and select the Web option. This will open a huge form with lots of things. Set the followings values and leave all the other ones with their defaults:

  • Origin Domain Name: You Static Website Hosting Endpoint. Example:
  • Viewer Protocol Policy: Redirect HTTP to HTTPS
  • Forward Query Strings: Yes
  • Price Class: Choose the one that best suites you according to latency and costs.
  • SSL Certificate: Check “Custom SSL Certificate” and select your previously uploaded certificate.

Take into account that you are using a CDN now and newly deployed files won’t change unless you invalidate them. You can read more about this here.

To make those invalidations automatically, we use the s3_website gem that works perfectly.

If you are using Route 53, select the A — IPv4 Address type and in Alias Target select the cloudfront distribution we created before and we are done! Everything should be working!

Wait a little bit until everything propagates and your app should be working with https. So next time you need to make a deploy use the gulp tasks, the s3_website gem, wait until propagates and that’s it!

At Wolox, we love finding new tools and ways to make our products even better. Stay tuned for new AngularJS posts!

Posted by Esteban Pintos (