Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

Jason McIver


A Javascript developer excited about Meteor, Mongo, React and Node.

Deploy with MUP

Meteor UP

Meteor has a convenient bundle feature for packaging your apps into a tarball for deployment, but you still need to manage the files and upstart on your remote host. Meteor Up (MUP) does this for us so you get logs, start/stop/status and environment vars, it is all controlled from your local machine.

Like most of my posts this is more or less notes I've kept from various sources and my own experience.

Install MUP

Install MUP on your local computer through NPM.

npm install -g mup  

MUP setup

In you local project directory

mup init  

Which generates a mup.json file like this:

{
  // Server authentication info
  "servers": [
    {
      "host": "<remote server addr>",
      "username": "root",
      //"password": "password"
      // or pem file (ssh based authentication)
      "pem": "~/.ssh/id_rsa"
    }
  ],

  // Install and configure MongoDB on remote server.
  "setupMongo": false,
  // Install Node.js on the server which is required
  "setupNode": false,
  // Configure your Node version number, stick with this for the moment.
  "nodeVersion": "0.10.36",
  // Install Phantom.js on the server
  "setupPhantom": false,

  // App name (No spaces)
  "appName": "<appname>", //this is used as the dir name to store your app under /opt/

  // Location of app (local directory)
  "app": "<local path to your meteor project>",

  // Configure environment vars you want to pass into your running app from the CLI
  "env": {
    "ROOT_URL": "http://<remote server ip>:<remote port>",
    "PORT": "<remote port>",
    "MONGO_URL": "mongodb://<remote MongoDB >"

  },

  // Meteor Up checks if the app comes online just after the deployment
  // before mup checks that, it will wait for no. of seconds configured below
  "deployCheckWaitTime": 15
}

MUP can configure Mongo on your remote server, the above guide is for a 3rd party Mongo host

Setup the remote enviornment. Uses the above settings to install and anything required and setup directories.

mup setup  

keys

You'll get sick of typing your password each time you make a change so it's recommended you use keys to authenticate. On your remote server add yourself to sudoers without password.

sudo visudo  

Add yourself:

<your username> ALL=(ALL) NOPASSWD:ALL  

If you don't already have local rsa keys create a new one:

ssh-keygen -t rsa -c "<your email address>"  

Use the default key storage and don't use a passphrase just leave it blank.

Then copy the public key from your remote server to your local dev pc. Output the key contents with:

cat ~/.ssh/id.rsa.pub  

then copy and paste it into remote file:

vi ~/.ssh/authorized_keys  

deploy

When your project is ready to deploy make sure you have initialized MUP, configured the mup.json file, then setup your remote enviornment with MUP setup before deploying with:

mup deploy  

It will use Meteor's bundle command, upload the resulting app to your remote host into /opt/ and finally restarting it.

Build mobile app

Not a MUP thing but you need to point your mobile app to the remote host when building it with Meteor.

meteor run android-device --mobile-server ip:port  

You can read more about it here Meteor mobile deployment

CORS

With your app running on mobile devices (android/ios) the remote server will prevent access to it's resources by default, you need to allow Cross-origin Resource Sharing.

if(Meteor.isServer){  
    Meteor.startup(function () {
      WebApp.connectHandlers.use(function (req, res, next) {
        res.setHeader('access-control-allow-origin', '*');
        return next();
      })
    })
}

Keep MUP upto date

npm update mup -g  

Reconfig application MUP settings

Anytime you change mup.json you need to apply any changes to your remote server

mup reconfig  

Multiple domains

MUP makes it easy to deploy and manage multiple apps on a single server remotely. If you want each one to have it's own sub-domains you need to configure a reverse proxy to handle the requests.
For this example I'm using Ubuntu 14.

Install Nginx

sudo apt-get install nginx  

Configure Nginx

copy the default configuration for each app you have a domain for, then edit the file

cp /etc/nginx/sites-available/default /etc/nginx/sites-available/<appname>  
vi /etc/nginx/sites-available/<appname>  

There are many settings in here but we just want to tell it to listen for our domain and point it to our app where Meteor is running. Configure Server similar to this:

server {  
        listen 80;
        server_name <app domain> <public ip:port>;
        access_log /var/log/nginx/<appname>.access.log;
        error_log /var/log/nginx/<appname>.error.log;

        location / {
                proxy_pass http://<internal ip:port>;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection 'upgrade';
                proxy_set_header X-Forwarded-For $remote_addr;
        }
}

Test the configuration file with

nginx -t  

Restart Nginx

nginx -s reload  

Accessing your domain should now redirect the request to your app.


FAQ

Q

How do I troubleshoot?

A

Monitor the logs for your app live

mup logs -f  

Q

mup deploy returns an error:

curl: (52) Empty reply from server

...
Waitinting for MongoDB to initialize  

A

Check the logs, but somethings to check:
Try serving up your Meteor app localy to see if it's your app or environment.
Has your MongoDB instance gone to sleep? The Compose sandbox can goto sleep.
Is remote server using Node version atleast same nodeVersion in mup.json? You can manage node versions with 'n':

npm install -g n  

Try extending deployCheckWaitTime in mup.json.

Q

I'm using Meteor accounts package and the MUP log reveals

Could not load the binding file, Tried:  
app/programs/server/npm/npm-bcrypt/node_modules/bcrypt/build/bcrypt_lib.node  

A

Try adding to packages.json in your local meteor project directory under .meteor/local/build/programs/

{
  "dependencies": {
    "bcrypt": "0.5.~"  
}