Setting up Django and your web server with uWSGI and nginx on Ubuntu

Post Date: October 05, 2018
Last Updated: September 22, 2026

Introduction

Deploying a Django application in a production environment requires more than just running the built-in Django development server. While the development server is useful for testing and development, it is not designed to handle production workloads, security requirements, or high traffic.

In this tutorial, we will learn how to deploy a Django application on Ubuntu 16.04 using uWSGI and Nginx. uWSGI acts as the application server that runs your Django application, while Nginx serves as the reverse proxy that handles incoming requests and efficiently serves static content.

By following this guide, you will be able to:

  • Install Django and its dependencies
  • Configure Python virtual environments
  • Install and configure uWSGI
  • Configure uWSGI Emperor mode
  • Create a Django application configuration
  • Configure Nginx as a reverse proxy
  • Serve static and media files
  • Manage Django services efficiently

Requirements

Before proceeding, ensure you have the following:

  • Ubuntu 16.04 Server
  • Python 3.6
  • Django 2.0.7
  • Nginx 1.10.3
  • Root or sudo access

Step 1: Install Python Dependencies

Install the required Python packages and development libraries:

sudo apt-get update
sudo apt-get install python3-dev python3-pip
sudo apt-get install python3-setuptools
sudo apt-get install python3-kivy

Verify the Python installation:

python3 --version
pip3 --version

Step 2: Install Virtual Environment

Virtual environments help isolate project dependencies from the system Python installation.

Install Virtual Environment tools:

pip3 install virtualenv virtualenvwrapper

Create a virtual environment:

virtualenv webapp-env

Activate the environment:

source webapp-env/bin/activate

Step 3: Install Django

Install Django using pip:

pip3 install django

Verify installation:

django-admin --version

Step 4: Install uWSGI

Install uWSGI:

sudo pip install uwsgi

Verify installation:

uwsgi --version

Step 5: Configure uWSGI Directory Structure

Create the required uWSGI directories:

cd /etc

sudo mkdir uwsgi

cd uwsgi

sudo mkdir vassals

cd vassals

sudo mkdir enabled

sudo mkdir available

The structure will look like:

/etc/uwsgi/
└── vassals
    ├── available
    └── enabled

Step 6: Configure uWSGI Emperor

Create the Emperor configuration file:

sudo nano /etc/uwsgi/vassals/emperor.ini

Add the following content:

[uwsgi]
emperor = /etc/uwsgi/vassals/enabled

The Emperor process automatically manages all uWSGI instances located in the enabled directory.


Step 7: Create uWSGI Systemd Service

Create a systemd service file:

sudo vi /etc/systemd/system/uwsgi.service

Add the following content:

[Unit]
Description=uWSGI Emperor
After=syslog.target

[Service]
ExecStart=/usr/local/bin/uwsgi --ini /etc/uwsgi/vassals/emperor.ini
RuntimeDirectory=uwsgi
Restart=always
KillSignal=SIGQUIT
Type=notify
StandardError=syslog
NotifyAccess=all

[Install]
WantedBy=multi-user.target

Reload systemd:

sudo systemctl daemon-reload

Start the service:

sudo systemctl start uwsgi

Check service status:

systemctl status uwsgi

Enable service at boot:

sudo systemctl enable uwsgi

Stop service if required:

sudo systemctl stop uwsgi

Step 8: Configure Django Project for uWSGI

Create a new configuration file:

vi /etc/uwsgi/vassals/available/web_app.ini

Add the following content:

[uwsgi]

# Django project directory
chdir = /var/www/webapp

# Django WSGI module
module = webapp.wsgi

enable-threads = true

# Process settings
master = true
processes = 10
listen = 100

# Socket configuration
socket = /var/www/webapp/webapp/web_app.sock
chmod-socket = 666

# Cleanup
vacuum = true

# Limits
max-requests = 1000

# Logging
daemonize = /var/log/uwsgi-emperor.log

Step 9: Enable the Application

Create a symbolic link:

ln -s /etc/uwsgi/vassals/available/web_app.ini /etc/uwsgi/vassals/enabled/

This allows the Emperor process to automatically detect and manage the application.


Step 10: Upload Your Django Project

Ensure your Django application is located under:

/var/www/webapp

Verify the directory:

ls -l /var/www/webapp

Example output:

drwxr-xr-x 3 www-data www-data 4096 Sep 14 05:41 bin
drwxr-xr-x 6 root root 4096 Oct 4 13:46 webapp
-rwxr-xr-x 1 root root 538 Aug 10 02:14 manage.py
-rw-r--r-- 1 root root 275 Aug 10 02:14 requirements

Step 11: Verify Django Application

Before configuring Nginx, ensure Django runs correctly:

python3 manage.py runserver 0.0.0.0:8000

Expected output:

Performing system checks...

System check identified no issues.
Django version 2.0.7
Starting development server at http://0.0.0.0:8000/

If there are no errors, proceed to the next step.


Step 12: Configure Nginx Virtual Host

Create a new Nginx configuration:

vi /etc/nginx/sites-available/webapp.com

Add the following content:

upstream web_app {
    server unix:///var/www/webapp/webapp/web_app.sock;
}

server {
    listen 80;
    server_name pheonixsolutions.com;

    charset utf-8;

    client_max_body_size 75M;

    location /media {
        alias /var/www/webapp/webapp/media;
    }

    location /static {
        alias /var/www/webapp/webapp/static;
    }

    location / {
        uwsgi_pass web_app;
        include /etc/nginx/uwsgi_params;
    }
}

Enable the virtual host:

ln -s /etc/nginx/sites-available/webapp.com /etc/nginx/sites-enabled/

Step 13: Test and Reload Nginx

Verify configuration syntax:

nginx -t

If successful, reload Nginx:

systemctl reload nginx

Or:

/etc/init.d/nginx reload

Step 14: Restart uWSGI

Apply configuration changes:

service uwsgi restart

Verify service status:

systemctl status uwsgi

Your application should now be accessible through:

http://pheonixsolutions.com

Additional Tips

Create Django Superuser

Activate the virtual environment:

source /var/www/webapp/bin/activate

Create an administrator account:

python3 manage.py createsuperuser --username=devops --email=devops@pheonixsolutions.com

Follow the prompts to set the password.


Collect Static Files

Collect all static assets into a single location:

python3 manage.py collectstatic

If you encounter errors, ensure the following exists in settings.py:

STATIC_ROOT = '/var/www/webapp/webapp/static/'

Run the command again after saving the changes.


Resolving Django Migration Errors

Sometimes deployments fail because database migrations were not fully applied.

You may encounter errors related to specific modules such as:

core_module

To resolve migration issues:

Generate migrations:

python3.6 manage.py makemigrations core

Apply migrations:

python3.6 manage.py migrate core

Apply all pending migrations:

python3.6 manage.py migrate

Restart uWSGI after migrations:

systemctl restart uwsgi

Verify the application and Django admin panel.


Troubleshooting

Check uWSGI Logs

tail -f /var/log/uwsgi-emperor.log

Check Nginx Error Logs

tail -f /var/log/nginx/error.log

Verify Socket File

ls -la /var/www/webapp/webapp/web_app.sock

Verify Running Services

systemctl status nginx
systemctl status uwsgi

Conclusion

You have successfully deployed a Django application using uWSGI and Nginx on Ubuntu 16.04. This production-ready setup provides improved performance, reliability, and scalability compared to the default Django development server.

By configuring uWSGI Emperor mode, systemd service management, Nginx reverse proxying, and static file handling, you now have a robust architecture capable of serving Django applications in production environments.

Regularly monitor logs, keep dependencies updated, apply security patches, and maintain proper backup procedures to ensure long-term stability and performance of your application.


Frequently Asked Questions (FAQ)

1. Why should I use uWSGI and Nginx instead of Django’s development server?

The Django development server is designed only for development and testing. uWSGI provides efficient application processing, while Nginx handles client requests, static files, SSL termination, and load balancing, making the combination suitable for production deployments.

2. What should I do if static files are not loading?

Ensure the STATIC_ROOT setting is configured correctly in settings.py and run:

python3 manage.py collectstatic

Also verify that the Nginx location /static block points to the correct directory and reload Nginx after making any changes.

3. How do I troubleshoot a 502 Bad Gateway error?

A 502 Bad Gateway error usually means Nginx cannot communicate with uWSGI. Check the uWSGI service status, verify that the socket file exists, and review the uWSGI and Nginx error logs:

systemctl status uwsgi
ls -la /var/www/webapp/webapp/web_app.sock
tail -f /var/log/nginx/error.log

These logs typically provide the information needed to identify and resolve the issue.


Related Article


Talk to our experts

Have a technology challenge or looking for the right solution for your business? Our team can help you with cloud, DevOps, development, infrastructure, design, and more. Feel free to reach out to our experts here.

admin

Our team has expertise across software and web development, WordPress, e-commerce, mobile applications, UI/UX, cloud and infrastructure, DevOps, CI/CD, API integration, security, testing, automation, and technical support. The team also works with AI-based software solutions, LLMs, AI workflows, AI agents, and intelligent application development to help businesses automate processes and build smarter digital solutions. We focus on developing, deploying, maintaining, and optimising secure, scalable, and reliable technology solutions while helping businesses adopt modern technologies and drive digital transformation.

Leave a Reply

Scroll to Top