How to proxy web apps using nginx?
When hosting our web applications, we often have one public IP
address (i.e., an IP address visible to the outside world)
using which we want to host multiple web apps. For example, one
may wants to host three different web apps respectively for
example1.com
, example2.com
, and example1.com/images
on
the same machine using a single IP address.
How can we do that? Well, the good news is Internet browsers send the domain name inside HTTP requests and all we need to do is to parse the requested domain name and URL and then route the HTTP request to the actual web server.
Oh, do I really need to parse HTTP requests? You can if you really want to, but there are lots of tools and technologies that readily do this for you. In this tutorial, we walk you through how you can use nginx to proxy multiple web applications.
We have prepared pre-copmiled binaries for your. You need to download nginx.tar.gz and uncompress it:
$ wget http://www.cs.toronto.edu/~soheil/csc309/nginx.tar.gz && tar -xvzf nginx.tar.gz
nginx/conf/nginx.conf
.nginx
in the directory.
To run nginx
, go to the nginx
directory (cd nginx
) and
run ./nginx ...
.Install nginx
using apt-get
:
$ sudo apt-get install nginx
Notes:
nginx
's config file we need resides in /etc/nginx/sites-enabled/default
.nginx
, you need to use sudo
.Install homebrew
, and then install nginx
using brew
:
$ brew install nginx
Notes:
nginx
's config file is in /usr/local/etc/nginx/nginx.conf
.nginx
, you need to use sudo
:
sudo nano /usr/local/etc/nginx/nginx.conf
and
sudo nginx ...
Write three different node applications running on different ports (say 8080, 8181, 8282) on your machine.
To do so, you need to edit your nginx
config file.
In the config file, find the server
section:
server {
listen 80;
...
location / {
...
}
...
}
If you're using CDF, make sure you change 80
to a vacant port number
(ask for one from your instructor). If not, you can keep using 80
or
change the port if you will.
Test nginx
./nginx
on CDF, or run sudo nginx
on your local machine.localhost:$PORT
(replace $PORT
with
the port number you configured for nginx
).Let say we want to configure nginx
to route requests for
/
, /blog
, and /mail
, respectively onto
localhost:8080
, localhost:8181
, and localhost:8282
.
+--- host --------> node.js on localhost:8080
|
users --> nginx --|--- host/blog ---> node.js on localhost:8181
|
+--- host/mail ---> node.js on localhost:8282
To route /
, you need to edit your nginx
config file.
In the config file, find the server
section:
server {
listen 80;
...
location / {
...
}
...
}
This section is simply telling nginx
how it should serve HTTP requests.
Now, change the location section to this snippet:
server {
listen ...;
...
location / {
proxy_pass http://127.0.0.1:8080;
}
...
}
proxy_pass
simply tells nginx
to forward requests to /
to the
server listening on http://127.0.0.1:8080
.
To reload nginx
's configuration run:
nginx -s reload
on your machine.
Referesh your browser. Do you see the output from your node.js
application?
If yes, you are all set. If no, there is a problem with your config.
To redirect /mail
and /blog
, you simply need to add new entries
the location section in the config file:
server {
listen ...;
...
location / {
proxy_pass http://127.0.0.1:8080;
}
location /blog {
proxy_pass http://127.0.0.1:8181;
}
location /mail {
proxy_pass http://127.0.0.1:8282;
}
...
}
Run nginx -s reload
on your machine.
Log onto localhost:$PORT/blog
in your browser.
Do you see the output from your second node.js
application?
Then log onto localhost:$PORT/mail
.
Do you see the output from your third node.js
application?
If yes & yes, you are all set. If no, there is a problem with your config.
Now as you might have noticed in Step 6, nginx sends the same
HTTP request to your node.js
web apps which results into a 404 error.
Why? Because, your node.js
web application serves requests from /
not from /blog
and /mail
. But, nginx
is sending requests to /blog
and
/mail
.
To fix this issue, we need rewrite the URL so that it matches the URL
you can serve on your node.js
applications.
To correctly rewrite URLs change your config file to match the following snippet:
server {
listen ...;
...
location / {
proxy_pass http://127.0.0.1:8080;
}
location /blog {
rewrite ^/blog(.*) /$1 break;
proxy_pass http://127.0.0.1:8181;
}
location /mail {
rewrite ^/mail(.*) /$1 break;
proxy_pass http://127.0.0.1:8282;
}
...
}
This rewrite commands are simple regular expressions that transform
strings like /blogWHAT_EVER
and /mailWHAT_EVER
to /WHAT_EVER
in the HTTP requests.
All set?
Configure your nginx to redirect URLs from /google
to http://www.google.com
Let say you want to host example1.com
, example2.com
, and example3.com
on your machine, respectively to localhost:8080
, localhost:8181
, and
localhost:8282
.
Note: Since you don't have access to a DNS server, you should
add domain name entries to your /etc/hosts
(you can't do this on CDF machines):
...
127.0.0.1 example1.com example2.com example3.com
...
To proxy eaxmple1.com
we can't use the location part of the default server.
Instead we need to add another server section with a server_name
set
to our virtual host (e.g., example1.com
, ...), and then a simple location
section that tells nginx
how to proxy the requests:
server {
listen 80;
server_name example1.com;
location / {
proxy_pass http://127.0.0.1:8080;
}
}
server {
listen 80;
server_name example2.com;
location / {
proxy_pass http://127.0.0.1:8181;
}
}
server {
listen 80;
server_name example3.com;
location / {
proxy_pass http://127.0.0.1:8282;
}
}
Simple, ha?!