Skip to content

Instantly share code, notes, and snippets.

@borgand
Created April 17, 2012 20:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save borgand/2408849 to your computer and use it in GitHub Desktop.
Save borgand/2408849 to your computer and use it in GitHub Desktop.
Nginx mass-virtualhosting with Unicorn and rails
# Mass-virtualhosting configuration for Nginx
# Sets up virtualhosts automatically, in the following way:
# test1.laas.tjs.ee -> /srv/laas/test1
# app.tjs.ee -> /srv/prod/test1
server {
# enable one of the following if you're on Linux or FreeBSD
listen 80 default deferred; # for Linux
# If you have IPv6, you'll likely want to have two separate listeners.
# One on IPv4 only (the default), and another on IPv6 only instead
# of a single dual-stack listener. A dual-stack listener will make
# for ugly IPv4 addresses in $remote_addr (e.g ":ffff:10.0.0.1"
# instead of just "10.0.0.1") and potentially trigger bugs in
# some software.
# listen [::]:80 ipv6only=on; # deferred or accept_filter recommended
client_max_body_size 4G;
# Change to your domain
server_name .tjs.ee;
# ~2 seconds is often enough for most folks to parse HTML/CSS and
# retrieve needed images/icons/frames, connections are cheap in
# nginx so increasing this is generally safe...
keepalive_timeout 5;
# Set vhost to default to host header
set $vhost $host;
# Split up the host header
# NB! Modify to your domain
if ($vhost ~ "^(w{3}\.)?(.*?)\.(.*?)?\.?tjs\.ee$") {
set $vhost $2;
set $dir $3;
}
# If dir is empty, set it to prod
if ($dir ~ "^$") {
set $dir prod;
}
root /srv/$dir/$vhost/public;
# Prefer to serve static files directly from nginx to avoid unnecessary
# data copies from the application server.
try_files $uri/index.html $uri.html $uri @app;
location @app {
# an HTTP header important enough to have its own Wikipedia entry:
# http://en.wikipedia.org/wiki/X-Forwarded-For
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enable this if and only if you use HTTPS, this helps Rack
# set the proper protocol for doing redirects:
# proxy_set_header X-Forwarded-Proto https;
# pass the Host: header from the client right along so redirects
# can be set properly within the Rack application
proxy_set_header Host $http_host;
# we don't want nginx trying to do something clever with
# redirects, we set the Host: header above already.
proxy_redirect off;
# socket is in app_root/tmp/unicorn.sock
proxy_pass http://unix:$document_root/../tmp/unicorn.sock;
}
# Maintenance
if (-f $document_root/maintenance.html) {
return 503;
}
error_page 503 @maintenance;
location @maintenance {
rewrite ^(.*)$ /maintenance.html break;
}
# Rails error pages
error_page 500 504 /500.html;
}
# Calculate basedir from current filename
basedir = File.absolute_path(__FILE__).sub(/(?:\/config\/)unicorn\.conf$/,'')
working_directory basedir
worker_processes 4
pid "#{basedir}/tmp/pids/unicorn.pid"
stderr_path "#{basedir}/log/unicorn.log"
listen "#{basedir}/tmp/unicorn.sock", :backlog => 2048
timeout 30
preload_app true
##
# REE
# http://www.rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
if GC.respond_to?(:copy_on_write_friendly=)
GC.copy_on_write_friendly = true
end
before_fork do |server, worker|
# the following is highly recomended for Rails + "preload_app true"
# as there's no need for the master process to hold a connection
defined?(ActiveRecord::Base) and
ActiveRecord::Base.connection.disconnect!
##
# When sent a USR2, Unicorn will suffix its pidfile with .oldbin and
# immediately start loading up a new version of itself (loaded with a new
# version of our app). When this new Unicorn is completely loaded
# it will begin spawning workers. The first worker spawned will check to
# see if an .oldbin pidfile exists. If so, this means we've just booted up
# a new Unicorn and need to tell the old one that it can now die. To do so
# we send it a QUIT.
#
# Using this method we get 0 downtime deploys.
old_pid = basedir + '/tmp/pids/unicorn.pid.oldbin'
if File.exists?(old_pid) && server.pid != old_pid
begin
Process.kill("QUIT", File.read(old_pid).to_i)
rescue Errno::ENOENT, Errno::ESRCH
# someone else did our job for us
end
end
end
after_fork do |server, worker|
##
# Unicorn master loads the app then forks off workers - because of the way
# Unix forking works, we need to make sure we aren't using any of the parent's
# sockets, e.g. db connection
ActiveRecord::Base.establish_connection
# Redis and Memcached would go here but their connections are established
# on demand, so the master never opens a socket
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment