MeteorJS Deployment the Proper Way
Meteor JS is undoubtedly a great framework that makes it very fast to learn and prototype. However, the downfall of the framework is when we try to move it to production, the documentation is scarce. This is also a problem we faced when we try to migrate our code for production. There are a few things to note before releasing Meteor App for production:
- Remove Insecure
- Remove Autopublish
- Make sure that Meteor JS environment variables are set correctly
Insecure Package
Meteor comes installed with insecure
package which makes development quick. It allows the client-side to edit (only insert, update and delete) database directly without writing any codes on the server-side but when you are moving your app to production, it should be removed for security reasons. Once this package is removed, you no longer able to use insert()
, update()
, upsert()
and remove()
methods from the collections API, instead you need to move that part of the code to the server-side's Meteor.method()
function and on the client-side, replace it with Meteor.call()
function. For more information on how it can be achieved, please refer to this Meteor Tutorial
Autopublish Package
Like the insecure
package, this is also installed on Meteor's fresh installation. However, it does not involve any database editing features, instead, this package is about the database's find()
method. Once this package is removed, your app's find()
method no longer works, you have to add Meteor.subscribe()
method on the client-side and Meteor.publish()
on the server-side. What I found making this feature confusing is its naming of the methods, it uses the same Model.find() method on the client.
This feature is when the controller changes, it will request a subset of the data to be stored on the client-side, so when Model.find()
is called on the client-side, it is actually querying the data that is stored within client. If you have conditions that filter the data by field on the client-side, make sure that those fields are also selected on the server-side publish()
method. For more information on how to migrate to publish/subscribe method, please refer to this tutorial.
Meteor JS Environment Variables
Other than insecure
and autopublish
package, it also comes with a feature called Hot Code Push. This is a feature that when you changed your template, Meteor JS will push the update to all clients. This makes it convenient for updating the clients, but makes debugging hard if you don’t know this feature is enabled by default. We have had this issue when we first deployed the app on Digital Ocean as we followed the deployment guides available through the Internet. Symptoms we encountered were:
- When the application is first launched (launch after a fresh installation), the screen seems to refresh automatically.
- Once it the screen refreshed, the app no longer able to contact the server.
Symptom #1
This is due to Meteor Cordova's Hot Code Push
pushing new codes the client, once it gets the new code, it refreshes the screen. This is supposed to happen only when I rebuilt the application, not for every clients. To prevent this, environment variable AUTOUPDATE_VERSION
needs to be set, if it's changed, an update will be sent to the client. For more information about AUTOUPDATE_VERSION
please refer to the FAQ
Sympton #2
MeteorJS Hot Code Push
feature also allow the update to the server's URL, this is a handy feature for migration of the server. However, it is also required that the ROOT_URL
environment variable to be set correctly on the server-side, it is what we have encountered with our application. After 1 whole day of debugging trying to figure out what went really wrong, we finally figured that it is this environment variable that is misconfigured. If you are not migrating to a new server, make sure that ROOT_URL
is the same as --server
parameter you used to build the app. For more information about this issue, please refer to this Github issue
My Final Upstart Configuration
#upstart service file at /etc/init/meteor-service.conf
description "Meteor.js (NodeJS) application for eaxmple.com:3000"
author "rohanray@gmail.com"
# When to start the service
start on runlevel [2345]
# When to stop the service
stop on shutdown
# Automatically restart process if crashed
respawn
respawn limit 10 5
# Essentially lets upstart know the process will detach itself to the background
expect fork
# drop root proviliges and switch to mymetorapp user
setuid <user>
setgid <user>
script
export PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
export NODE_BIN='/usr/local/bin'
export PORT=3000
# this allows Meteor to figure out correct IP address of visitors
export HTTP_FORWARDED_COUNT=1
export MONGO_URL=mongodb://<mongo User>:<mongo password>@127.0.0.1:27017/<mongo DB>
export ROOT_URL=https://<domain>
# this is for hot code push
export AUTOUPDATE_VERSION=0.0.1
exec node ~/bundle/main.js >> ~/meteor.log
end script