Maxence Henneron
Maxence Henneron

Reputation: 495

Using nginx to map rails applications

I'd like to use nginx in order to map all my rails apps on port 80.

Currently, I have 3 rails apps running on port 3000 3001 and 3002 and I'd like to use nginx on port 80 to map them so :

http://127.0.0.1/app1 => 127.0.0.1:3000
http://127.0.0.1/app2 => 127.0.0.1:3001
http://127.0.0.1/app3 => 127.0.0.1:3002

Here's what I did :

server {
    listen 80;
    location /app1/ {
        proxy_pass http://127.0.0.1:3000/;
    }

    location /app2/ {
        proxy_pass http://127.0.0.1:3001/;
    }

    location /app3/ {
        proxy_pass http://127.0.0.1:3002/;
    }
}

However, when I try to access http://127.0.0.1/app1, I only get the HTML content, no assets/js/css as the browser tries to get them from http://127.0.0.1/assets instead of http://127.0.0.1/app1/assets.

Is there a way to fix this?

Upvotes: 4

Views: 250

Answers (2)

EugZol
EugZol

Reputation: 6545

Add ActionController::Base.relative_url_root = "/app1" to the end of your config/environment.rb of app1 (similarly for other two apps). This will make Rails add proper prefix to URLs.

If you don't want to mess with Rails config, you probably could force Nginx to go through all of your assets folder until it finds the one it needs, if I'm not mistaken it could be archived like this:

location /assets/ {
  try_files /app1/$uri /app2/$uri /app3/$uri;
}

Please note that you must have different filenames for assets of different apps. That is already so if you are using asset pipeline everywhere, as it hashes file names.

UPD.

You can also try 'Referer'-based routing:

location /assets/ {
   if ($http_referer ~* /app1) {
     rewrite ^(.*)$ app1/$1 break;
   }
   if ($http_referer ~* /app2) {
     rewrite ^(.*)$ app2/$1 break;
   }
   if ($http_referer ~* /app3) {
     rewrite ^(.*)$ app3/$1 break;
   }    
}

Upvotes: 1

tompave
tompave

Reputation: 12412

This is a good default configuration for what you want to achieve:

server {
    listen 80;
    location /app1/ {
        root /srv/rails/app1/public;
        try_files $uri $uri/index.html $uri.html @app1_forward;
    }

    location @app1_forward {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header Host $http_host;
      proxy_redirect off;
      proxy_pass http://app1_backend;
    }

    location /app2/ {
        root /srv/rails/app2/public;
        try_files $uri $uri/index.html $uri.html @app2_forward;
    }

    location @app2_forward {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header Host $http_host;
      proxy_redirect off;
      proxy_pass http://app2_backend;
    }

    location /app3/ {
        root /srv/rails/app3/public;
        try_files $uri $uri/index.html $uri.html @app3_forward;
    }

    location @app3_forward {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header Host $http_host;
      proxy_redirect off;
      proxy_pass http://app3_backend;
    }
}

upstream app1_backend {
    server 127.0.0.1:3000    fail_timeout=0;
}

upstream app2_backend {
    server 127.0.0.1:3001    fail_timeout=0;
}

upstream app3_backend {
    server 127.0.0.1:3002    fail_timeout=0;
}

Also check this article, where I link to this example nginx config, for Rails.

Upvotes: 1

Related Questions