Deploying a Django WebSocket Application with Uvicorn, Nginx, and PostgreSQL

Dhairya PatelDhairya Patel
4 min read

In this comprehensive guide, we'll walk through the process of deploying a Django application that uses WebSockets. We'll set up a production-ready environment using Uvicorn as the ASGI server, Nginx as a reverse proxy, and PostgreSQL as the database.

Prerequisites

  • An Ubuntu 22.04 server (or similar Linux distribution)

  • A domain name pointing to your server

  • Basic knowledge of Django, ASGI, and WebSockets

  • Root or sudo access to your server

1. Initial Server Setup

First, let's update our system and install required packages:

sudo apt update && sudo apt upgrade -y
sudo apt install python3-pip python3-venv nginx postgresql postgresql-contrib -y

2. Setting Up PostgreSQL

Let's configure our database:

# Create a database user
sudo -u postgres createuser --interactive
# Enter username: djangouser
# Make as superuser? y

# Create a database
sudo -u postgres createdb djangodb

# Set password for the user
sudo -u postgres psql
postgres=# ALTER USER djangouser WITH PASSWORD 'your_secure_password';
postgres=# \q

3. Project Setup

Create a directory for your project and set up a virtual environment:

mkdir ~/django_websocket
cd ~/django_websocket
python3 -m venv venv
source venv/bin/activate

# Install required packages
pip install django channels uvicorn psycopg2-binary "uvicorn[standard]" websockets

Step 4 — Creating and Configuring a New Django Project

With the Python components installed, you can create the actual Django project files.

# Create a new Django project
django-admin startproject socket_demo

Now, let's configure the project:

# Navigate to the project directory
cd socket_demo

# Create a Django app
python manage.py startapp chat

Make changes in your chatbot project now. For demo purpose you can clone my project and start doing deployment.

Django-WebSocket

5. ASGI Configuration

Create or update your asgi.py:

# asgi.py

import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from socket_demo.routing import websocket_urlpatterns

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'socket_demo.settings')

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": AuthMiddlewareStack(
        URLRouter(
            websocket_urlpatterns
        )
    ),
})

6. Test the ASGI Configuration\

Run this command in socket_demo directory

uvicorn socket_demo.asgi:application --reload

Now, open your browser and navigate to http://localhost:8000

You will see chatbot page in your browser. You will see connnected in green box means you have connected to websocket server.

Open in different browser and navigate to http://localhost:8000 and test socket.

6. Setting Up Uvicorn Service

Create a systemd service file for Uvicorn:

sudo nano /etc/systemd/system/django-websocket.service

Add the following content:

[Unit]
Description=Django WebSocket Application
After=network.target

[Service]
User=ubuntu
WorkingDirectory=/home/ubuntu/socket_demo
Environment="PATH=/home/ubuntu/socket_demo/venv/bin"
ExecStart=/home/ubuntu/socket_demo/venv/bin/uvicorn socket_demo.asgi:application --host 0.0.0.0 --port 8000
Restart=always

[Install]
WantedBy=multi-user.target

Enable and start the service:

sudo systemctl enable django-websocket
sudo systemctl start django-websocket

7. Nginx Configuration

Create a new Nginx configuration file:

sudo nano /etc/nginx/sites-available/django-websocket

Add the following configuration:

server {
    listen 80;
    server_name your_domain.com;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/ubuntu/django_websocket;
    }

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Enable the site and restart Nginx:

sudo ln -s /etc/nginx/sites-available/django-websocket /etc/nginx/sites-enabled/
sudo systemctl restart nginx

8. Setting Up SSL with Let's Encrypt

Install Certbot and get an SSL certificate:

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d your_domain.com

10. Testing the WebSocket Connection

You can test your WebSocket connection using JavaScript:

const socket = new WebSocket('wss://your_domain.com/ws/chat/');

socket.onopen = function(e) {
    console.log('Connection established');
    socket.send(JSON.stringify({
        'message': 'Hello, Server!'
    }));
};

socket.onmessage = function(e) {
    console.log('Message received:', e.data);
};

socket.onclose = function(e) {
    console.log('Connection closed');
};

View logs of your django application

sudo journalctl -u django-websocket -f

Restart your django application

sudo systemctl restart django-websocket

Common Issues and Solutions

  1. WebSocket Connection Failed

    • Verify Nginx WebSocket configuration

    • Check firewall settings

    • Ensure SSL is properly configured

  2. Static Files Not Loading

    • Run python manage.py collectstatic

    • Check Nginx static files configuration

If you have any issues or doubts feel free to react out to me!!

1
Subscribe to my newsletter

Read articles from Dhairya Patel directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Dhairya Patel
Dhairya Patel

A DevOps Engineer with 2 year of experience as infrastructure support (AWS, Linux, Azure), DevOps (Build, CICD & Release Management)