Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Warning: so far I have only learnt how to use nginx to serve apps with their own domain and server block. But I think its time to dive a little deeper.

To mitigate the need for multiple SSL certificates or expensive wildcard certificates I would like to serve multiple apps (e.g. rails apps, php apps, node.js apps) from one nginx server_name. e.g. rooturl/railsapp rooturl/nodejsapp rooturl/phpshop rooturl/phpblog

I am unsure on ideal strategy. Some examples I have seen and or thought about:

  1. Multiple location rules, this seems to cause conflicts between the individual app config requirements, e.g. differing rewrite and access requirements

  2. Isolated apps by backend internal port, is this possible? Each port routing to its own config? So config is isolated and can be bespoke to app requirements.

  3. Reverse proxy, I am little ignorant of how this works, is this what I need to research? is this actually 2 above? Help online seems to always proxy to another server e.g apache

What is an effective way to isolate config requirements for apps served from a single domain via sub uris?

share|improve this question

1 Answer 1

up vote 2 down vote accepted

Nginx can do quite a bit, including reverse proxying, caching and serving content, but in large environments, individual functions are split to make them more maintainable or specialized with better-suited alternatives (like stud for high-volume https://).

A reverse proxy just means something that sits between the client and the actual app; it's actually a misnomer, and should be called a "server proxy."

To serve everything from one cert on one domain, start with something like this:

(Tested on Ubuntu LTS 12.04)

/etc/nginx/proxy_params

#proxy_set_header Host            $proxy_host; # instead of standard $host
proxy_set_header  X-Real-IP       $remote_addr;
proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;

/etc/nginx/sites-enabled/global_redirects

# note: must disable the built-in 
#       /etc/nginx/sites-enabled/default by removing it (it's a symlink) 
server {

    # redirects all http:// requests to https://
    # critically, passes the original host the client was trying to connect to.
    rewrite ^ https://$host$request_uri? permanent;

    # combined redirect access and error logs for easier correlation
    error_log  '/var/log/nginx/global_redirects';
    access_log '/var/log/nginx/global_redirects';

}

/etc/nginx/sites-enabled/global_ssl

# This serves all enabled-locations over ssl only.
# If there's no match, it shows the default site.

include /etc/nginx/upstreams-enabled/*; # include enabled upstream proxies

server {

    listen 443 ssl;

    ssl_certificate      /etc/nginx/server.crt;
    ssl_certificate_key  /etc/nginx/server.key;

    keepalive_timeout    70;

    root /usr/share/nginx/www;
    index index.html index.htm;

    access_log '/var/log/nginx/global_ssl';
    error_log  '/var/log/nginx/global_ssl';

    include /etc/nginx/locations-enabled/*;

}

/etc/nginx/locations-enabled/bar

# points to hackernews but
# it could be http://10.2.4.5:401/app495 instead
location ~ ^/bar(/.*)?$ {

    include proxy_params;
    include apps/node;

    proxy_pass       http://news.ycombinator.com/$1;

    access_log '/var/log/nginx/bar';
    error_log  '/var/log/nginx/bar';

}

/etc/nginx/locations-enabled/foo

location ~ ^/foo(/.*)?$ {

    include proxy_params;
    include apps/ruby;

    proxy_pass       http://www.linode.com/$1;

    access_log '/var/log/nginx/foo';
    error_log  '/var/log/nginx/foo';

}

/etc/nginx/upstreams-enabled/news.ycombinator.com

upstream news.ycombinator.com {
  server news.ycombinator.com;
}

/etc/nginx/upstreams-enabled/www.linode.com

upstream www.linode.com {
  server www.linode.com;
}

/etc/nginx/apps/ruby

# Place ruby specific directives here

/etc/nginx/apps/node

# Place node specific directives here

Remember that this does not rewrite urls in pages, because those are generated by each app. Instead, each app should know it's external scheme, host, port and url base and produce links appropriately (most real apps support this).

References:

  1. http://wiki.nginx.org/HttpProxyModule
  2. http://wiki.nginx.org/HttpSslModule
share|improve this answer
    
Thank you for such a full answer. It looks very modular which I am sure will be easy to work with and extend. I will stage these and see If I can decipher what it all means! Appreciated. –  icpu Oct 7 '12 at 10:08
    
This is working great, needed to tweak the https rewrite to handle request uris, edit is above pending review. Thanks a squillion. –  icpu Oct 7 '12 at 13:28
    
That was a copy & paste error on my part, my bad. The prod system actually had the same as the edit. Thanks community. :) –  Barry Oct 7 '12 at 17:00
    
For some mgmt scripts for this style of setup: gist.github.com/3848972 –  Barry Oct 7 '12 at 17:19

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.