Phusion white papers Phusion overview

Meteor support for Phusion Passenger has been open sourced

By Hongli Lai on November 1st, 2013

Meteor

For those who haven’t heard of Meteor yet: it is a hip new Javascript platform for developing web apps. It’s quite an innovation compared to “traditional” web frameworks: you develop in a single codebase and the code almost magically works in both the browser and the server. The platform also synchronizes data automatically across all connected clients by using long polling, WebSockets etc. It’s definitely worth checking out.

Are “traditional”[1] frameworks like Rails in danger? We at Phusion tend to believe that each framework has its own strengths and weaknesses, with no single framework being a silver bullet for all possible use cases. But there are many Meteor advocates out there who believe differently. Josh Owens from from Differential claims that Rails has seen its last days.

[1] In this article, “traditional” is used very loosely and refers to all non-Meteor-inspired frameworks. There’s nothing wrong with these older frameworks, just different. I still think Rails is revolutionary in many ways.

Announcing Phusion Passenger + Meteor

Whatever the result will be, the Phusion Passenger application server will be around to help you simplify your deployments and keeping your systems running smoothly.

Meteor support was previously an Enterprise-only feature. But just like we open sourced Node.js support a week ago, we are now open sourcing Meteor support. We are strong open source supporters at heart, and we believe that it’s time to give back to the community. The source code is already available on Github.

Why use Meteor on Phusion Passenger?

Phusion Passenger takes a lot of complexity out of deploying Meteor, and adds powerful enterprise-grade features that are useful in production. It also makes administering Meteor apps much easier. It has already done this for Ruby, Python and Node.js and is being used by high-profile companies such as Apple, Pixar, New York Times, AirBnB, Juniper etc.

Here are some of the benefits that Phusion Passenger gives you:

  • The power of Nginx – Phusion Passenger combines Meteor with the increasingly popular Nginx web server. By combining them, Nginx will offload Meteor from serving static assets. This also adds a buffering reverse proxy layer which provides I/O security and protects Meteor against invalid HTTP requests, slow clients, etc.
  • Multitenancy – Run multiple Meteor applications on a single server easily and without hassle.
  • Process management and supervision – Meteor processes are automatically started, and automatically restarted when they crash.
  • Statistics and insight – Phusion Passenger provides tools for inspecting the applications’ status, such what requests they’re currently processing, how many requests they’ve processed. All relevant information is shown at a glance. Having this in production will help a lot with tracking down problems.
  • Scaling and load balancing – Based on current traffic, Phusion Passenger can spawn more Meteor processes to handle the load, or spin down some existing Meteor processes to conserve resources. Phusion Passenger automatically load balances traffic across Meteor process. The load balancing mechanism utilizes a smart “first-available” selection algorithm to avoid problems caused by slow requests. Although Node.js and Meteor are single-threaded, this approach allows them to utilize multiple CPU cores.

Phusion Passenger is quite small and fast, being written in optimized C++. It’s a lightweight tool which drastically reduces complexity in your production environments.

How’s this any different from putting Meteor behind an Nginx reverse proxy yourself?

  • Using Phusion Passenger is much easier. If you do it yourself, you’ll have to write reverse proxy rules, write init scripts, setup process supervision, etc and the result probably does not handle corner cases properly. Phusion Passenger takes care of all this for you and handles virtually all the corner cases. This reduces the number of moving parts and reduces complexity.
  • Phusion Passenger integrates much deeper into Nginx than a straight reverse proxy does, and as such can leverage Nginx features much better. For example, the load balancing and response buffering in Phusion Passenger is much better than the one you get with manual reverse proxying.
  • By using Nginx’s proxy module, it’s very hard to see what’s going on with the system right now. Are all connections ok? Are all processes ok? Phusion Passenger provides simple and powerful administration tools that can help you with that.

Getting started

Update: for the most recent version of this tutorial, please refer to Phusion Passenger: Meteor tutorial.

Installing

Visit the Phusion Passenger download page. There are tailor-made, polished installation methods for OS X, Debian/Ubuntu, Heroku, etc. :) You need at least version 4.0.23.

Preparing your app

A Meteor app in Phusion Passenger must contain the public and tmp subdirectories.

public directory contains static files. All files in this directory are automatically served by the web server. For example, if there’s a file public/foo.jpg, then any requests to /foo.jpg will be handled by the web server, and never passed to the application.

The tmp directory can be used by the application, but is also used by Phusion Passenger for restarting the application. By touching the file tmp/restart.txt, Phusion Passenger will restart the application on the next request. This seemingly strange mechanism comes from the fact that Phusion Passenger is designed to be friendly to shared hosters which only provide FTP access and no SSH access.

meteor create --example leaderboard
cd leaderboard
mkdir public tmp

Developing Meteor apps on Nginx

Developing on Nginx is a matter of adding a virtual host entry in your web server, and telling the web server that it’s a Phusion Passenger-served app. The meteor command must be installed.

Note that the document root must point to the public directory of the app! Suppose the app is located in /webapps/leaderboard, then:

server {
    server_name www.foo.com;
    root /webapps/leaderboard/public;
    passenger_enabled on;
    passenger_app_env development;
}

If you restart Nginx and visit http://www.foo.com/ now (assuming that your system’s DNS or /etc/hosts is configured to route to the web server in question), the request will be handled by your Meteor application.

There are many configuration options that you can tweak. Please refer to the Phusion Passenger manuals.

Deploying to Nginx during production

There are two options when deploying a Meteor app in production mode. You can either deploy a created Meteor bundle, or you can deploy the raw Meteor application directory.

Deploying a Meteor bundle

When deploying a Meteor bundle, we’re treating Meteor as a regular Node.js app. You do not need to have Meteor installed, just Node.js.

Create a bundle first and upload it to your production server:

meteor bundle leaderboard.tar.gz
scp leaderboard.tar.gz someserver:/webapps/leaderboard

On your production server, extract the bundle and install NPM modules:

cd /webapps/leaderboard
# This will create a directory /webapps/leaderboard/bundle
tar xzvf leaderboard.tar.gz
cd bundle
# Install whatever NPM modules your app needs. See the bundle README.
npm install fibers@1.0.1

You need to rename the main.js file in the bundle to app.js, and create a public directory, as per the Phusion Passenger requirements for Node.js.

mv main.js app.js
mkdir public

Now that the directory structure has been setup, create a virtual host in Nginx:

http {
    ...
    server {
       server_name www.foo.com;
       root /webapps/leaderboard/bundle/public;
       passenger_enabled on;
       passenger_set_cgi_param MONGO_URL mongodb://localhost:3002/meteor;
       passenger_set_cgi_param ROOT_URL http://www.foo.com;
    }
}

Caveat (November 1 2013): unfortunately Nginx only allows setting environment variables globally, not per virtual host. We are working on a solution for this, which we expect to roll out in the coming few weeks. Please stay tuned for updates. This problem turns out to be untrue. passenger_set_cgi_param can be used to set environment variables.

Deploying a raw app directory in production

When deploying a raw Meteor app directory, you need to have Meteor installed. The procedure is the same as for developing Meteor apps on Nginx: you need to create a public directory, and you need to point the Nginx virtual host root there.

In this mode, you do not need to set MONGO_URL and other environment variables because Phusion Passenger will start your Meteor app through meteor run --production. Phusion Passenger even automatically finds a free port for it to run on so that you don’t need to worry about it.

cd /webapps/leaderboard
mkdir public

Then:

server {
    server_name www.foo.com;
    root /webapps/leaderboard/public;
    passenger_enabled on;
    # The following is not needed because passenger_app_env defaults to production.
    # But this example sets it explicitly so that you can see what's going on.
    passenger_app_env production;
}

Further reading and troubleshooting

Phusion Passenger comes with an extensive manual.

Running into any trouble? Please check out the troubleshooting section of the documentation.

Administration tools

The passenger-status tool allows you to inspect Phusion Passenger and the currently application’s state, such as what processes exist, how much memory and CPU they use, how many requests they’ve processed, etc.

The passenger-memory-stats tool allows you to inspect the memory usage of all processes related to Phusion Passenger, including the web server, Phusion Passenger itself and the applications. The difference with passenger-status is:

  • passenger-status does not display the web server’s memory usage.
  • passenger-status does not display the memory usage of internal Phusion Passenger processes.
  • The metrics displayed by passenger-status are gathered by internal Phusion Passenger processes that run in the background. passenger-memory-stats displays information by querying ps. If the Phusion Passenger internal processes are malfunctioning, then passenger-memory-stats still works.

Your feedback is valuable!

We’d like to hear from you if you’re using Phusion Passenger to host Meteor apps! If there are any problems, or even if there are no problems, we’d like to know. Please send an email to the community discussion forum. Thank you!

Discuss this on Hacker News.

Want to stay up to date with the latest Phusion news, including news about our Meteor support? Please sign up for our newsletter. You can unsubscribe any time.



  • Mike

    Maybe it was something peculiar to my nginx setup but the lines:

    # Meteor app settings
    env MONGO_URL mongodb://localhost:3002/meteor;
    env ROOT_URL http://www.foo.com;

    get the error: “invalid number of arguments in “env” directive”.

    The below worked:

    env MONGO_URL=mongodb://localhost:3002/meteor;
    env ROOT_URL=http://www.foo.com;

  • http://www.phusion.nl/ Hongli Lai

    You’re right, that was a typo, which has now been fixed. Thanks for spotting that.

  • http://eldog.me.uk/ Lloyd Henning

    This is very cool and a fun way to deploy your own meteor sites. Thanks!

    For those who use Meteor.settings for config in their sites and are wondering about METEOR_SETTINGS you can set that too by doing something like this

    # NGINX conf

    server {

    passenger_set_cgi_param METEOR_SETTINGS ‘{“someSettings”:{“someOtherSetting”:”Some value”}}';


    }

  • hipertracker

    Does it support sticky session?

  • http://www.phusion.nl/ Hongli Lai

    Actually, yes, it does! It has been introduced in 4.0.29 but is for now an undocumented feature. You can learn more here: https://groups.google.com/forum/#!topic/phusion-passenger/wT-QiSlfwFU

  • Alex Babichev

    passenger_app_env production; – don’t work. app allways starts only in development mode.

  • JayRoe

    I’ve been using Passenger with Nginx for development, but had to stop. On code change, Passenger with its Nginx modification causes my app to fully stop and start which takes up to half a minute whereas without their Nginx modification Meteor restarts normally in only a few seconds.

  • http://www.phusion.nl/ Hongli Lai

    We haven’t seen this behavior before and it isn’t supposed to happen. Could you tell us more about this issue? Any address where we can contact you on?

  • JayRoe

    That was swift. You can reach me at jakobrosenberg at gmail dot com.