Prologue

“nginx [engine x] is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server, originally written by Igor Sysoev.”

- Nginx

So in this article, I’m going to talk about the basic use of Nginx proxying, including:

All these are done on a Ubuntu server. 😉


Setup Nginx

Before we actually use it, let’s have a brief look of Nginx.

First, we can get Nginx by a simple apt command.

1
sudo apt install nginx

Then, we’ll write some basic configurations in /etc/nginx/conf.d/default.conf. It tells Nginx to listen to requests on port 80, and the server name it works on.

1
2
3
4
server {
listen 80;
server_name xx.xx.xx.xx;
}

If you have multiple profiles, you can then write different .conf under /etc/nginx/conf.d/, and Nginx will load them all.

To launch Nginx, you simply need these two commands, once and for all, unless you stop it permenantly.

1
2
sudo nginx
systemctl start nginx.service

Every time you make any change to .conf files, you may want to reload Nginx, here is how to to it.

1
sudo nginx -s reload

And at last, if you want to stop Nginx, you can force terminate it immediately, or let it stop itself after all current works finished.

1
2
sudo nginx -s quit # stop after current process finishes its work
sudo nginx -s stop # stop immediately

Serving Static Files

Now, let’s begin with the easiest part - serving static files.

In our Web service, we may want our resources accessible via URL. For example, in Django project, the static/ and media/ folder will be exposed directly to URL when DEBUG set to True. However, Django won’t serve static files in production, when Nginx is needed.

In order to map URL to server directory, we can add location sections in server. For example, if we want to map /media route, we can add a location section called /media/. This tells Nginx to handle all URL routes begin with /media/ using schema defined in this section.

And in location section, we need to assign a root directory to tell Nginx to look for /media/ folder under this root. This way, Nginx will look for local file home/wwwroot/media/avatar/1.png when receives URL /media/avatar/1.png.

1
2
3
4
5
6
7
8
server {
listen 80;
server_name xx.xx.xx.xx;

location /media/ {
root /home/wwwroot/;
}
}

If we have several static file routes, we can write root outside location to make it visible for all location sections, if it is not explicitly declared within.

1
2
3
4
5
6
7
8
9
10
11
12
server {
listen 80;
server_name xx.xx.xx.xx;

root /home/wwwroot/;

location /media/ {
}

location /static/ {
}
}

If you want to serve static html files, but don’t want to add index.html at the end of the route, you can use autoindex to have Nginx handle this for you.

1
2
3
4
5
6
7
8
9
10
server {
listen 80;
server_name: xx.xx.xx.xx;

root /home/wwwroot/;

location /pages/ {
autoindex on;
}
}

Now, you will get /pages/tags/index.html with URL /pages/tags/.

Be warned, autoindex only works for URLs that ends with /.


Basic Proxying

It is really convenient to use Nginx for backend API proxying, as it could hide annoying port suffix.

Proxying HTTP Requests

Basically, if we want to proxy our API for port 5000, we can simply write this. The only thing to notice is that, in order not to confuse API routes with others, such as static files, we can add a simple /api/ prefix to all our APIs.

1
2
3
4
5
6
7
8
9
server {
listen 80;
server_name xx.xx.xx.xx;

location /api/ {
proxy_pass http://localhost:5000/api/;
}
}

In this way, we can use xx.xx.xx.xx/api/your_api_route instead of xx.xx.xx.xx:5000/api/your_api_route.

Proxying WebSocket Requests

Reference: WebSocket Proxying

WebSocket is a way you can use to exchange data between client side and server side, regardless of whether there is a new request or not. In fact, it is a GET request, but then get a protocol upgrade when connection established. Then how to proxy for it?

Almost the same as HTTP requests, but with some more information. Also, you may add a /ws/ prefix, or whatever you like to avoid confusion.

1
2
3
4
5
6
7
8
9
10
11
12
server {
listen 80;
server_name xx.xx.xx.xx;

location /ws/ {
proxy_pass http://localhost:5000/ws/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 360s;
}
}

Here, we set http version and headers to upgrade GET requests to WebSocket connection. According to Nginx official site, the default timeout for WebSocket connection is 60 seconds, which might be a little too short for your project. You can manually set it to any value you like. 😋


Epilogue

Well, this is merely the basic use of Nginx proxying. Explore more on your own. 🙂