Skip to content

Instantly share code, notes, and snippets.

@mikhailov
Created November 23, 2010 15:18
Show Gist options
  • Save mikhailov/711913 to your computer and use it in GitHub Desktop.
Save mikhailov/711913 to your computer and use it in GitHub Desktop.
nginx+passenger (real production config)
# NOTICE: to get Nginx+Unicorn best-practices configuration see the gist https://gist.github.com/3052776
$ cd /usr/src
$ wget http://nginx.org/download/nginx-1.2.1.tar.gz
$ tar xzvf ./nginx-1.2.1.tar.gz && rm -f ./nginx-1.2.1.tar.gz
$ wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.30.tar.gz
$ tar xzvf pcre-8.30.tar.gz && rm -f ./pcre-8.30.tar.gz
$ wget http://www.openssl.org/source/openssl-1.0.1c.tar.gz
$ tar xzvf openssl-1.0.1c.tar.gz && rm -f openssl-1.0.1c.tar.gz
$ gem install passenger -v=3.0.12 --no-ri --no-rdoc
$ passenger-install-nginx-module --nginx-source-dir=/usr/src/nginx-1.2.1 --extra-configure-flags="--with-pcre=/usr/src/pcre-8.30 --with-openssl-opt=no-krb5 --with-openssl=/usr/src/openssl-1.0.1c --with-http_gzip_static_module --with-http_stub_status_module --without-mail_pop3_module --without-mail_smtp_module --without-mail_imap_module"
$ mkdir /tmp/client_body_temp
user app;
worker_processes 2;
worker_priority -5;
error_log /home/app/logs/nginx.error.log crit;
events {
use epoll;
worker_connections 1024;
}
http {
client_max_body_size 25m;
client_body_buffer_size 128k;
client_body_temp_path /tmp/client_body_temp;
passenger_root /usr/local/lib/ruby/gems/1.8/gems/passenger-3.0.12;
passenger_ruby /usr/local/bin/ruby;
passenger_pool_idle_time 0;
passenger_max_pool_size 15;
passenger_pre_start http://127.0.0.1/;
include mime.types;
default_type application/octet-stream;
server_tokens off;
sendfile on;
keepalive_timeout 70;
gzip on;
gzip_http_version 1.1;
gzip_disable "msie6";
gzip_vary on;
gzip_min_length 1100;
gzip_buffers 64 8k;
gzip_comp_level 3;
gzip_proxied any;
gzip_types text/plain text/css application/x-javascript text/xml application/xml;
ssl_certificate /opt/nginx/ssl_certs/cert.crt;
ssl_certificate_key /opt/nginx/ssl_certs/server.key;
ssl_session_timeout 15m;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers RC4:HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
add_header Strict-Transport-Security "max-age=16070400; includeSubdomains";
add_header X-Frame-Options DENY;
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
include /opt/nginx/conf/nginx_host.conf;
}
server {
listen 80;
server_name *.host.com;
rewrite ^(.*) https://$host$1 permanent;
location ~ \.(php|html)$ {
deny all;
}
access_log /dev/null;
error_log /dev/null;
}
# HTTPS server
server {
ssl on;
listen 443 default ssl;
server_name *.host.com;
root /home/app/public_html/host_production/current/public;
try_files $uri /system/maintenance.html @passenger;
location @passenger {
passenger_enabled on;
passenger_min_instances 5;
rails_env production;
passenger_set_cgi_param HTTP_X_FORWARDED_PROTO https;
limit_req zone=one burst=5;
}
error_page 500 502 504 /500.html;
error_page 503 @503;
location = /50x.html {
root html;
}
location = /404.html {
root html;
}
location @503 {
error_page 405 = /system/maintenance.html;
if (-f $document_root/system/maintenance.html) {
rewrite ^(.*)$ /system/maintenance.html break;
}
rewrite ^(.*)$ /503.html break;
}
if ($request_method !~ ^(GET|HEAD|PUT|POST|DELETE|OPTIONS)$ ){
return 405;
}
if (-f $document_root/system/maintenance.html) {
return 503;
}
location ~ ^/(assets|images|javascripts|stylesheets|swfs|system)/ {
gzip_static on;
expires max;
add_header Cache-Control public;
add_header Last-Modified "";
add_header ETag "";
break;
}
location = /favicon.ico {
expires max;
add_header Cache-Control public;
}
location ~ \.(php|html)$ {
return 405;
}
access_log /dev/null;
error_log /dev/null;
}
@mikhailov
Copy link
Author

ivanku, thanks for bugreport.
nginx_host.conf has been updated, please take a look at the line 67

@madcatbiz
Copy link

thanks,

but this:

server_name  *.host.com;

dont work for me, need change to:

server_name  subdomain1.host.com sub2.host.com etc..;

@mikhailov
Copy link
Author

server_name can include wildcard, just take a look at official documentation here http://nginx.org/en/docs/http/server_names.html

@madcatbiz
Copy link

конечно же я читал, но именно *.host.com не срабатывает, нужно было перечислить все поддомены

@mikhailov
Copy link
Author

версия nginx и конфиг?

@madcatbiz
Copy link

centos 5.5
nginx 0.8.54 + passenger 3.0.4

собственно это единственно что у меня не сработало, остальное сделал по вашему конфигу, спасибо

@mikhailov
Copy link
Author

limit_req has been added to location @Passenger

@pmq20
Copy link

pmq20 commented Jan 19, 2012

helpful. thank you very much

@sjoonk
Copy link

sjoonk commented May 7, 2012

Would you mind let us know your system spec for this config? CPU. How many core, and RAM, etc??

@mikhailov
Copy link
Author

@sjoonk it's pretty standard, EC2 HighCPU medium instance

@mikhailov
Copy link
Author

updates:

  • nginx 1.0.15, passenger 3.0.12
  • block unwanted requests by blocking .html (/phpmyadmin, /mysqladmin..)
  • client_max_body_size moved before passenger initialization, because it works in that way only
  • increase limit per zone to 10r/s
  • SSL cache via ssl_session_cache

@mikhailov
Copy link
Author

ssl_session_cache and increased ssl_session_timeout can save 25% of CPU usage

@mikhailov
Copy link
Author

--with-openssl-opt=no-krb5 --with-openssl=/usr/src/openssl-0.9.8x - refer to http://nginx.2469901.n2.nabble.com/nginx-ssl-prefer-server-ciphers-and-MSIE-7-x-core-dump-td3288089.html

@mikhailov
Copy link
Author

SSL config updated

ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!ADH:!MD5;

@mikhailov
Copy link
Author

SSL BEAST attack fixed, locations optimized

@mikhailov
Copy link
Author

openssl upgraded to 1.0.1c to enable TLSv1.1 and TLSv1.2.
Few headers was added by security reasons:
add_header Strict-Transport-Security "max-age=16070400; includeSubdomains";
add_header X-Frame-Options DENY;

@supairish
Copy link

Hey just found this gist, and I've learned a lot from it. Thanks for sharing.
Can I still use something like the following, if my Rails app is using full page caching to the file system? The files get written out with the .html extension.

location ~ .(php|html)$ {
deny all;
}

@mikhailov
Copy link
Author

@supairish yes, you can just remove "|html", the main purpose to use that is to prevent search-bots scans

@mikhailov
Copy link
Author

UPDATE: serve static assets fix

@mikhailov
Copy link
Author

UPDATE: nginx 1.2.1 instead of 1.0.15, it allows me to disable Last-Modified headers for assets

@pmq20
Copy link

pmq20 commented Jun 26, 2012

watching and learnt

@mikhailov
Copy link
Author

We recently moved to Nginx+Unicorn due to some passenger's segmentation faults.
You can try passenger in standalone mode, but compile mod_rails module inside is not recommended now.
Anyway, nginx upstream module help you in both cases: 1) use Unicorn, 2) use Standalone Passenger.

See this config here: https://gist.github.com/3052776.

@mentholiptuz
Copy link

nice config man!

@foton
Copy link

foton commented May 2, 2014

Thank you very much, this config , especially part:

try_files $uri /system/maintenance.html @passenger;

location @passenger {
     passenger_set_cgi_param HTTP_X_FORWARDED_PROTO https;
 }

very helped me.
I lost 1 day to finding out how to send HTTP_X_FORWARDED_PROTO to passenger. Proxy configs was useless.

@kjakub
Copy link

kjakub commented Jun 23, 2014

what location @Passenger means?

@threadhead
Copy link

You really shouldn't use that ssl_protocols line anymore. SSL is not secure. TLS is the new black.

ssl_protocols        TLSv1 TLSv1.1 TLSv1.2;

@ashrafalzyoud
Copy link

can u update it ???

@ashrafalzyoud
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment