By Matt Merkes May 14, 2014

Hosting a website on a free AWS EC2 instance: Not for the faint-hearted

Have you ever tried to get your website going on a free AWS EC2 instance and failed to get it running? I sure did.

In my younger years, as in last year, I struggled to get a site running on the EC2 server. Amazon likes to change things around pretty regularly, so the tutorials can go out of date pretty quickly. Fortunately, a good friend of mine and computer wizard, Jon Swenson, wrote down notes when he got his wedding website running (which was great when his server crashed) and was kind enough to share them with me (and to let me share them with you). I’ve modified them further to try to make it more noob-friendly, but you will need to use the command line and may need to troubleshoot a bit. Good luck!

I. Get your instance going

Launch an AWS EC2 instance. Select Ubuntu 12.04 LTS image. At this point, you’ll need to download a private key (.pem file) and put that somewhere on your local machine.

For example, you could do something like this:

# Make a hidden directory called ssh 
mkdir -p ~/.ssh
# Copy the private key and move it to ~/.ssh
cp ~/Downloads/mykey.pem ~/.ssh
# Change permission to 'read by owner'
chmod 400 ~/.ssh/mykey.pem

To make a shell shortcut, add these lines to a ~/.ssh/config file:

Host mywebsite 
Hostname ec2-XX-XXX-XXX-XXX.compute-1.amazonaws.com 
User ubuntu
IdentityFile ~/.ssh/mykey.pem

The X’s are your instance’s IP, shown in the AWS console. These lines allow you to go into your shell and just type ssh mywebsite instead of:

ssh ubuntu@blahblahblah.amazonaws.com -I ~/.ssh/mykey.pem.

You will also need to make sure that the security group associated to your EC2 instance has ports 80 (for HTTP communication) and 22 (for SSH) open. Add inbound “Custom TCP rules” to your security group with port range 80 and source 0.0.0.0/0, then another with port range 22. You can do this through the AWS web interface.

II. Install Nodejs and nginx (pronounced ‘engine x’) on your instance.

SSH into your instance and run the following install commands:

 Tools to prepare for Node install
sudo apt-get install python-software-properties python g++ make 
sudo add-apt-repository ppa:chris-lea/node.js 
sudo apt-get update
# Note: Ubuntu apt-get downloads an old version of Node, so if
# you have any problems with node, you might want to install
# it via a different method.
sudo apt-get install nodejs

# Install nginx
sudo apt-get install nginx

# Install whatever Node dependencies you'll need.
# Be sure to install 'forever', as you'll need it to ensure
# that your node scripts are running continuously.
sudo npm install -g express swig forever

III. Set up an nginx config file for your site.

This was found by Googling “node and nginx setup,” though you could use a different config file. I keep this file at /etc/nginx/sites-available/mywebsite and its contents are:

# Note: You will need to edit this file via the console,
# meaning vi or vim. If you're not familiar with their usage,
# search online. They can be difficult for the uninitiated.
# The local IP on which your node server is running. 3000 is a common choice. 
upstream myapp { 
  server 127.0.0.1:3000; 
}

# the nginx server instance
server { 
  listen 80; 
  server_name mywebsite.com; 
  access_log /var/log/nginx/mywebsite.log;

  # Pass the request to the node.js server with the correct headers and 
  # much more can be added, see nginx config options.
  location / { 
    proxy_set_header X-Real-IP $remote_addr; 
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
    proxy_set_header Host $http_host;
    proxy_set_header X-NginX-Proxy true;

    proxy_pass http://mywebsite/; 
    proxy_redirect off; 
  } 
}

After you have saved this file, run:

sudo service nginx restart

IV. Add actual website content

You still haven’t added any actual site content to your server yet. Start with:

sudo mkdir -p /var/www/mywebsite

All site content should go here, including the node app itself. The node app should sit in the /var/www/mywebsite directory, not in any subdirectory.

Alternatively, if you’re using git, cd into /var/www and do git clone http://url-to-your-repo and download the contents of your site. It will create a directory, and you’ll just need to make sure that the directory matches what you listed in the config file.

At this point, if you run your app with node (by typing node app.js or whatnot), your website should be up and running. You should be able to go to the IP address of your instance and see that node is running properly. This is a good way to check whether things are in the right place so far, but you should do one more thing.

There are multiple ways to get the code to your EC2 instance, so you’ll just have to search around if you don’t want to use git. Check gitolite if you want to host the repo on your server for easy pushing and pulling.

V. Finally, a startup script.

You can basically just copy this guy’s script and use it without much modification. The only lines you need to be modified are the variable lines.

NAME="siteName"
NODE_BIN_DIR=/usr/bin/node
NODE_PATH=/usr/lib/node_modules
APPLICATION_DIRECTORY=/var/www/mywebsite
APPLICATION_START=myapp.js 
# as mentioned above, myapp.js should be located in /var/www/mywebsite
PIDFILE=/var/run/mywebsite.pid
LOGFILE=/var/log/mywebsite.log

Before this works, you will need the npm forever package:

sudo npm install -g forever

The startup script allows you to run your site as an Ubuntu service. The beauty is that if your node process is ever terminated, dies (maybe your EC2 instance had to reboot, which it will), etc., a new node process will respawn as soon as possible (e.g., when the EC2 instance has rebooted) and your site will be back up without your having to do anything.

This script should be located in:

/etc/init.d/mywebsite

And should be made executable to all:

sudo chmod a+x /etc/init.d/mywebsite

Then, just run:

sudo service mywebsite start

And your site will be up and running.

This starts the node server process in a safe, “respawnable” way. You don’t have to worry about starting nginx, since it runs as a daemon by default. The nginx config file ensures that nginx and your node app can communicate.

When you update your website, just do:

sudo server mywebsite restart

VI. Pat yourself on the back

And it should be up and running again!

Hope that gets your EC2 instance going!

Check out the original post and more resources on Matt’s blog.