You’ve learned a lot.
You should earn a lot.

Find a Job

Deploying a MEAN App to Amazon EC2 (Part 1)


As someone who has trudged through many tutorials on the MEAN development stack, I’ve built many demo applications using some variation of localhost. Yet, when time came for me to move onto real-world deployments, I had a much tougher time finding guides straightforward enough to follow.

In an effort to help future versions of myself, I’ll be releasing a two-part tutorial that demonstrates the process of deploying a MEAN application live onto Amazon’s EC2.

In this first part, we’ll be taking an existing MEAN application and deploying it onto an EC2 instance with its own live URL.

Setting up your initial code

For this tutorial, we’ll be using the Node and Angular To-Do App that Chris created in an earlier guide. (If you’re not familiar with the MEAN stack, I’d highly recommend you check out his tutorial. It’s one of the best free MEAN guides out there).

To begin, let’s create a forked copy of his code in Github. We’re forking the code as opposed to cloning it, because we’ll need our own repo to commit changes into for later steps.

Cloning Repo

Now clone your forked repo into a local directory and run npm install to download all of the necessary dependencies.

git clone https://github.com/afhaque/node-todo.git 
cd node-todo
npm install   

Let’s run a quick test to make sure things are working correctly, by running node server.js. Open your browser and navigate to http://localhost:8080. If all goes well you should see the familiar “I’m a Todo-aholic” screen.

I'm a Todo-aholic

Woo hoo! Now onto EC2 Deployment.

A quick primer on AWS and EC2

Before we begin, I think its worth having a quick primer on Amazon Web Services (AWS) and Amazon Elastic Compute Cloud (EC2). AWS is a collection of remote computing services, or web services, offered by Amazon to handle tasks related to cloud computing, storage, databases, networks, deployments, and analytics. The list of services included in AWS is incredibly vast and targets wide range of broad to extremely specific purposes.

For today’s tutorial, we’ll be focused entirely on Amazon EC2, the most widely used of the AWS offerings. EC2 provides a low-cost computing service for handling computational tasks. In our case, we’ll be using EC2 to run the server which will host our web application.

Getting Started with EC2

The first step in our deployment is to create an account with AWS. Just follow the steps on the screen to complete the process. All new AWS users are automatically placed in the free usage tier, which grants, among other features, 750 hrs/month of free Amazon EC2 micro access – plenty of room for experimentation. As you are creating your account, be sure to choose the Basic (Free) option.

Once registered, click “Sign In to the Console” and you’ll be taken to the AWS home screen. The console provides links to all of the AWS offerings available to you. For our deployment, we’ll be heading to the EC2 dashboard.

EC2 Interface on Dashboard

Before we start launching our EC2 instance, our first step is to create an EC2 Key Pair. Key Pairs refer to the public and private keys used to encrypt and decrypt login information. Amazon requires that you use a key pair with every EC2 instance, so we’ll need to create one before proceeding. To do this, let’s navigate to the menu option titled “Key Pairs” and click “Create Key Pair”.

Image of where Key Pair is

Name your key pair in the pop-up that appears. Immediately after, a .pem file with the same name will download to your system. Don’t lose this file! It’s only generated once and you’ll need it to access your EC2 instance. (During development, I like to keep this file handy by placing it in a resources folder of the app I am working in.)

Create Key Pair

    | app
    | config
    | node_modules
    | public
    | resources
        | todoaholic.pem

Launching our EC2 Instance

Now that you have a key pair in hand, head back to the main AWS console, and go to the AWS Marketplace. The Marketplace includes a variety of pre-configured images for quickly deploying software and operating systems onto EC2.

In our case, we’ll be using a Bitnami MEAN image from BitRock. Search for this in the marketplace and open up the one titled: “MEAN Powered by Bitnami”.


At this point, let me take a moment to say, I have a lot of mixed feelings about the Bitnami MEAN Stack for EC2. On the one hand, it’s free and offers a lot of convenience when it comes to initial setup. All the necessary MEAN components (MongoDB and Node) are pre-installed upon launch. On the other hand, the Bitnami documentation is extremely poor. My hope is this guide will help you take advantage of its convenience, while addressing its poor documentation.

From the Bitnami MEAN screen, click the continue button. You can keep the region set to US East (N. Virginia). Next you’ll be shown a number of options regarding version, region, security groups, and more. The only thing to change is the EC2 Instance Type. In order for you to avoid any charges, select t2.micro. (As a new user, you have 750 hours of no-cost EC2 micro usage).

EC2 Launch

Also, note on the bottom how the Key Pair you created earlier has been pre-selected for you.


Now, click: “Accept Terms & Launch with 1-Click”. You will then receive a notification telling you that your EC2 instance is being deployed.


From here, navigate back to the Amazon Web Services Console and open up the EC2 dashboard again. What you’ll see on this screen is that you now have 1 Running Instance (server), 1 Volume (storage), 1 Key Pair (encryption), and 2 Security Groups (security) under your resources.


Click the link on “1 Running Instance” and you’ll be taken to your newly created server with the Bitnami MEAN image. Wait a few moments for the instance to complete its initialization. You will know its ready when the Status Checks change from “Initializing” to “2/2 checks”.


Connecting to your EC2 Instance

Now, this next step is very important. So read closely. As part of the Bitnami MEAN installation, your instance comes pre-configured with an initial MongoDB admin username and password. The initial username is always root, but a unique password is created upon first launch of an instance. To obtain your password, right-click on the row of your EC2 instance and navigate to Instance Settings -> Get System Log.


Scroll through the System Log to the very end. You should see a bright box with the words: Setting Bitnami application password to followed by a password. This is your initial MongoDB admin password. Copy it and paste it somewhere safe. And again, don’t lose this password either! You will only be shown it once, and you will need this in order to access your EC2 instance of MongoDB.


Okay! We’re making great progress. The next item of business is connecting to our EC2 instance via SSH. As a windows user, I like to use PuTTY for this. Download this program if you don’t already have an SSH client handy. (Note: I also like to keep the PuTTY .exe file in the resources folder of my application for convenience as well. You’ll be using it fairly frequently).

Once installed, navigate back to your AWS Console and to your running EC2 instance. From this screen look at the description section associated with your EC2 instance. Note the Public DNS. This represents the URL where your application will sit and the hostname you will be connecting to. You’ll be using this Host Name along with the .pem security key you downloaded earlier to connect to your EC2 instance.


But before we can proceed with our connection, you will need to convert your .pem file into a .ppk file that PuTTY can recognize. For this you will need the program PuTTYgen. Go ahead and download the program now.

After its ready, load your existing .pem security file into PuTTYgen. Remember to switch the file types to all “All Files .” when browsing for your key. Once its loaded, click “Save Private Key” and re-save your file as a PuTTY Private Key file (.ppk).


Still with me? Great! Because we’re finally ready to connect to our EC2 instance.

Open up PuTTY and enter the Public DNS you noted earlier as the Host Name. Set the Port for 22. Finally, look through the category menu for the SSH -> Auth page. Where it says: “Private Key for Authentication” upload the .ppk file we generated earlier.



Click “Open” and a terminal will pop-up. If this is the first time you’ve accessed this specific host, a warning will appear informing you that the server's host key is not cached in the registry. Just hit “Yes” to instruct it to continue. You’ll then be greeted by a screen saying: “login as”. Enter bitnamiand you should see a few lines welcoming you to the system.


Huzzah! Connection successful :-)

Pulling Files

Alright now that our system is setup and configured, it’s time to start deploying our code.

First, let’s get familiar with what we have installed. In the SSH terminal, type ls to see the directories. As you can see, we have three folders, one for apps one for htdocs and one for stack. Let’s look into the stack folder.


You’ll see a variety of directories including ones for apache2, mongodb, nodejs, php, python, and sqlite. By using the Bitnami image, we’ve saved ourselves the trouble of having to install each of these ourselves. Yay, convenience!

But let’s not celebrate too much yet. There’s still a lot more to be done. Let’s begin by cloning our node-todo git repository onto the server. (Always remember to include sudo!)

cd apps
sudo git clone https://github.com/scotch-io/node-todo.git {USE YOUR LINK}
cd node-todo

To confirm things worked out, do a quick ls to check that the node-todo folder was created. cd into that folder and again check the contents with ls.


Looking good! Next step, let’s download and install all of our npm dependencies.

sudo npm install 

Okay! deep breath Let’s see if we can run our server.js file using node.

node server.js


Ugh. Guess not. So, what’s going on here?

Setting Security Access

Well. As you may remember from testing local applications in the past, whenever we build MEAN applications we designate a specific port to which the server refers. (Think localhost:3000, localhost:8080, etc). This doesn’t require configuring when you’re running locally, but now that we’re in the real-world, our ports aren’t just open by default. This means since our application is looking to use port 8080, we need to make sure that port 8080 is accessible for use. We need to configure these settings in AWS.

Open up your web browser and navigate back to the AWS EC2 Dashboard. Then, using the menu on the left, open up the Security Groups panel. Click on the row associated with our MEAN application. (It will have a Group name like: “MEAN powered by Bitnami”). Beneath our row is a set of Inbound and Outbound rules specifying which ports are accessible for the application and by the outside world.


We need to create a custom inbound TCP rule that makes port 8080 accessible. Set the Protocol to TCP, the Port Range to 8080, and the source (anywhere). Additionally, we’ll do the same for port 27017, which will be used by MongoDB.



Once you’ve added this new rule, refresh the security group using the menu button at the top right.

Now, let’s close out the PuTTY connection previously opened and reconnect using the same DNS name, port, and .ppk file that you used earlier.

Launch Time!

Okay. Round 2. Let’s try launching our server.js file again.

node server.js

No errors. That’s a good sign.


But there’s only one way to see if our application is actually working. It’s time to check things in our browser.

But what’s the URL? Good question! It’s just going to be the complete DNS Hostname followed by the port.

<DNS Hostname>:<Port Number> 

In my case this means: http://ec2-52-0-14-185.compute-1.amazonaws.com:8080/

Open up your browser and give it a go.

And if you do, you’ll hopefully see our friendly To-Do list right before your eyes. (Relish this moment. It may be one of the few times you can take pride looking at a to-do-list).


“Okay! Mission accomplished!”

Not quite. As of now, the moment we close out PuTTY, our application dies with it. Conceivably, we could keep our PuTTY window open forever, but that sort of defeats the purpose of having our application on a server.

So instead, we’re going to utilize the node package forever.js. Forever is a simple tool that ensures a given script runs continuously (i.e. forever). To install it, let’s first stop our existing application with ctrl+c.

Then we’ll run:

sudo npm install forever -g

And finally, to launch our application continuously, we wil enter

forever start server.js

You will get a short message saying Forever processing file: server.js and you should be good to go. The best way to test that things after that is to simply close out your instance of PuTTY and give your application another try in browser.

If all went well, you should once again see your familiar Todo-aholic screen.

Yay! Congratulations! You now have a live deployment of your first MEAN application!

Utilizing EC2 Instance of MongoDB (Part 2)

Now, at this point, you have fully deployed a MEAN application to EC2.

But as some of you may have picked up, we never even touched MongoDB in EC2. We never specified the MongoDB URL in our MEAN application, and we never used that funny green password I told you to not lose.

Yet, still our application worked wonderfully. Why is that?

Well, in the original MEAN application developed by Chris, we make use of an external instance of MongoDB – specifically one sourced from Modulus.io. In this case, Modulus is providing our application with a Database-as-a-Service (DaaS). There are other companies out there that offer similar services (MongoLab and Compose.io for instance). All-in-all these services are pretty great. They offer you a quick, reliable instance of MongoDB, fantastic GUIs for administering your data, and a free sandbox instances to play around with. For many purposes, this is exactly what you need.

That said, if you are looking to retain greater control of your MongoDB database, you may be inclined to use your own MongoDB instance in EC2. As an added advantage, utilizing your own MongoDB instance in EC2 can be significantly cheaper in the long-run. As an example, an M1 Cluster with 40 GB of storage would cost you about $180 per month using MongoLab. In contrast, a similarly structured MongoDB instance in EC2 would cost only $36 per month, if you set it up yourself. You wouldn’t have the nifty GUIs or the dedicated support, but hey – it’s always good to know your options.

In the next part of our tutorial, we’ll be working through the process of migrating from the current DaaS to our own EC2 instance of MongoDB. Stay tuned!

p.s. Don’t lose your password. It’s never coming back! :-)

Ahmed Haque

Grad Student. Javascript Developer. Wannabe Social Entrepreneur. Trying to fit it all together.