How to Deploy Django Application to an AWS or Compatible VPS

How to Deploy Django Application to an AWS or Compatible VPS
Photo by Faisal / Unsplash

This document provides an optimised, step-by-step process for deploying a Django project named <<project>> to a Virtual Private Server (VPS) such as Amazon AWS, using Gunicorn, systemd, NGINX, and Let's Encrypt SSL.


Prerequisites

  • A VPS running Ubuntu (e.g., 20.04 or later)
  • A Django project named <<project>>
  • Root or sudo access to the VPS
  • Domain name pointing to the VPS IP (e.g., cms.periwin.com)

Step 1: Connect to VPS and Prepare the Environment

ssh ubuntu@<your-server-ip>
cd /app/<<project>>

Ensure the folder /app/<<project>> contains your Django project.

Activate the virtual environment:

source <venv>/bin/activate

Install required packages:

pip install -r requirements.txt

Test the server runs without errors:

python manage.py runserver

Step 2: Install and Configure Gunicorn

Install Gunicorn:

pip install gunicorn

Test Gunicorn locally:

gunicorn --bind 0.0.0.0:8000 root.wsgi:application

Replace root with the appropriate name if your project is different.


Step 3: Create systemd Service and Socket Files

For example, if the domain is cms.periwin.com, use this name in the service and socket files:

Create the socket file:

sudo vim /etc/systemd/system/cms.periwin.com.socket

Paste the following content:

[Unit]
Description=cms.periwin.com socket

[Socket]
ListenStream=/run/cms.periwin.com.sock

[Install]
WantedBy=sockets.target

To save and exit in vim, press Esc, then type :wq and press Enter.

Create the service file:

sudo vim /etc/systemd/system/cms.periwin.com.service

Paste:

[Unit]
Description=cms.periwin.com service
Requires=cms.periwin.com.socket
After=network.target

[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/app/<<project>>
ExecStart=/app/<<project>>/venv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/cms.periwin.com.sock root.wsgi:application

[Install]
WantedBy=multi-user.target

Save and exit with Esc, then :wq.

Enable and start services:

sudo systemctl daemon-reload
sudo systemctl enable --now cms.periwin.com.socket
sudo systemctl start cms.periwin.com.service
sudo systemctl status cms.periwin.com.service

Step 4: Configure NGINX

Create NGINX config:

sudo vim /etc/nginx/sites-available/cms.periwin.com.conf

Paste:

server {
    listen 80;
    server_name cms.periwin.com;

    location = /favicon.ico { access_log off; log_not_found off; }

    location /static/ {
        root /app/<<project>>;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/cms.periwin.com.sock;
    }
}

Save and exit with Esc, then :wq.

Enable configuration:

sudo ln -s /etc/nginx/sites-available/cms.periwin.com.conf /etc/nginx/sites-enabled

Test and restart NGINX:

sudo nginx -t
sudo systemctl restart nginx

Step 5: Configure Domain and SSL

Update DNS A record for your domain (e.g., cms.periwin.com) to point to the server IP.

Install Certbot:

sudo apt update
sudo apt install certbot python3-certbot-nginx

Obtain and install SSL certificate:

sudo certbot --nginx

Follow prompts to enable HTTPS and redirect traffic.


Conclusion

Your Django project <<project>> is now deployed on an AWS VPS with production-grade configuration using Gunicorn, systemd, NGINX, and secured via HTTPS with Let's Encrypt, under the domain cms.periwin.com.