Nginx and rails configuration question

Hi,

I’m trying to configure nginx to serve multiple rails applications, each
from
its own path. app1 is accessible from ‘/’ and app2 is accessible from
‘/app2’.

In my configuration I’ve defined two location’s as follows:

– begin snip! –

app1

location / {

root /u/apps/app1/current/public;

proxy_set_header X-Real-IP $remote_addr;

needed for HTTPS

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;

if (-f $request_filename) {
break;
}

  if (-f $request_filename/index.html) {
    rewrite (.*) $1/index.html break;
  }

  if (-f $request_filename.html) {
    rewrite (.*) $1.html break;
  }

  if (!-f $request_filename) {
    proxy_pass http://mongrel_app1;
    break;
  }

}

#app2
location /app2 {

root /u/apps/app2/current/public;
proxy_set_header X-Real-IP $remote_addr;

# needed for HTTPS
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;

if (-f $request_filename) {
break;
}

if (-f $request_filename/index.html) {
    rewrite (.*) $1/index.html break;
}

if (-f $request_filename.html) {
    rewrite (.*) $1.html break;
}

if (!-f $request_filename) {
      proxy_pass http://mongrel_app2;
    break;
}

}

– end snip! –

The problem is that nginx is trying to resolve static files for /app2
along the
/app2 path inside my rails application’s public directory, which doesn’t
exist.

The only way I’ve been able to make the above configuration work is to
create a
symbolic from ‘app2’ to ‘public’. Is there some way to tell nginx to
ignore the
location part it has already matched when dealing with a request?

regards,
C.

Hi Cathal, …

You need two mongrel cluster instances, one per each rails app ok!

eg:

upstream mongrel_app_1 {
server 127.0.0.1:8000;
server 127.0.0.1:8001;
server 127.0.0.1:8002;
}

upstream mongrel_app2_2 {
server 127.0.0.1:9000;
server 127.0.0.1:9001;
server 127.0.0.1:9002;
}

Currently I’m hosting two rails app in my OpenBSD server.

Regards.

Hi Francisco,

Thanks for replying.
I’ve defined the cluster instances elsewhere in my conf file.
I just didn’t include them in the sample I posted.
The issue is that $request_filename includes the matched location
‘/app2’
in its path.

So the following directive:

if (-f $request_filename)
{
break;
}

looks for ‘/app2/styesheets/style.css’ in the root directory.
This doesn’t exist.

Is there someway to take into account that ‘/app2’ is a virtual path
when
attempting a match?

regards,
C.

Can you post the complete nginx.conf file ?

Regards.

Francisco Valladolid <ficovh@…> writes:

Can you post the complete nginx.conf file ?Regards.
On Thu, Apr 3, 2008 at 4:08 AM, Cathal
[email protected] wrote:
break;
}
looks for ‘/app2/styesheets/style.css’ in the root directory.
This doesn’t exist.
Is there someway to take into account that ‘/app2’ is a virtual path when
attempting a match?
regards,C.

– Francisco Valladolid H. – http://bsdguy.net - Jesus Christ follower.

Hi Francisco,

Here is the nginx.conf file I’m using.

regards,
C.

— begin nginx.conf —

user and group to run as

user user users;

number of nginx workers

worker_processes 6;

pid of nginx master process

pid /var/run/nginx.pid;

Number of worker connections. 1024 is a good default

events {
worker_connections 1024;
}

start the http module where we config http access.

http {

ignore_invalid_headers off;

pull in mime-types. You can break out your config

into as many include’s as you want to make it cleaner

include /usr/local/nginx/conf/mime.types;

set a default type for the rare situation that

nothing matches from the mimie-type include

default_type application/octet-stream;

configure log format

log_format main '$remote_addr - $remote_user [$time_local] ’
'“$request” $status $body_bytes_sent “$http_referer” ’
‘“$http_user_agent” “$http_x_forwarded_for”’;

main access log

access_log /var/log/nginx_access.log main;

main error log

error_log /var/log/nginx_error.log debug;

no sendfile on OSX

sendfile on;

These are good default values.

tcp_nopush on;
tcp_nodelay off;

output compression saves bandwidth

gzip on;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_proxied any;
gzip_types text/plain text/html text/css application/x-javascript
text/xml application/xml
application/xml+rss text/javascript;

this is where you define your mongrel clusters.

you need one of these blocks for each cluster

and each one needs its own name to refer to it later.

upstream mongrel_app1 {
server localhost:7000;
server localhost:7001;
server localhost:7002;
server localhost:7003;
}

upstream mongrel_app2 {
server localhost:10000;
server localhost:10001;
server localhost:10002;
server localhost:10003;
}

the server directive is nginx’s virtual host directive.

server {
# port to listen on. Can also be set to an IP:PORT
listen 80;

# Set the max size for file uploads to 50Mb
client_max_body_size 50M;

# sets the domain[s] that this vhost server requests for
# server_name www.[engineyard].com [engineyard].com;

# doc root
root /u/apps/app1/current/public;

# vhost specific access log
access_log  /var/log/nginx.vhost.access.log  main;

# this rewrites all the requests to the maintenance.html
# page if it exists in the doc root. This is for capistrano's
# disable web task
if (-f $document_root/system/maintenance.html) {
  rewrite  ^(.*)$  /system/maintenance.html last;
  break;
}

# SNMP MRTG location
location /admin/mrtg/  {

  satisfy_any  on;
  deny   all;
  auth_basic            "closed site";
  auth_basic_user_file  /var/passwords;

  alias /var/www/mrtg/;
  index index.html index.htm;
}

app1

location / {
  # needed to forward user's IP address to rails
  proxy_set_header  X-Real-IP  $remote_addr;

  # needed for HTTPS
  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;

  # If the file exists as a static file serve it directly without
  # running all the other rewite tests on it
  if (-f $request_filename) {
    break;
  }

  # check for index.html for directory index
  # if its there on the filesystem then rewite
  # the url to add /index.html to the end of it
  # and then break to send it to the next config rules.
  if (-f $request_filename/index.html) {
    rewrite (.*) $1/index.html break;
  }

  # this is the meat of the rails page caching config
  # it adds .html to the end of the url and then checks
  # the filesystem for that file. If it exists, then we
  # rewite the url to have explicit .html on the end
  # and then send it on its way to the next config rule.
  # if there is no file on the fs then it sets all the
  # necessary headers and proxies to our upstream mongrels
  if (-f $request_filename.html) {
    rewrite (.*) $1.html break;
  }

  if (!-f $request_filename) {
    proxy_pass http://mongrel_app1;
    break;
  }
}

app2

location /app2 {

root /u/apps/app2/current/public;

  # needed to forward user's IP address to rails
  proxy_set_header  X-Real-IP  $remote_addr;

  # needed for HTTPS
  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;

  # If the file exists as a static file serve it directly without
  # running all the other rewite tests on it
  if (-f $request_filename) {
    break;
  }

  # check for index.html for directory index
  # if its there on the filesystem then rewite
  # the url to add /index.html to the end of it
  # and then break to send it to the next config rules.
  if (-f $request_filename/index.html) {
    rewrite (.*) $1/index.html break;
  }

  # this is the meat of the rails page caching config
  # it adds .html to the end of the url and then checks
  # the filesystem for that file. If it exists, then we
  # rewite the url to have explicit .html on the end
  # and then send it on its way to the next config rule.
  # if there is no file on the fs then it sets all the
  # necessary headers and proxies to our upstream mongrels
  if (-f $request_filename.html) {
    rewrite (.*) $1.html break;
  }

  if (!-f $request_filename) {
proxy_pass http://mongrel_app2;
    break;
  }
}

error_page   500 502 503 504  /500.html;
location = /500.html {
  root   /u/apps/app1/current/public;
}

}
}

— end nginx.conf —

I found the following post:
http://article.gmane.org/gmane.comp.web.nginx.english/2283 which is very
similar
to what I am attempting. My problem is that my nginx can’t resolve
static files
prefixed with the path matched in the location directive. All static
file
requests are then proxied to the rails app. which cannot resolve them
either.
Can anybody provide some guidance?

regards,
C.

On Apr 7, 2008, at 9:34 AM, Cathal wrote:

regards,

you just want to remove the /app2 /app1 etc from static file checks?

am i reading all that correctly?

if yes, this was our ugly solution to the fact that we write tracking
info into the url
( not rails but same scenario )
so that

/dir/file.html would appear as url as /s-SOMETHINGHERE/dir/file.html

set $dynamic 0;
set $real_file $request_filename;

if ( $uri ~* ^(/s-[^/]/)(.)$ )
{
set $real_file $document_root/$2;
set $has_lid 1;
}

IS IT DYNAMIC?

if ( !-e $real_file )
{
set $dynamic 1;
}

FILE DOESNT EXIST SO WE HAND OFF

if ( $dynamic )
{
# DO YOU DYNAMIC HANDLING HERE
}

THIS REWRITES OUT THE EXTRA STUFF FOR STATIC HANDLING

if ( $has_lid )
{
rewrite ^(/s-[^/]/)(.)$ /$2;
}

This may not be the best way to do it. But it works.

~