How to setup Gunicorn and Nginx for Django on Debian

If you develop your project on Django, then you probably know that you need a web server like nginx to serve your static files: images, stylesheets and so on. While Django has its own ability to serve static files, you should use it only during development. In this guide you will learn how to install and configure all software required to serve your Python Django/Flask application.

Why should you use Nginx and Gunicorn

You need a web server. Django’s builtin “staticfiles” app is not suitable for production use. As mentioned in the official documentation regarding staticfiles view:

[…] this view is grossly inefficient and probably insecure. This is only intended for local development, and should never be used in production.

Source: docs.djangoproject.com

You might wonder, why to choose Nginx over Apache. The answer is simple — security and speed.

The next thing you need is a WSGI server. It’s a program, which turns your project into a real website. This is achieved by multithreading your application so it is able to process several requests at the same time. Also, it serves the app on the local port or Unix domain socket. We will use the latter case.

I tried a lot of WSGI servers and figured out that Gunicorn is the best choice. So, when you know what tech stack you will use, you can proceed to installation.

Setting up Nginx

First, update your package lists. Then install Nginx.

sudo apt update
sudo apt install nginx

Next, configure your website. Write this to /etc/nginx/sites-available/website (where “website” is the name of your website). I assume you have directory website which contains your website in the home directory of the user named bob. /run/gunicorn.sock is a path to the Gunicorn socket you will create later on.

server {
    server_name example.com;

    location = /favicon.ico {
        access_log off;
        alias /home/bob/website/static/icons/favicon.ico;
    }

    location /icons/ {
        alias /home/bob/website/static/icons/;
    }
    location /static/ {
        root /home/bob/website/;
    }

    location / {
        rewrite ^([^.]*[^/])$ $1/ permanent;
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }

    listen 80;
}

Enable your website by creating symbolic link from sites-available/website to sites-enabled/website:

sudo ln -sf /etc/nginx/sites-{available,enabled}/website

We used bash expansion here. You could write the command above as follows: sudo ln -sf /etc/nginx/sites-available/website /etc/nginx/sites-enabled/website

Optionally, you can also remove the default “It works” page from enabled websites. It is recommended to do this in production environment: sudo rm /etc/nginx/sites-enabled/default.

Installing and configuring Gunicorn

Go to the directory of your website and activate the virtual environment:

cd /home/bob/website/
. venv/bin/activate

You could use source command instead of dot. Next, install the Gunicorn WSGI HTTP server:

pip install gunicorn

Next, write the following to /etc/systemd/system/gunicorn.socket to create a Systemd unit for the Gunicorn socket:

[Unit]
Description=Gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

Save the file. Next, write the follwing to /etc/systemd/system/gunicorn.service to create a service. Replace “bob” with your username. Also, replace “website” with your project name and paths with your apps paths.

[Unit]
Description=Gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
User=bob
Group=www-data
WorkingDirectory=/home/bob/website/
ExecStart=/home/bob/website/venv/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn.sock \
          website.wsgi:application

[Install]
WantedBy=multi-user.target

Enabling and starting the services

The configuration process is almost completed. Now you need to add Nginx and Gunicorn to system autostart. Use --now option to start them now.

sudo systemctl enable --now gunicorn
sudo systemctl enable --now nginx

Check if it works by visiting you website. You should see your app. If not, run these commands:

sudo systemctl daemon-reload
sudo systemctl restart gunicorn.socket gunicorn.service
sudo systemctl restart nginx

To see status of the website, run systemctl status gunicorn

Summary

Now you know how to setup your Python web application for production use. I did not include the Django settings.py configuration, you should do it by referring to official documentation on this topic. To setup Nginx and Gunicorn for Python Django web project, you need to do this:

  • Install and configure Nginx to serve static files.
  • Install Gunicorn, configure systemd unit and socket to multithread your app to improve performance.
  • Enable and start Gunicorn and Nginx.

Leave a Comment