How to configure nginx as a reverse proxy to a gunicorn socket
by Thomas Tran
In the previous tutorial, we learned how to configure gunicorn
to run our WSGI
(Django
) app to a socket. In this tutorial, we'll use nginx
as a reverse-proxy to relay external web requests to that socket. We'll also configure nginx to serve static files.
Why nginx? A reverse proxy server sits behind a firewall in a private machine a directs client requests to the appropriate backend server. In our case, nginx
will forward external requests to the gunicorn
socket. There are many reasons why nginx
is a good choice. Firstly, by intercepting requests toward the backend, it protects the identities of the backend. For instance, nginx
buffers slow clients which, among other things, prevents denial-of-service attacks from malicious parties. Secondly, nginx
can compress inbound and outbound data, so it speeds up the flow of traffic between clients and servers. Thirdly, it helps with load balancing, distributing client requests across a group of servers to maximizee speed and capacity utilization. This will be helpful with high traffic sites and multiple machines will be necessary to handle that many requests.
Install nginx
Firstly, we need to install nginx
. Run the following command to install it:
sudo apt-get update
sudo apt-get install nginx
nginx
will by default have its config files in the directory /etc/nginx/
. The file /etc/nginx/nginx.conf
contains default global nginx
configs.
Configuring nginx
We'll create a additional server
block which will tell nginx how to direct external requests to our gunicorn
socket.
The directory /etc/nginx/sites-available/
contains additional configs servers on the machine. We'll create a file, which will contain our server
block:
sudo vim /etc/nginx/sites-available/djangoapp
Now paste the following into that file and then save:
server {
listen 80;
server_name [your domain name or public ip];
location /static/ {
root /var/www/djangoapp/static/;
}
location / {
include proxy_params;
proxy_pass http://unix:/var/www/djangoapp/djangoapp.sock;
}
}
In the file above, the directive listen 80
sets the port on which the server will accept requests. It will list to to port 80
by default for external requests.
The server_name
directive specifies which server block is used for a given request. For instance, if you are serving your app to an IP, input your machine's public IP. If you are serving your app to a domain name, such as www.example.com
, input that instead.
The directive location /static/
specifies where our static files are located. If you are serving to a domain name, static files will be served as www.example.com/static/example.css
, for instance.
Finally, the location /
directive tells nginx to relay any other requests in this server
block to our socket, meaning that all other requests besides static files will be directed toward the socket, which will then be picked up by gunicorn and then processed. proxy_params
contains somes useful header parameters which we definitely want to use.
Enabling and starting nginx
To enable these new configs, we'll connect this file to the sites-enabled
directory. To do so, input the following commands:
sudo ln -s /etc/nginx/sites-available/djangoapp /etc/nginx/sites-enabled
Then, restart nginx
with the command:
service nginx restart
Useful commands and troubleshooting
When working with systemctl
, some systems allow you to use the service
command to control services. In our case, the following comands are available to us:
service nginx start
service nginx stop
service nginx restart
If you run into permission errors, you probably have insufficient rights to run nginx
with the djangoappuser
. ngix
also uses the security group www-data
, so make sure to add djangoappuser
to www-data
. To do so, you can do the following:
sudo useradd -g www-data djangoappuser