Deploy Django with Nginx and Gunicorn on Ubuntu

Installing Packages

$ sudo apt update

$ sudo apt install nginx curl
$ conda install gunicorn

Testing Gunicorn’s Ability to Serve the Project

$ cd /opt/var/labs/supernotes/
$ gunicorn --bind 0.0.0.0:8000 supernotes.wsgi

Creating systemd Socket and Service Files for Gunicorn

$ cat <<EOF | sudo tee /etc/systemd/system/gunicorn.socket > /dev/null
[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target
EOF

$ cat <<EOF | sudo tee /etc/systemd/system/gunicorn.service > /dev/null
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
User=james
Group=www-data
WorkingDirectory=/opt/var/labs/supernotes
ExecStart=/opt/local/conda/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn.sock \
          supernotes.wsgi:application

[Install]
WantedBy=multi-user.target
EOF

$ sudo systemctl start gunicorn.socket
$ sudo systemctl enable gunicorn.socket

# Checking for the Gunicorn Socket File
$ sudo systemctl status gunicorn.socket
$ file /run/gunicorn.sock
$ sudo journalctl -u gunicorn.socket

# Testing Socket Activation
$ sudo systemctl status gunicorn
○ gunicorn.service - gunicorn daemon
     Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled)
     Active: inactive (dead)
TriggeredBy:  gunicorn.socket
$ curl --unix-socket /run/gunicorn.sock localhost
$ sudo systemctl status gunicorn
● gunicorn.service - gunicorn daemon
     Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled)
     Active: active (running) since Sat 2023-03-18 02:01:29 CST; 34s ago
TriggeredBy:  gunicorn.socket
   Main PID: 11243 (gunicorn)
      Tasks: 4 (limit: 76309)
     Memory: 132.7M
        CPU: 598ms
     CGroup: /system.slice/gunicorn.service
             ├─11243 /opt/local/conda/bin/python /opt/local/conda/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock supernotes.wsgi:appli>
             ├─11244 /opt/local/conda/bin/python /opt/local/conda/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock supernotes.wsgi:appli>
             ├─11245 /opt/local/conda/bin/python /opt/local/conda/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock supernotes.wsgi:appli>
             └─11246 /opt/local/conda/bin/python /opt/local/conda/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock supernotes.wsgi:appli>

$ sudo journalctl -u gunicorn
$ sudo systemctl daemon-reload
$ sudo systemctl restart gunicorn

Configure Nginx to Proxy Pass to Gunicorn

$ cat <<EOF | sudo tee /etc/nginx/sites-available/supernotes > /dev/null
server {
    listen 80;
    server_name supernotes.local;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /opt/var/labs/supernotes;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}
EOF

$ sudo ln -s /etc/nginx/sites-available/supernotes /etc/nginx/sites-enabled
$ sudo nginx -t
$ sudo systemctl restart nginx
$ sudo ufw allow 'Nginx Full'

Testing Nginx Activation

$ curl -v http://supernotes.local/