NGINX Web Server

Brightboxes come with Apache by default, but NGINX is a faster alternative with lower memory requirements. If you don't need all the features of Apache, NGINX is definitely recommended.

The Brightbox GEM does not currently support NGINX, but you can easily set it up manually and use the gem for everything else (monit config, code deploy etc.). It will just create Apache configs that you can ignore.

Installing NGINX

First stop Apache if it is running. If Apache is listening on port 80, the NGINX install will not complete successfully.

sudo monit apache stop

Then install NGINX from The Brightbox Ubuntu Apt Repository. Some of the configuration requires nginx 0.6, which is in the testing repository.

sudo apt-get update
sudo apt-get install nginx

Point your web browser to your Brightbox server and you should see the 'Welcome to nginx!' holding page.

You can prevent Apache from starting up on the next boot like this:

sudo update-rc.d -f apache2 remove

Base config

In /etc/nginx/nginx.conf put this base config:

# Run as the www-data user
user www-data;
 
# For high performance you'll need one worker process per disk spindle
# but in most cases 1 or 2 is fine.
worker_processes 2;
 
error_log  /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
 
events {
  # Max concurrent connections = worker_processes * worker_connections
  # You can increase this past 1024 but you must set the rlimit before starting
  # ngxinx using the ulimit command (say ulimit -n 8192)
  worker_connections 1024;
  # Linux performance awesomeness on
  use epoll;
}
 
http {
  server_names_hash_bucket_size 64;
  # More Linux performance awesomeness
  sendfile on;
  tcp_nopush  on;
  tcp_nodelay off;
 
  # Where to store the body of large client requests on disk
  # NGINX will stream this to disk before posting it to your Mongrels,
  # preventing slow clients tying up your app.
  client_body_temp_path /var/spool/nginx-client-body 1 2;
 
  # Max size of a request from a client (usually a POST).  This will limit
  # the size of file uploads to your app
  client_max_body_size 32m;
 
  ## MIME stuff
  # Mime-type table
  include /etc/nginx/mime.types;
  # Default mime-type if nothing matches from the table
  default_type application/octet-stream;
 
  ## Logging
  # Specify a log format compatible with Apache's combined format
  log_format main '$remote_addr - $remote_user [$time_local] '
                '"$request" $status $body_bytes_sent "$http_referer" '
                '"$http_user_agent" "$http_x_forwarded_for"' ;
 
  access_log /var/log/nginx/access.log main;
 
  ## Compression
  gzip on;
  gzip_http_version 1.0;
  gzip_comp_level 2;
  gzip_proxied any;
  gzip_min_length  1100;
  gzip_buffers 16 8k;
  gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;
  # Some version of IE 6 don't handle compression well on some mime-types, so just disable for them
  gzip_disable "MSIE [1-6].(?!.*SV1)";
  # Set a vary header so downstream proxies don't send cached gzipped content to IE6
  gzip_vary on;
 
  # Send along useful info to the mongrels
  proxy_set_header  X-Real-IP  $remote_addr;
  proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header Host $http_host;
  proxy_redirect false;
  proxy_max_temp_file_size 0;
 
  server {
    listen 80;
    root /home/rails/default;
  }
 
  include /etc/nginx/sites-enabled/*;
}

Virtual host config

Create configs for each virtual host in /etc/nginx/sites-available like the template below, then symlink them into /etc/nginx/sites-enabled and reload nginx. appname should be the name you used when running the Brightbox gem, but it doesn't have to be.

upstream appname_mongrels {
  # The fair module ensure requests are sent to the least busy mongrel, rather than
  # the default round robin behaviour.  Comment out if you don't have nginx compiled
  # with the fair proxy balancer module.
  fair; 
  # List your mongrel servers
  server 127.0.0.1:9200;
  server 127.0.0.1:9201;
}
server {
  server_name www.example.com;
  root /home/rails/appname/current/public;
  access_log /var/log/web/appname.log main;

  # Capistrano maintenance message support
  if (-f $document_root/system/maintenance.html) {
    rewrite ^(.*)$ /system/maintenance.html last;
    break;
  }

  location / {
    ## General Rails error page stuff
    error_page 404              /404.html;
    error_page 422              /422.html;
    error_page 500 502 503 504  /500.html;
    error_page 403              /403.html;


    # If the file exists then stop here. Saves 4 more stats and some
    # rewrites.
    if (-f $request_filename) { 
      break; 
    }
    # Rails page caching
    if (-f $request_filename/index.html) {
      rewrite (.*) $1/index.html break;
    }
    if (-f $request_filename.html) {
      rewrite (.*) $1.html break;
    }
    # If it hasn't been handled above, and isn't a static file
    # then send to the mongrels
    if (!-f $request_filename) {
      proxy_pass http://appname_mongrels;
    }
  }
}

A note on configuring SSL

You need a separate server declaration listening on 443 with the following additional options:

  ssl on;
  ssl_certificate /etc/ssl/certs/myssl.crt;
  ssl_certificate_key /etc/ssl/private/myssl.key;
  proxy_set_header X_FORWARDED_PROTO https;

It turns out, array directive overrides (such as proxy_set_header) will clear out any directives set at a higher level. Hence when you set X_FORWARDED_PROTO in for your ssl server, you will also need to set up all the other proxy_set_header directives again. Since I'm generating my server blocks with erb during my cap deployment I was able to move the declarations but still keep things dry.

Monit service monitoring

First of all delete the Apache monitoring config file :

sudo rm /etc/monit/conf.d/apache.monitrc

Then create a new config file for monitoring Nginx in /etc/monit/conf.d/nginx/monitrc :

check process nginx with pidfile /var/run/nginx.pid
  start program = "/etc/init.d/nginx start"
  stop program  = "/etc/init.d/nginx stop"
  group server

Finally we need to resart monit :

sudo /etc/init.d/monit restart
docs/nginx.txt · Last modified: 1 Jun 2008 @ 5:19 pm by robd