Tips for Deploying Meteor 1.3 App to AWS EC2

Hey Guys,

Recently I have been exploring Meteor framework, which is quite appealing and interesting for a guy just mastered Django framework. While, both of them have pro and cons but Meteor is more concise and undoubtably suitable for some simple, real-time, interactive applications.

Writing Meteor Application may be a wonderful journey but deploying it on AWS EC2 was not a pleasant experience to me, which is full of pitfalls and trails and errors as I have spent over 20 hours to deploy the Meteor App to AWS EC2 with MongoDB installed successfully. Thus let me share my experience here and hopefully be helpful to you.

Setup a free tier of AWS EC2 is relatively simple and straightforward. If you are not familiar about it, please refer to this article.

1. Meteor Server setup

I. Version! Version! Version!

For the latest Meteor 1.3, you would use mupx as your deployment tool rather than the mup, as the first one is better for the latest Meteor and using docker technique.

npm install -g mupx

II. Different folder

Strongly recommend you to mkdir a new folder to deploy meteor, which is not the same as the one your app located.

For example,

/Parent directory
|–/MyMeteorApp
|–/MyMeteorApp-deployment

III. init

mupx init

This command will create two configuration files, mup.json and settings.json. We will deal with mup.json only.

IV. mup.json

If you are using ubuntu image in EC2, your mup.json should look like this,

{
  "servers": [
    {
      "host": "<Your ec2 aws url or public IP>",
      "username": "ubuntu",
      "env": {}
      "pem": <Your local directory to xxx.pem>
    }
  ],
  "setupMongo": true,
  "appName": "MyMeteorApp",
  "app": "<Your local directory to /MyMeteorApp>",

  // Configure environment
  // ROOT_URL must be set to your correct domain (https or http)
  "env": {
    "PORT": 80,
    "ROOT_URL": "<Your ec2 aws url or public IP>"
  },  
  "deployCheckWaitTime": 60, 
  "enableUploadProgressBar": true,
  "buildOptions": {
     "debug": true,
     "executable": "meteor"
  }  
}

V. Deploy
mupx setup

mupx deploy

 

mup setup will setup the EC2 server using the mup.json we just edit, while mup deploy is the method who actually deploys our MyMeteorApp to EC2 server. Therefore, later if you want to update your application, mup deploy is the only one to be run when updating if the mup.json wasn’t changed.

Note, this setup may have lots of different kinds of issues, some tips to debug.

1. Make sure you can access your EC2 instance locally

     ssh -i <local path to .pem file> ubuntu@<EC2 public IP>

2. Check your Meteor version

3. Sometimes you would better deploy to a clean EC2 instance.

4. set deployCheckWaitTime in mup.json to over 60s

5. mup logs -f to check the deployment log to see what happens

6. rm -rf ~/.meteor/package-metadata and then re-deploy

VI. Security Group in EC2

Pay attention to your security group in EC2, it should look like this,

Screen Shot 2016-04-04 at 9.44.03 PM

Only one SSH rule is enough, while we may set the source as your local IP. Port 27017 is for MongoDB.

By far, we should see your application shown up through the EC2’s public url as set in ROOT_URL in mup.json.

2. MongoDB Server setup

I. Version! Version! Version!

Till now, your App may be running but may not access your local mini mongoDB, due to this mini mongo is used for accelerating client-server communicating but will not deploy to your EC2 server automatically. So we are going to install MongoDB 3.2.4 on a different AWS EC2 instance and accessing this remote mongodb

II. Following Official MongoDB guide

For ubuntu 14.04

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv EA312927

echo "deb http://repo.mongodb.org/apt/ubuntu trusty/mongodb-org/3.2 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.2.list

sudo apt-get update
sudo apt-get install -y mongodb-org=3.2.4 mongodb-org-server=3.2.4 mongodb-org-shell=3.2.4 mongodb-org-mongos=3.2.4 mongodb-org-tools=3.2.4
echo "mongodb-org hold" | sudo dpkg --set-selections
echo "mongodb-org-server hold" | sudo dpkg --set-selections
echo "mongodb-org-shell hold" | sudo dpkg --set-selections
echo "mongodb-org-mongos hold" | sudo dpkg --set-selections
echo "mongodb-org-tools hold" | sudo dpkg --set-selections

III. start mongoDB

sudo service mongod start

IV. configure mongoDB
sudo vi /etc/mongod.conf

then open buidIp to all IP

bindIp: 0.0.0.0

V. Restart the mongoDB after you changed mongod.conf

sudo service  mongod restart

VI. check mongoDB running

sudo netstat -tlnp | grep 27017

it should look like this,
mongo

VII. If you login your EC2 server and type

sudo netstat -tlnp | grep 27017

it will look like this and this docker-proxy hardly server as mongoDB.

server

VIII. Debugging

1. First you have to make sure you can access your EC2 mongodb locally

mongo <EC2 mongoDB public IP>/test

or

mongo <EC2 mongoDB public IP>:27017/test

2. Second here’s a pitfall, your have to make sure your local mongo shell version is identical as the one in EC2 mongoDB server. The version 2.4.9 shell cannot communicate with the one of version 3.2.4

Screen Shot 2016-04-04 at 10.21.07 PM.jpg

3. Sometimes, try

rm -rf /var/lib/mongodb/mongod.lock

and then restart mongoDB did work

3. Local App modification

I. Server side

Actually this part should be in the middle of this guide, and I spent too much time to figure it out while it is extremely simple under the hood.

Note if you haven't set mongoDB username and password leave them blank for now.
For example, if you intend to access a collection named talk

if (Meteor.isServer) {
  process.env.MONGO_URL = "mongodb://<Database username>:<database password>@ec2-xx-xx-x-xxx.us-west-2.compute.amazonaws.com:27017/test";
  var myDatabase = new MongoInternals.RemoteCollectionDriver(process.env.MONGO_URL);
  Talk = new Mongo.Collection('talk', { _driver: myDatabase });
  Meteor.publish('talks',function(){
  //console.log("server side", Talk.find().count());
  return Talk.find();
 });
}

II. Client Side
In your Talk template,

if (Meteor.isClient) {
    Talk = new Mongo.Collection('talk');

    Template.talks.onCreated(function(){
        this.subscribe('talks');
    });
    Template.talks.helpers({
        talks: function () {
            return Talk.find({});
        }
    });
};

Note you have to declare Talk twice once in server and once in the client.

III. Debugging

If you met the following error, you might met trouble of MONGO_URL.

However, if you can access your EC2 remote mongoDB in local terminal, then your Meteor App should work well.

Screen Shot 2016-04-04 at 10.41.11 PM.jpg

 

Conclusion

Deployment is difficult especially for the newbies and for the new frameworks such as Meteor. But carry on please, you will make it! Good luck~

Reference

  1. https://www.youtube.com/watch?v=Lyyh2fkXovo
  2. http://www.curtismlarson.com/blog/2015/11/03/deploy-meteor-to-aws/
  3. https://github.com/arunoda/meteor-up/issues/103
  4. https://scotch.io/tutorials/deploying-a-mean-app-to-amazon-ec2-part-2

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s