Skip to content

Phusion Passenger: Node.js tutorial

Hannah Wolfe edited this page May 30, 2017 · 58 revisions

Phusion Passenger™ is an open source, polyglot (multi-language) application manager. It takes a lot of complexity out of deploying Node.js, and adds powerful enterprise-grade features that are useful in production. It also makes administering Node.js apps much easier. It has already done this for Ruby, Python and Meteor, and is being used by high-profile companies such as Apple, Pixar, New York Times, AirBnB, Juniper etc as well as over 350.000 websites.

5 minute intro: Making node.js deployment enjoyable (DotJS Paris 2013)

Learn more: Website | Documentation | Support resources | Github | Twitter | Blog

Node.js Phusion Passenger

Table of contents

  1. Understanding Phusion Passenger
  2. Getting started
  3. Understanding what happened
  4. Deploying to production
  5. Using Passenger in development
  6. Caveats
  7. Management and inspection
  8. Troubleshooting
  9. Conclusion

1. Understanding Passenger


Phusion Passenger wraps Node.js, makes it simpler to deploy,
adds management tools and other useful production features.

Why use Node.js on Passenger?

Here are some of the benefits that you will gain:

  • The power of Nginx
    Phusion Passenger combines Node.js with the increasingly popular Nginx web server. By combining them, Nginx will offload Node.js from serving static assets. This also adds a buffering reverse proxy layer which provides I/O security and protects Node.js against invalid HTTP requests, slow clients, etc. It will even allow you to use SSL without having to code explicit SSL support in your Node app.

    Nginx isn't the only thing supported though. Passenger also supports Apache, and can even run standalone without needing an existing web server.

  • Multitenancy
    Run multiple Node.js applications on a single server easily and without hassle.

  • Process management and supervision
    Node.js processes are automatically started, and automatically restarted when they crash.

  • Statistics and insight
    Phusion Passenger provides tools for inspecting the applications' status, such as what requests they're currently processing, how many requests they've processed.

  • Scaling and load balancing
    Based on current traffic, Phusion Passenger can spawn more Node.js processes to handle the load, or spin down some existing Node.js processes to conserve resources. Phusion Passenger automatically load balances traffic across Node.js processes. The load balancing mechanism utilizes a smart "first-available" selection algorithm to avoid problems caused by slow requests. Although Node.js is single-threaded, this approach allows you to utilize multiple CPU cores.

  • I/O security
    Node.js is automatically put behind a buffering web server, such as Nginx or Apache, which preprocesses and postprocesses HTTP requests and responses. This protects the Node.js app against slow-client attacks such as Slowloris. It also provides a secure environment which sanitizes HTTP headers, to protect against vulnerabilities in the app's HTTP parser.

  • System security
    Node.js processes are automatically started as the user which owns the app. This allows the OS to separate their privileges, so that a vulnerability in one app does not affect another.

  • Static file acceleration
    Static files are directly served by the web server (Nginx/Apache), not by Node.js. This offloads the Node.js application from handling those things.

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 Node.js 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. The result probably does not even 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.

How does it work?

Instead of using Node.js directly, you use Phusion Passenger, which in turn manages Node.js.

Passenger and Nginx form an integrated whole. As a user, you don't deal with Passenger and Nginx separately: you deal with both of them at the same time. This makes the system considerably easier to administer. You configure Passenger by editing the Nginx configuration file. You start and shutdown Passenger by starting and shutting down Nginx.

Passenger and Nginx receive requests and forwards them to Node.js. Passenger internally sets up Nginx reverse proxy rules. This reverse proxy layer sanitizes HTTP headers and provides buffering, which protects Node.js against slow clients.

Further under the hood, Passenger manages multiple Node.js processes and load balances traffic amongst them. If a process crashes, it is restarted. By using multiple processes, Passenger allows you to take advantage of multiple CPU cores (1 process can use 1 core), even though Node.js is single-threaded. Again, you never have to deal with all the Node.js processes individually. You only deal with Passenger, which takes care of all this for you.

Any requests that can be mapped to a static file on disk, will be handled immediately by Nginx, and the request never reaches Node.js. Nginx is highly optimized at serving static files, and does a much better job at it than Node.js. This offloads Node.js for only the most important requests, namely the dynamic ones.

Passenger also introduces a management and inspection console. Normally it's very hard to see what your Node.js app is doing. What request is it handling? How much CPU and memory is it using? Is it maybe stuck or malfunctioning? Is it under heavy load? Because Passenger keeps score of statistics, all these questions can be answered with the Passenger management and inspection tools.

Some readers may immediately recognize that Passenger is Unix. This is a traditional Unix process supervision architecture. The architecture leverages a lot of powerful Unix features. For example, the communication links between Passenger and Node.js are not TCP sockets, but are high-performance Unix domain sockets. The supervision code utilizes POSIX process management APIs.

Multiple integration modes

Note that "Nginx" in the previous diagram can be replaced by "Apache". This is because Passenger supports three modes:

  • An Nginx integration mode, which works as previously described.
  • An Apache integration mode, which is exactly like the Nginx integration mode, but with Apache.
  • A Standalone mode. Whereas the Nginx integration mode requires you to install and configure Nginx, the Standalone mode works as a single standalone server. Under the hood it still uses Nginx and things still work like in the previous diagram, but all the complexity is encapsulated in a single command on the command line.

The manual documents the differences between the multiple integration modes. In this tutorial, we'll first introduce you to the Standalone mode because it's the easiest to work with. Then we'll slowly cover the other modes as well.

What Passenger doesn't do

Passenger follows the Unix philosophy of doing a small number of things, but doing them well. So there are a number of things that are (currently) outside Passenger's scope. Passenger may or may not take care of some of these some time in the future.

  • Setting up a server with an operating system
    Passenger assumes that you already have a server with an working operating system on it. Passenger is not a hosting service. It is software that is to be installed on a server.
  • Installing Node.js
    To run Node.js apps on Passenger, you must already have Node.js installed. Passenger doesn't do that for you. Passenger doesn't care how you install Node.js though; you sometimes just need to tell Passenger where Node.js is.
  • Transferring the application code and files to the server
    Passenger does not transfer the application code and files to the server for you. To do this, you must use tools like Git, scp, FTP, Capistrano, Fabric, etc. Passenger assumes that the application code and files are already on the server, and does not care which tool you use to make that so.
  • Installing application dependencies
    Passenger does not install your application's dependencies for you.
  • Managing the database
    If your application requires a database, then Passenger does not install that database for you, nor does it sets up database accounts and tables for you. They must already be set up by the time you deploy your application to Passenger.
  • Managing auxiliary daemons and services
    If your application requires additional daemons and services, e.g. Memcached or Redis, then Passenger does not manage those. They must already be running.
## 2. Getting started

Installing

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

Make sure you get a version that is recent enough. This tutorial assumes at least version 4.0.37.

Prepare your app

One of the philosophies behind Phusion Passenger is convention over configuration. In practice, many web apps share many structural commonalities. For example, many web frameworks use server.js as the program's entry point, and most web apps have a directory in which they store static assets.

Phusion Passenger leverages this property to make your life easier. It assumes this convention by default. If your app follows these conventions then you get many features out of the box, without any configuration. If your app does not follow these coventions then you can still tell it what the structure actually is, by passing a few configuration options.

Here is the Phusion Passenger convention:

application directory
  |
  +-- app.js
  |
  +-- public/
  |
  +-- tmp/
  • app.js is the entry point of your application. Phusion Passenger starts your application by loading that file. It must register a request handler, as documented later.
  • The 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.

Perhaps your app only follows this convention partially, or perhaps not at all. For simplicity reasons, this tutorial will first cover apps that follow this convention, so for now please modify your app to fit this structure. This tutorial will later teach you how to make Passenger work with any structure.

Example app

Let's create an example Node.js app directory structure:

mkdir passenger_node_test
mkdir passenger_node_test/public
mkdir passenger_node_test/tmp
cd passenger_node_test
nano app.js

Enter the following code for app.js. This small example application starts an HTTP server, and responds to every request with the message "hello world!".

var http = require('http');
var server = http.createServer(function(req, res) {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end("hello world!\n");
});
server.listen(3000);

Now start your application inside Phusion Passenger's Standalone mode:

$ passenger start
=============== Phusion Passenger Standalone web server started ===============
PID file: /Users/phusion/passenger_node_test/passenger.3000.pid
Log file: /Users/phusion/passenger_node_test/passenger.3000.log
Environment: development
Accessible via: http://0.0.0.0:3000/

You can stop Phusion Passenger Standalone by pressing Ctrl-C.
Problems? Check http://www.modrails.com/documentation/Users%20guide%20Standalone.html#troubleshooting
===============================================================================

Open another terminal, and make a request to your app:

$ curl http://0.0.0.0:3000/
hello world!

Understanding what happened

The previous instructions worked like magic, but what happened? Under the hood, Passenger took care of a lot of stuff for you, and there's a lot of complexity that Passenger is hiding for you. However you should have a good understanding of what Passenger does, so that you know what to do when there are problems.

So here's a rundown of what happened earlier:

  • You created a Node.js application directory structure in the format Phusion Passenger expects it.
  • app.js is the entry point to your application.
  • Instead of running node app.js, you ran passenger start. This command starts Phusion Passenger in its Standalone mode. The Standalone mode does not require Nginx or Apache.
  • Passenger is now serving and managing your application.

Port binding

There is also some magic involved with regard to port binding. Normally, a Node.js app binds a server socket on a certain port by calling listen() on an http.Server object. But when run in Phusion Passenger, this control is inversed:

  1. The user tells Phusion Passenger which port to listen on (if not specified, port 3000 is chosen).
  2. Phusion Passenger makes the Node.js app listen on some other, randomly available port.
  3. Phusion Passenger forwards requests to Node.js. This is what allows Phusion Passenger to load balance between multiple Node.js processes.

Phusion Passenger implements this on the Node.js side by hooking into the first http.Server object in your app that calls listen(). That http.Server object will be selected as the server object to receive requests.

When run in Phusion Passenger, the port number that you pass to listen() is irrelevant and has no effect. Instead of 3000 we could just as easily have written 4000. The fact that Phusion Passenger Standalone runs on port 3000 by default is not related to what you pass you listen().

This means that most Node.js applications will work out of the box on Phusion Passenger, even if they are already configured to run on a specific port.

Changing the port

Since control is inversed, you, the user, control a lot of the operational parameters of your application by configuring Passenger. This also means that you don't have to write extra code to make your app configurable: Passenger already takes care of that for you, to a certain extent.

Let's continue with some basic operational configuration. Passenger Standalone runs on port 3000 by default. You can tell it to run on another port by passing the --port option. Press Ctrl-C to stop your existing Passenger Standalone instance, and run:

$ passenger start --port 3001
=============== Phusion Passenger Standalone web server started ===============
PID file: /Users/phusion/passenger_node_test/passenger.3001.pid
Log file: /Users/phusion/passenger_node_test/passenger.3001.log
Environment: development
Accessible via: http://0.0.0.0:3001/

You can stop Phusion Passenger Standalone by pressing Ctrl-C.
Problems? Check http://www.modrails.com/documentation/Users%20guide%20Standalone.html#troubleshooting
===============================================================================

Let's try it out. Open another terminal and run:

$ curl http://0.0.0.0:3001/
hello world!

Voila, it worked! Notice that app.js still calls listen(3000)? As explained before, the argument passed to listen() doesn't have any effect. Only the --port option does.

Process spawning

Remember the diagram from How does it work? At its core, Passenger is a process manager and starts and stops Node.js processes for you. How can you see what processes are running? There's a tool for that! passenger-status gives you an overview of all your processes, how much CPU and memory they're using, etc.

$ passenger-status
Version : 4.0.37
Date    : 2013-11-14 21:55:30 +0100
Instance: 25002
----------- General information -----------
Max pool size : 6
Processes     : 1
Requests in top-level queue : 0

----------- Application groups -----------
/Users/phusion/nodetestapp#default:
  App root: /Users/phusion/nodetestapp
  Requests in queue: 0
  * PID: 25012   Sessions: 0       Processed: 2       Uptime: 9s
    CPU: 0%      Memory  : 14M     Last used: 3s ago

By default, Passenger only starts a single Node.js process per application. We can use the --min-instances option to tell it to spawn more. Press Ctrl-C to stop your existing Passenger Standalone instance, and run:

passenger start --port 3001 --min-instances 2

Now open another terminal and run:

$ passenger-status
Version : 4.0.37
Date    : 2013-11-14 21:58:20 +0100
Instance: 25019
----------- General information -----------
Max pool size : 6
Processes     : 1
Requests in top-level queue : 0

----------- Application groups -----------
/Users/phusion/nodetestapp#default:
  App root: /Users/phusion/nodetestapp
  Requests in queue: 0
  * PID: 25024   Sessions: 0       Processed: 1       Uptime: 9s
    CPU: 0%      Memory  : 14M     Last used: 3s ago
  * PID: 25025   Sessions: 0       Processed: 0       Uptime: 9s
    CPU: 0%      Memory  : 14M     Last used: 3s ago

As you can see, there are now two Node.js processes. Passenger automatically balances requests between the two of them.

Maximum number of processes

Passenger is designed to be safe and robust as well. That means it tries very hard not to overuse your server's resources and make it crash. For this reason, Passenger has a setting which controls the maximum number of application processes it may spawn. It will never spawn more than this number of processes unless you explicitly increase the limit. The limit is controlled with --max-pool-size, and at the time of writing (version 4.0.37) the default is 6.

For example, try running:

passenger start --min-instances 8

You will see that Passenger only spawns 6 processes, no more. The following lifts the limit:

passenger start --min-instances 8 --max-pool-size 8

So what does this mean for you?

  • Each process can leverage a different CPU core. So spawning more processes allows you to leverage more cores.
  • It does not make sense to have more Node.js processes than the number of CPU cores.
  • If you spawn too many processes, your server may run out of memory, and processes will start becoming slow or start crashing. So keep an eye on your memory usage and decrease the number of processes if you notice that it's eating away your RAM.

You might especially be interested in this article: Tuning Phusion Passenger's concurrency settings.

Process supervision

The cool thing about Passenger is that it restarts processes that crash! Let's try it out. Tell Passenger to spawn two processes.

passenger start --min-instances 2

Run passenger-status and obtain the PID of a random process. Then kill that process to simulate a crash.

passenger-status
kill <PID>

Wait a few seconds, and run passenger-status again. Notice that the original process is gone, but that it has been replaced by another one!

The characteristics of having multiple processes

You've most likely only ever worked with a single Node.js process so far. Having multiple Node.js processes changes things somewhat. There are some strong caveats that you should be aware about.

First, what is a process anyway other than an entry in ps or passenger-status? A process is an instance of a computer program that is isolated from other processes. "Isolated" means that processes don't share memory with each other. Suppose that your program has a variable A with initial value A = 1. If you run two instances of your program -- two processes -- and you tell one process to set A = 2, then the value 2 is only visible to that process. The other process still thinks A == 1!

This is in contrast to threads. A thread runs inside a process, so if a thread changes a value, all other threads in the same process see the change.

But you can't change variables in your program and expect all processes to see the changes. They don't. So how do you communicate changes to all your processes? By using a shared data store, which can be:

  • The database.
  • Redis.
  • Memcached.

Another characteristic about processes is that, if one process crashes, others are unaffected. This is also in contrast to threads: if a thread crashes and is unable to recover from the crash, then the entire process crashes with all its threads in it.

This is why Passenger likes having multiple processes. If one process crashes, no problem, the other can (temporarily) take over while Passenger spawns a new one. This is also why Passenger itself is its own process: so that Node.js can't take down Passenger.

NODE_ENV

Many Node.js web frameworks use the NODE_ENV environment variable to determine whether they should operate in development or in production mode. Phusion Passenger automatically sets this environment variable.

The Standalone mode is primarily meant to be a development tool, so it sets NODE_ENV to development by default. You can change this by passing --environment:

passenger start --environment production

As you will learn later, the Nginx integration mode and Apache integration mode are primarily meant for production, so they set NODE_ENV to production by default. You will later learn how to change the NODE_ENV value for those modes.

Further configuration

There are many more configuration options. Configuration depends on the integration mode. So far we've only covered the Standalone mode. You can learn more about configuring the Standalone mode in the Passenger Standalone manual.

The Nginx integration mode and the Apache integration mode, which we're going to cover later in this tutorial, are configured differently. They too have their own manuals which cover configuration.

If your app does not follow the convention laid out in Prepare your app, then you can tell Phusion Passenger about its structure by following this guide.

4. Deploying to production

As mentioned before, Passenger has multiple integration modes. You've only worked with the Standalone mode so far. All modes are fit for production, but you might prefer a specific mode in production. So let's go over them.

Deploying Standalone

If you have no experience with Nginx and Apache, then deploying the Standalone mode directly is by far the easiest. This way you don't have to deal with Nginx and Apache at all.

On the downside - unless you're using the Mass Deployment feature in the Enterprise variant - Passenger Standalone can only serve 1 Node.js application at the same time. Serving multiple applications at the same time requires you to start multiple Passenger Standalone instances, and to attach them to a reverse proxy. That makes things quite complicated, so if you want to serve multiple applications then you should use the Nginx or Apache integration mode.

Anyway, here's how you deploy a single Passenger Standalone instance to production.

  1. Install Phusion Passenger on your server.

  2. Copy over your application to your server and install its dependencies, set up a database for it, etc.

  3. Login to your server and change the working directory to your application.

  4. Run Passenger Standalone on port 80, and after binding to port 80, drop its privileges. Also tell it to start the app with NODE_ENV=production, and to daemonize into the background.

    sudo passenger start --port 80 --user someusername --environment production --daemonize
    

    Here, someusername should be the user that you want to run your application as. As a rule, never run your application as root. That is insecure!

  5. Configure Passenger Standalone to start at boot.

Deploying on Nginx or Apache

In the Nginx and Apache integration modes, Phusion Passenger acts as an Nginx or Apache module, so it is automatically started along with the web server. If you already have experience with Nginx or Apache then these modes are better suited for you. These modes make it trivial to serve multiple Node.js applications.

First, install Phusion Passenger in Nginx or in Apache mode. Deploying an app is then 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.

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

Nginx:

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

Apache:

<VirtualHost *:80>
    ServerName www.foo.com
    DocumentRoot /webapps/foo/public
</VirtualHost>

If you 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 Node.js application.

The first request is slower

Notice that the first request that you made to http://www.foo.com/ is slower than usual? That's because when run in the Nginx or Apache integration mode, your application is not started until the first request. You can make Passenger start your application during web server startup by using these configuration options:

NODE_ENV is set to production by default

As mentioned earlier, the Nginx and Apache integration modes set NODE_ENV to production by default. You can set a different value by passenger_app_env (Nginx) and PassengerAppEnv (Apache):

  • passenger_app_env development
  • PassengerAppEnv development

Configuration

While the Standalone mode is usually configured through command line options, the Nginx/Apache integration modes are configured through the Nginx/Apache configuration files. There are many configuration options that you can tweak. For example you can set the number of processes you want, you can set a memory limit, etc. Please refer to the Phusion Passenger manuals.

Automatic user switching

Nginx and Apache are usually configured to run as the www user. Does that mean your Node.js applications are also run as that user? The answer is no. Since Passenger was designed to be multitenant, we wouldn't want one Node.js application to be able to modify and mess with the files of another Node.js application on the same machine, especially not because of a vulnerability in the application. So running all Node.js applications under the same user as the web server would open a huge security hole.

Passenger has had a remedy for this problem since version 1.0, through the Automatic User Switching feature. Simply put, your Node.js application is run as the owner of app.js, unless you configure it otherwise. Of course you still have to make sure that each of your applications is owned by another user.

Note that Automatic User Switching is only supported in the Nginx and Apache integration modes, not in Standalone.

Redeploying (restarting) an application

Suppose that you've deployed a new version of your application. The old version is still running, so how do you make it restart?

As explained in Prepare your app, you can trigger a restart by touching the file tmp/restart.txt. On the next request, your application will be restarted: the old processes will be gone, and Passenger will spawn new processes.

5. Using Passenger in development

Should Passenger be used in development as well?

With all the focus on production, should Passenger be used during development as well? Yes it should!

Let me be clear: you are in no way obliged to use Passenger in development. You can develop in pure Node.js, then deploy with Passenger. But it is generally a good idea to let your development environment match the production environment as closely as possible. Otherwise you may run into unexpected problems during production.

Restarting your application on every request

Passenger also provides one nice development feature: the ability to restart your application on every request. If you're not using a Node.js framework that supports hot code reloading during development, then the mechanism that Passenger provides is a nice alternative.

To activate this mechanism, create the file tmp/always_restart.txt. As long as the file exists, Passenger will restart your application on every request.

6. Caveats

Don't mess with stdout or stderr

Phusion Passenger uses stdout and stderr to communicate with the application. It is safe for you to log messages to stdout and stderr, but don't do things like redirecting them to a file. Doing so will make Phusion Passenger think your app froze during startup, because it never receives a message back.

The close event might not work as expected

If your app listens for the close event on requests, then you may find that the close event isn't fired when the client disconnects. For more information, please refer to this StackOverflow question.

Restarting apps that serve WebSocket or other long-running connections

At the time of writing (September 15 2014), whenever you tell Phusion Passenger to restart an app, it will first wait for all its connections to terminate before actually restarting the app. The intention is to prevent clients from experiencing error messages. Unfortunately this does not work well with WebSockets or other long-running connections (e.g. long polling with long timeouts). When you try to restart an app that's currently serving such a long-running connection, you will see that Phusion Passenger waits indefinitely, until the connection terminates:

----------- Application groups -----------
/Users/phusion/Sites/socketio.test#default:
  App root: /Users/phusion/Sites/socketio.test
  Requests in queue: 0
  * PID: 5542    Sessions: 1       Processed: 6       Uptime: 21s
    CPU: 0%      Memory  : 49M     Last used: 19s ago
    Shutting down...

Phusion Passenger 4.0.52 introduces a temporary solution for this problem. By setting the _PASSENGER_NODE_CONTROL_SERVER environment variable, whenever you issue a restart command, Phusion Passenger will force the app to exit. All connections, both short-running connections (e.g. normal HTTP requests) and long-running connections, will be terminated.

Phusion Passenger 5 is going to introduce a cleaner solution, so that only long-running connections are aborted. Until then, this temporary solution is the way to go. This temporary solution will be removed once Phusion Passenger 5 is released, which is why environment variable name is prefixed with an underscore.

To use it in Passenger Standalone, set the environment variable before invoking passenger start:

export _PASSENGER_NODE_CONTROL_SERVER=1
passenger start ...

To use it in Phusion Passenger for Nginx, set the environment variable with passenger_set_cgi_param:

server {
    listen 80;
    server_name ...;
    root ...;

    passenger_enabled on;
    passenger_set_cgi_param _PASSENGER_NODE_CONTROL_SERVER 1;
}

To use it in Phusion Passenger for Apache, set the environment variable with SetEnv:

<VirtualHost *:80>
    ServerName ...
    DocumentRoot ...
    SetEnv _PASSENGER_NODE_CONTROL_SERVER 1
</VirtualHost>

7. Management and inspection

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. You've already been introduced to this tool in section Understanding what happened.

Passenger-status has another mode, one for showing what requests are active and by which process. Run passenger-status --show=requests to see all requests that are currently being handled.

And there is another tool: passenger-memory-stats. This 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.

8. Troubleshooting

If something doesn't work properly then the first place to look at is the global web server error log. This is because Phusion Passenger's stdout and stderr, as well as the stdout/stderr of all spawned applications, are redirected to the error log. You may find the error reason there.

You can find the web server error log as follows:

  • On Apache, this is the file that is configured in the global (not per-vhost) ErrorLog directive, and on most systems the default is /var/log/apache2/error.log.
  • On Nginx, this is the file that is configured in the global error_log directive. The error_log directive may also appear in the http section, but beware: that one is not the global error log. The default filename is $PREFIX/logs/error.log on self-compiled Nginx installations, where $PREFIX is the prefix on which you configured Nginx. For example, if you configured Nginx with --prefix=/opt/nginx, then the default error log location is /opt/nginx/logs/error.log. If you installed Nginx with a native package (e.g. through APT or YUM) then the default filename is probably /var/log/nginx/error.log.

Do you not see a useful message in the log file? Raise PassengerLogLevel or passenger_log_level to see more verbose messages.

If things still don't work, try consulting the Troubleshooting section in the manual. Or you can consult one of the support resources.

9. Conclusion

Passenger's background: where did it come from?

Phusion Passenger began in early 2008 was originally made to serve Ruby web applications. Since then, it has grown to be the most popular application server for Ruby. Unlike most Ruby application servers, both now and then, Phusion Passenger is designed to integrate with the web server, to take as much management work out of the administrator's hands, and generally to be "zero-maintenance".

But from the start, it was designed not to be Ruby-only. It was a little-known fact that Phusion Passenger also supported Python as early as mid-2008. Although we never marketed Python support and although we've always called our Python support "experimental", hosting providers such as Dreamhost were already successfully using it in production for serving Django and other Python apps.

In late 2012 we decided to raise Python support to a more official status, namely the beta status. In 2013, Python support was made production-ready, and Node.js and Meteor support were introduced.

Further reading

Please take a look at the extensive documentation. To stay up to date with the latest developments, please follow us on Twitter or follow the Phusion blog.

Your feedback is valuable!

We'd like to hear from you if you're using Phusion Passenger to host Node.js 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!

Please enjoy Phusion Passenger, a product by Phusion. :-)