Skip to content

Instantly share code, notes, and snippets.

@IanVS
Last active August 29, 2015 14:24
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save IanVS/1b8e5c37f2430ed77a2b to your computer and use it in GitHub Desktop.
SANE Deployment Strategies

SANE deployment

You’ve created a web app using the SANE stack (using an Ember.js client and a Sails.js API), and now you’re ready to get it out there for the world to see. There are many ways to handle deployments, with varying complexity and tradeoffs. This series of posts will present a few of those methods, with increasing levels of complexity, for deploying your app to AWS. There are many options of where to deploy your app, including Heroku, Firebase, DigitalOcean, AWS, and others. I’ve chosen to use AWS as it is currently the largest and most well-known.

Setting up a single EC2 Instance

When your app is young and you have between 0 and 100 users, it makes sense to keep the architecture as simple as possible. This means running all the pieces of your app (web server, database, API server, etc.) on a single EC2 instance.

Step 1: Choose and Create EC2 Instance

The first thing to do is pick out a base image to use for your instance. As of July, 2015, the image I’ve chosen to use is “Ubuntu Trusty 14.04 LTS hvm (x64)” with SSD disk storage. You can use http://cloud-images.ubuntu.com/locator/ec2/ to find the image you want to use, which will depend on your region. I’m in us-east-1, so I will use "ami-c135f3aa". This isn’t intended to be an in-depth guide on AWS itself, so I won’t get into the step-by-step of how to create the instance, but there are plenty of resources out there to take you through that process.

Step 2: Configure

Once your EC2 instance is up and running, you will need to SSH in so that you can make some changes. In more advanced methods, you will never need to manually log in to an individual instance, but that will come later. After you are logged in, perform the following actions:

  1. Update apt-get repository and installed packages
sudo apt-get update
sudo apt-get -y upgrade
  1. Install node

There are many ways to install node.js on a system. Feel free to use whatever way you are comfortable with. The simplest and quickest way I have found is with using Nave from Isaac Schlueter. The method below will take ownership of some directories in /usr/local, which is fine as long as you don't plan to run the EC2 instance with a user other than the default ubuntu. It will install the latest stable version of node.js, but you may also specify a version in place of stable on the last line.

mkdir ~/.nave
cd ~/.nave
wget http://github.com/isaacs/nave/raw/master/nave.sh
chmod u+x nave.sh
sudo ln -s $PWD/nave.sh /usr/local/bin/nave
sudo mkdir -p /usr/local/{share/man,bin,lib/node,lib/node_modules,include/node}
sudo chown -R $USER /usr/local/{share/man,bin,lib/node,lib/node_modules,include/node}
nave usemain stable

To verify node installed correctly, use node --version

  1. Install NPM
wget -O - http://npmjs.com/install.sh | sh
  1. Install Ember, Sails, and other dependencies and tools
npm i -g sails
npm i -g ember-cli
npm i -g bower
npm i -g pm2

sudo apt-get install -y git

Additionally, you will need to install the database you are using (MySQL, PostgreSQL, MongoDB, etc.), as well as any other packages you may need like make and g++.

Step 3: Deploy App Code

Now that your EC2 instance is set up with the necessary environment, you need some way to get your application code to the server. There are many ways to do this, and I will be exploring other methods in future posts, but as a simple first step you can just clone it from your git repository. In this section, that's what we will do, and we will get the application to the point where it is ready to start.

  1. Clone project into a directory
cd ~
git clone <git repo url>
  1. Install project dependencies

If you've gotten to the point of deploying your app, you likely know how all this goes, but I'm including it here for the sake of completeness. Assuming you use the default SANE structure of using client and server directories, it will look like this:

cd <project-dir>
npm i
cd server
npm i
cd ../client
bower install
npm i
  1. Build your ember app for production

You now need to run your Ember app through a production build to concatenate, minify, etc. From the client directory, run:

ember build --environment=production --output-path=../server/assets/

This will replace the default index.html which Sails comes with, so that users will get the Ember app instead.

Start the App

The EC2 box is built, the application code is deployed, and now we are ready to fire it up. As always, there is a little yak shaving to get out of the way first.

  1. Allow Node to listen on low ports

In Linux systems, root permissions are usually required in order for a process to listen on a port below 1024. We want our web app to listen on port 80 (HTTP) and possibly 443 (SSL), so we will need to make some changes. There are two main ways to handle this. The most robust is to add a web server like Nginx as a reverse proxy which forwards requests to the Node.js app. I'll cover that in a future blog post, but in the interest of keeping things simple for now, we will just give the sails app permissions to listen on low ports.

sudo apt-get install -y libcap2-bin
sudo setcap cap_net_bind_service=+ep /usr/local/bin/node

See http://technosophos.com/2012/12/17/run-nodejs-apps-low-ports-without-running-root.html for more details on what we're doing here.

  1. Start App

You could just start your Sails app in production mode at this point, and you would have a working app. However, if it ever died for some reason, your site would go down and you would manually have to start it back up. Ain't nobody got time for that, so we are going to use PM2 instead. From within your server directory:

pm2 start app.js -- --prod

Notice the two sets of double dashes. The sails option for production is --prod, but in order for pm2 to pass arguments to the app, you need another set of --.

  1. Start App on server boot

Congratulations, you just deployed your app. You should be able to visit the public IP given to your EC2 instance and see the app. Technically this is all you need to do. But wouldn't it be nice if the app would start up automatically if the server reboots? Maybe you're still testing and you want to start and stop the EC2 instance to save cost. If so, this is what you want:

sudo env PATH=$PATH:/usr/local/bin pm2 startup -u $USER

Summary

You have a running application with a little bit of fanciness like autorestart. But once you start getting users you're going to want to improve the architecture to make it easier to deploy, scale, and manage. In future posts we will discuss adding a reverse proxy and load balancer, as well as configuration management and continuous deployment techniques.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment