Created
April 17, 2012 20:40
-
-
Save borgand/2408849 to your computer and use it in GitHub Desktop.
Nginx mass-virtualhosting with Unicorn and rails
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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