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.