Efficient Production Deployment of Django with Nginx and Gunicorn
Published: 2023-02-18 17:11:22

_This post intends to help you in quick setup along with configuration files and their contents. In subsequent post I shall include ssl setup as well._ 

We shall follow step-by-step approach to to deploy a Django application over AWS using nginx and gunicorn.

Software version details in this blog:
Django : 3.2
Python: 3.10

--------------------------------------------------------------
**STEP 1 : Create a Django project**

For now we shall assume that you have a basic Django project setup that you run locally using the command below.

```
python manage.py runserver
```
--------------------------------------------------------------
**STEP 2 : Connecting gunicorn to Django app**

Install gunicorn in your virtual environment.

```
pip install django gunicorn
```

Configuring gunicorn. The below command should give you an indication whether the gunicorn is running correctly.

```
gunicorn --bind 0.0.0.0:8000 <your_project_name>.wsgi
```

Now deactivate your virtual env.

Daemonizing gunicorn using systemd (highly recommended).

a) Create gunicorn socket file.

```
sudo vi /etc/systemd/system/gunicorn.socket
```
```
# file content of gunicorn.socket
[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.target
```
b) Create gunicorn service file

```
sudo vim /etc/systemd/system/gunicorn.service
```

```
# file content of gunicorn.service
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
# here you should put the user who has access to the django project path (In my case it was ubuntu)
User=ubuntu
Group=www-data
WorkingDirectory=<path to your django project root>
ExecStart=<path to your django virtual env>/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn.sock \
          core.wsgi:application
[Install]
WantedBy=multi-user.target
```
c) Start and enable socket

```
sudo systemctl start gunicorn.socket
```
```
sudo systemctl enable gunicorn.socket
```
d) [optional] In case you update the gunicorn service file later, run the below commands

```
sudo systemctl daemon-reload
```
```
sudo systemctl restart gunicorn.service
```

--------------------------------------------------------------
**STEP 3: Configuring Nginx as a reverse proxy**

Create a configuration file for Nginx using the following command

```
sudo vim /etc/nginx/sites-available/<your_project_name>.conf
```

```
server {
    listen 80;
    server_name xyz.domain.in;
    charset utf-8;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    location /static/ {
        alias <your_project_path>/staticfiles/;
    }
    location /media/ {
        alias <your_project_path>/media/;
    }
    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
    location /favicon.ico {
        access_log off;
        log_not_found off;
    }
    location /robots.txt {
        access_log off;
        log_not_found off;
    }
}
```
What we shall do below is create a symlink of the conf file in directory sites-enabled and start ngnix.

```
cd /etc/nginx/sites-enabled
```
```
sudo ln -s /etc/nginx/sites-available/<your_project_name>.conf
```
```
sudo systemctl restart nginx
```