Common passenger config - abletech/easy-deployment GitHub Wiki

Common Apache uses with rails/passenger applications

NOTE: Many of these features require one or more apache modules, which means you cannot use PassengerHighPerformance on (which disables all other apache modules) at the same time.

Default apache/passenger VirtualHost template.

easy-deployment contains a template for the most common used setup at https://github.com/AbleTech/easy-deployment/blob/master/lib/easy/generators/templates/stage/apache.conf.tt

Here is a basic example:

<VirtualHost *:80>
  ServerName www.example.com

  DocumentRoot /var/apps/APPLICATION/current/public
  RackEnv production

  # Passenger tuning
  # at least 1 prevents passenger going to sleep after 15min inactivity, increase as desired
  PassengerMinInstances 1
  # Pre-load app on deploy. This needs to match the ServerName above
  # PassengerPreStart http://www.example.com
  # If you don't need any apache mods within this VirtualHost, you may turn this on
  # PassengerHighPerformance on

  <Directory /var/apps/APPLICATION/current/public>
    AllowOverride all
    Options -MultiViews
  </Directory>
</VirtualHost>

URL Rewriting

This requires the apache module mod_rewrite to be enabled (which it is by default on most platforms). In order to enforce presence of the www subdomain, place the following config within your VirtualHost entry:

ServerName www.example.com
ServerAlias example.com
# Rewrite requests with no subdomain to www.
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
RewriteRule ^(.*)$ http://www.example.com$1 [R=301,L]

Rails asset serving

This requires the apache module mod_expires to be enabled. Place the following config within your VirtualHost entry:

<Location /assets/>
  # Use of ETag is discouraged when Last-Modified is present
  Header unset ETag
  FileETag None
  # RFC says only cache for 1 year
  ExpiresActive On
  ExpiresDefault "access plus 1 year"
</Location>

SSL (https enforced)

If you are running a site which requires SSL (for example if someone logs-in to your site), it is recommended to simply enforce all pages to be served via HTTPS. The cpu overhead is minimal (despite what historic wisdom may tell you). This requires the apache modules mod_ssl and mod_rewrite.

Benefits to serving all traffic off HTTPS:

  • reduces the need for application logic to enforce SSL in certain areas of the application
  • prevents cookies being stolen by methods such as employed by firesheep when your users later browse via HTTP
  • ensures the page serving a login form is served off HTTPS and hence the form target cannot be modified en-route.

For more information about generating SSL keys and certificates, read more at:

Example configuration:

# Redirect HTTP users to HTTPS
<VirtualHost *:80>
  ServerName www.example.com
  RewriteEngine On
  Redirect permanent / https://secure.example.com/
</VirtualHost>

# Serve site off HTTPS
<VirtualHost *:443>
  ServerName secure.example.com

  SSLEngine on
  SSLProtocol all -SSLv2
  SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
  SSLCertificateFile      /etc/ssl/private/secure.example.com.crt
  SSLCertificateKeyFile   /etc/ssl/private/secure.example.com.key
  # SSLCertificateChainFile /etc/ssl/private/intermediate.crt

  DocumentRoot /var/apps/APPLICATION/current/public
  RackEnv production

  # Passenger tuning
  # at least 1 prevents passenger going to sleep after 15min inactivity, increase as desired
  PassengerMinInstances 1
  # Pre-load app on deploy. This needs to match the ServerName above
  # PassengerPreStart https://secure.example.com:443/
  # We need apache modules in here.
  PassengerHighPerformance off

  <Directory /var/apps/<%= application_name %>/current/public>
    AllowOverride all
    Options -MultiViews
  </Directory>

</VirtualHost>

SSL (https and http traffic)

If you want to serve both http and https traffic, you could have two near identical blocks both with passenger configured, but then you'd have two application instances managed separately, wasting resources. Here is an alternate solution which employs having the dynamic passenger application running on HTTP (port 80), and VirtualHost running HTTPS (port 443) which instead of loading another passenger instance, instead handles SSL, and then passes plain HTTP request to the other local HTTP instance running passenger.

This requires both mod_ssl for SSL encryption, mod_headers to ensure the HTTP site knows that the original request was encrypted and mod_proxy to proxy requests from HTTPS to the HTTP instance. This example also assumes that this is the only site running under this apache instance.

# Run the application under HTTP
<VirtualHost *:80>
  ServerName www.example.com

  DocumentRoot /var/apps/APPLICATION/current/public

  PassengerEnabled on
  RackEnv production

  PassengerMinInstances 1
  PassengerPreStart http://www.example.com/
  PassengerHighPerformance on

  <Directory /var/apps/APPLICATION/current/public>
    Options -MultiViews
    Options FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
  </Directory>

</VirtualHost>

# Provide an HTTPS entry point as well
<VirtualHost *:443>
  ServerName www.example.com

  SSLEngine on
  SSLProtocol all -SSLv2
  SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
  SSLCertificateFile      /etc/ssl/private/www.example.com.crt
  SSLCertificateKeyFile   /etc/ssl/private/www.example.com.key
  # SSLCertificateChainFile /etc/ssl/private/intermediate.crt
  RequestHeader set X_FORWARDED_PROTO 'https'

  DocumentRoot /var/apps/APPLICATION/current/public

  # This is just passing a proxy to a localhost server
  ProxyRequests Off
  ProxyPreserveHost On

  <Proxy *>
    Order deny,allow
    Allow from all
  </Proxy>

  ProxyPass / http://localhost/
  ProxyPassReverse / http://localhost/
</VirtualHost>
⚠️ **GitHub.com Fallback** ⚠️