How To Set Up Secure Django with Postgres, Nginx, and Gunicorn on Ubuntu
Introduction
Django is a robust web framework designed to help you rapidly build Python applications or websites. While Django provides a simplified local development server, you’ll need a more secure and scalable server setup for production environments.
This guide will walk you through setting up Django on Ubuntu 22.04 (or a supported version) with a PostgreSQL database. We’ll configure the Gunicorn application server to interface with your Django app and set up Nginx to reverse proxy to Gunicorn, leveraging its security and performance benefits. Additionally, we’ll deploy the application from GitHub using DigitalOcean’s App Platform, allowing automatic scaling and management.
By isolating Django within a virtual environment, you’ll be able to handle project dependencies independently. Once your database and application are live, Gunicorn will translate client requests into Python calls. Nginx will manage connections and serve static files efficiently.
Let’s dive into setting everything up!
Prerequisites
Ensure you’re using Ubuntu 22.04 or newer, as older versions like 16.04 are no longer supported. Follow our server setup guide to create a non-root user with sudo
privileges and an active firewall.
Steps to Set Up Django with PostgreSQL, Gunicorn, and Nginx
Install Packages from Ubuntu Repositories
Create PostgreSQL Database and User
Set Up a Python Virtual Environment
Create and Configure Your Django Project
Complete the Django Setup
Test Gunicorn’s Ability to Serve Django
Create Gunicorn
systemd
Socket and Service FilesCheck Gunicorn Socket File
Configure Nginx to Proxy Gunicorn
Troubleshoot and Complete Setup
Step 1 — Install Packages from Ubuntu Repositories
Start by updating your package lists and installing the required packages:
sudo apt update
sudo apt install python3-venv python3-dev libpq-dev postgresql postgresql-contrib nginx curl
This will install Python, PostgreSQL, and Nginx, alongside development libraries and tools required for your project.
Step 2 — Create PostgreSQL Database and User
Set up your PostgreSQL database and user:
- Log in as the
postgres
user and access PostgreSQL:
sudo -u postgres psql
- Create the database and user for your Django project:
CREATE DATABASE myproject;
CREATE USER myprojectuser WITH PASSWORD 'password';
- Configure the user’s access and settings:
ALTER ROLE myprojectuser SET client_encoding TO 'utf8';
ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';
ALTER ROLE myprojectuser SET timezone TO 'UTC';
GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;
- Exit PostgreSQL:
\q
Step 3 — Set Up a Python Virtual Environment
Create a virtual environment and install Django:
- Create and navigate to your project directory:
mkdir ~/myprojectdir
cd ~/myprojectdir
- Create and activate a virtual environment:
python3 -m venv myprojectenv
source myprojectenv/bin/activate
- Install Django, Gunicorn, and PostgreSQL adapter:
pip install django gunicorn psycopg2-binary
Step 4 — Create and Configure a New Django Project
- Create a new Django project:
django-admin startproject myproject .
- Update Django settings:
- Modify
ALLOWED_HOSTS
inmyproject/
settings.py
:
ALLOWED_HOSTS = ['your_server_domain_or_IP', 'localhost']
- Configure PostgreSQL database settings:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'myproject',
'USER': 'myprojectuser',
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '',
}
}
- Configure static files:
STATIC_URL = 'static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
Step 5 — Complete the Django Setup
- Migrate the database schema:
python manage.py migrate
- Create a Django superuser:
python manage.py createsuperuser
- Collect static files:
python manage.py collectstatic
- Open firewall for testing:
sudo ufw allow 8000
- Test the development server:
python manage.py runserver 0.0.0.0:8000
Visit http://your_server_domain_or_IP:8000
in your browser to verify that Django is running.
Step 6 — Test Gunicorn’s Ability to Serve the Project
Stop the Django development server and test Gunicorn:
- Run Gunicorn:
gunicorn --bind 0.0.0.0:8000 myproject.wsgi
- Visit your server again to ensure the app is served.
Step 7 — Create Gunicorn systemd
Socket and Service Files
Create socket and service files for Gunicorn:
- Create a Gunicorn socket file:
sudo nano /etc/systemd/system/gunicorn.socket
Add the following content:
[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.target
- Create a Gunicorn service file:
sudo nano /etc/systemd/system/gunicorn.service
Add this content:
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
User=your_user
Group=www-data
WorkingDirectory=/home/your_user/myprojectdir
ExecStart=/home/your_user/myprojectdir/myprojectenv/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/run/gunicorn.sock \
myproject.wsgi:application
[Install]
WantedBy=multi-user.target
- Start and enable the Gunicorn socket:
sudo systemctl start gunicorn.socket
sudo systemctl enable gunicorn.socket
Step 8 — Check the Gunicorn Socket File
Verify that Gunicorn started properly:
sudo systemctl status gunicorn.socket
You should see a message indicating that the socket is active.
Check for the socket file:
file /run/gunicorn.sock
If there’s an issue, check the logs:
sudo journalctl -u gunicorn.socket
Step 9 — Configure Nginx to Proxy Gunicorn
- Create a new Nginx server block:
sudo nano /etc/nginx/sites-available/myproject
Add this content:
server {
listen 80;
server_name your_server_domain_or_IP;
location / {
proxy_pass http://unix:/run/gunicorn.sock;
}
location /static/ {
alias /home/your_user/myprojectdir/static/;
}
}
- Enable the configuration:
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
sudo nginx -t
- Restart Nginx:
sudo systemctl restart nginx
Step 10 — Troubleshoot Nginx and Gunicorn
If you encounter any issues, check Nginx’s error log:
sudo journalctl -u nginx
And Gunicorn’s logs:
sudo journalctl -u gunicorn
If everything is working, your Django application should now be live, served via Nginx and Gunicorn with PostgreSQL as the database backend!
Subscribe to my newsletter
Read articles from Sundar Adhikari directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by