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

Find a Job

Deploying a MEAN App to Amazon EC2 (Part 2)


Welcome back. In Part I of our tutorial, we took steps to deploy a MEAN application to EC2. In the process, we created a running EC2 instance, configured our security settings, made a connection, and set our application to run.

In this part of the tutorial, we’ll be modifying our MEAN application to utilize an instance of MongoDB running on our EC2 server.

Why should we do this?

Live To-Do App

As we discussed at the conclusion of Part I, our current To-Do application is relying on an external instance of MongoDB. Specifically, we’re employing a Database-as-a-service (DaaS) offered by Modulus.io to provide a complete database that our node application can connect to.

DaaS’s (like Modulus.io, MongoLab, and Compose.io) offer a convenient way to use MongoDB without having to handle installation and troubleshooting. As an added advantage, they often provide friendly GUIs for administering and querying their databases.


That said, these services come with tradeoffs.

For one, their monthly cost tends to be significantly higher than if you setup MongoDB yourself on your own server. As an example, an M1 Cluster with 40 GB of storage would cost you about $180 per month using MongoLab. In contrast, a similar MongoDB instance in EC2 would cost only $36 per month if you set it up yourself.

Additionally, using DaaS’s often limit your ability to fully customize all aspects of your database. (If, for instance, you were creating a healthcare application and needed a HIPPA compliant system, a ready-made solution typically wouldn’t make the cut.)

Just consider the pros and cons. But for today’s tutorial, we’re going to ditch the DaaS in favor of our own EC2 instance of MongoDB.

Getting Back to Business

Because this tutorial is focused on deployment, you will need to have completed Part I in order to follow along. Take a look and come back when you’re done. For those returning, make sure you have your passwords and account details handy.

Once you’re ready, let’s connect to our EC2 instance again using PuTTY.


When prompted, enter: bitnami to login.

Login Bitnami

Logging into MongoDB

To begin working with Mongo, we’ll need to login as an administrator.

Here, we’ll be making use of the green password we obtained in Part I. (Remember, that password is only displayed once. If you failed to record it earlier, you’ll need to create a new EC2 instance and repeat Part I again. Sorry!).


While in the EC2 terminal, use mongo admin to enter MongoDB. (p.s. Remember to include sudo or you may go crazy wondering why MongoDB refuses to permit you):

sudo mongo admin --username root --password {YOUR GREEN PASSWORD}

Once you’ve logged in, the first action we’ll take is to create a new user with administrative privileges. We’ll create this account, so you have access to a username and password you can actually remember.

> show dbs 
> use admin 
> db.createUser 
> db.createUser(
      user: "YOUR USERNAME",
      pwd: "YOUR PASSWORD",
      roles: [ "root" ]

If all goes well, you should be notified that the user was successfully added.

Now, log out of mongodb by entering ctrl+c and try logging back in using your new admin username and password.

sudo mongo admin --username {YOUR USERNAME} --password {YOUR PASSWORD}

Login Successful

Confirm that your account has been granted complete privileges by querying the databases and adding in a dummy record. Here we’ll add a record: “This is a test” into the “test” collection of “dummyDB”.

> show dbs 
> use dummyDB 
> db.test.insert({ item: "This is a test"})

If we query for the record we should see it appear.

> db.test.find().pretty()

Queried Record

Perfect. There’s our dummy record — proving that our admin account is fully functional. Now its time to connect our app.

Enabling Access

Before we can copy and paste our MongoDB URL into our MEAN application, we need to make sure that its fully accessible. This means two things. First, it means ensuring the MongoDB port is accessible to the outside world. And secondly, it means configuring MongoDB so it knows which IP addresses to allow database access.

We aren’t going to dive too deeply into “ideal” security settings in this tutorial. How loosely or how tightly you need your database access to be is dependent on your specific application. And since we’re just deploying a simple demo, we’re going to keep things simple.

So let’s begin. For a first step, let’s make sure the MongoDB port is accessible. We cheated and already did this in Part I, but I think its worth re-examining. By default, the port used by MongoDB is 27017. (The Bitnami image we used in Part I also uses this default as well.)

Now, open your Amazon EC2 instance in the Amazon Web Console and head to the Security Groups section. If you completed the steps in Part I correctly, you should see that we have a Custom TCP Rule which allows inbound access to port 27017 for all IP addresses (

AWS Security Groups

Great! Step 1 complete.

Now, we need to ensure that all IP addresses can run commands in MongoDB itself. This allowance is helpful especially during development, in which, many developers may need to access the database from multiple machines. To do this, open up your PuTTY window again and cd back into the main directory. From here, head into Stack -> MongoDB.

cd stack
cd mongodb

MongoDB Directory

If you look into this directory, you’ll see a number of files and folders associated with MongoDB. In our case, we will be opening the mongodb.conf file and making a few edits using the vi editor.

sudo vi mongodb.conf

Once you’ve opened the file, you’ll see a list of config settings. Notice, for instance, where it specifies the port is 27017.

In our case, we’ll actually be changing the bind_ip value to equal This will allow all IP addresses access to our MongoDB instance. While still in the editor, type i to enter insert mode. Change the value of the bind_ip. Then type :w to save and :q to exit the editor.

This is how your config file would have looked before…

Bind IP Before Change

And after.

Bind IP After Change

Once complete, navigate up one level back to the stack folder. Then run the bash script in ctlscript.sh to restart mongodb. This will ensure your changes to the MongoDB have taken effect.

cd ..
sudo bash ctlscript.sh restart mongodb

Restarting MongoDB

At this point, our MongoDB database is ready for use by our MEAN application. But, unfortunately, we have a few more steps to get things working for remote development and testing.

Necessary Workaround for MongoDB 3.0

To describe why this next step is necessary, open up a local terminal and try to access your EC2 MongoDB database instance. Use the below command as a guide.

mongo {EC2 DOMAIN}/admin -u  {YOUR USERNAME} -p {YOUR PASSWORD} 

At this point, what you’ll likely see is the aggravating response: Error: 18... "auth failed". Try as you might in repeating your password or creating new users — this error won’t go away.

Auth Failed

The reason for this error has less to do with your faulty memory and more to do with the recent upgrade to MongoDB. With version 3.0, came a new authentication mechanism for MongoDB. In Mongo 2.0, a database could be accessed via a remote shell or terminal so long as an admin username and password was supplied. This was convenient for upstart developers trying to quickly set things up. With the latest change, the authentication mechanism requires a bit more work as many third-party tools (including Bitnami’s default image) have yet to switch to the new drivers.

Fortunately, the MongoDB team has a relatively simple workaround, in which we will revert our MongoDB setting to the old authentication mechanism.

To do this, first open up your PuTTY instance to EC2 and navigate to the mongodb.conf file again.

cd stack
cd mongodb
sudo vi mongodb.conf

Now, look for where it says: auth = true. Temporarily, comment this value out, and uncomment the parameter that says noauth = true. Save your changes (:w) and exit the vi editor (:q). Your config file should now look like the image below.


With this change to config settings, we could actually access MongoDB remotely without even having to authenticate. But that’s clearly not a solution we want. Instead, we are going to create a new administrator that utilizes the old-form of MongoDB credentialing.

Now restart MongoDB again by running the restart script in ctlscript.sh.

cd ..
sudo bash ctlscript.sh restart mongodb

Finally, login to MongoDB and run the following to revert the authentication mechanism.

> use admin
> var schema = db.system.version.findOne({"_id": "authSchema"}) 
> schema.currentVersion = 3 
> db.system.version.save(schema)

Your output should look like the below. Reverting Authentication

Now create a new admin profile. This administrator will work with the reverted authentication mechanism and work for remote connections. To restrict access for this remote admin, I am going to limit its access to the dummyDB we created earlier.

> show dbs 
> use dummyDB
> db.createUser({
        user: "NEW USERNAME",
        pwd: "NEW PASSWORD",
                        "role" : "readWrite",
                        "db": "dummyDB"

Once created, go back again to the mongodb.conf file, comment out noauth=true, and uncomment auth=true. (Essentially re-activate the authentication requirement). Your config file should now look like this:


Restart MongoDB again using the ctlscript.sh and then try connecting to your Mongo instance via local terminal again.

mongo {EC2 DOMAIN}/dummyDB-u {New Username} -p {password}

Connected Remotely

Voila! Connection successful!

Incorporating the EC2 DB into our App

Okay. We have one final step before we can re-deploy our code. We just need to incorporate the new MongoDB URI into our MEAN application. Open up your forked node-todo app from before.

Navigate to the database.js file found in the config folder.

Comment out the existing URL and replace it with the URL associated with your EC2 instance of MongoDB. It should follow the format below:

'mongodb://{NEW USERNAME}:{NEW PASSWORD}@{EC2 URL}:{PORT}/dummyDB'

As a reference, here’s how my url looked:


Finally, run your code locally using node server.js and navigate to localhost:8080. If all went well the app should work as before. The big change is that you’re now using your EC2 instance of MongoDB. Huzzah!

To-Do with Mongo EC2

Add a few to-do items in the web application. Then open up your PuTTY window, login to MongoDB, and query the dummyDB database to confirm that the todo items match.

> use dummyDB
> show collections
> db.todos.find().pretty()

Do we have a match?

Matching MongoDB  Records

YES! Victory at last.

Pushing, Pulling, and Calling it a Day

We’ve been through a lot in these past two tutorials. All that’s left for us to do is to push our node-todo code into Github and pull the updates onto our Amazon EC2 instance.

From your local dev environment commit and push your changes to Github.

git commit -m "Changed the DB URL to use EC2"
git push

Then from the node-todo folder of your EC2 instance, run

sudo git pull 

Pulled code

Finally, run forever to launch your MEAN application.

forever stopall
forever start server.js

And with that, it’s time to check out our finished work.


Finished App

Closing thoughts

After a long and hard slog we’ve finally completed our EC2 deployment. In this two part tutorial we went through the process of initializing an EC2 instance, setting up Node and MongoDB, configuring security settings, and connecting our app to a running instance of MongoDB located on our EC2 server.

As you can see, the process was arduous. But with the power of EC2 behind you, it becomes possible to create and deploy, low-cost MEAN applications for the entire world to see. Good luck building something great!

Ahmed Haque

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