Setting Up a Secure Django Environment with PostgreSQL, Nginx, and Gunicorn on Ubuntu
Introduction
Django is a powerful web framework that allows you to quickly build robust applications in Python. While its local development server is great for development, production environments require a more secure and scalable setup.
In this guide, we'll walk you through the process of deploying a Django project on an Ubuntu server with a PostgreSQL database, using Gunicorn to serve the application and Nginx as a reverse proxy. This setup enhances security and performance by leveraging the strengths of each component.
We'll also discuss how to configure systemd to manage Gunicorn and set up a virtual environment for isolating dependencies.
Prerequisites
An Ubuntu 22.04 server or newer with a non-root user and sudo privileges
An active firewall
A registered domain name (optional but recommended)
Step 1: Install Required Packages
First, update your package lists:
sudo apt update sudo apt upgrade -yNext, install Python, PostgreSQL, and Nginx, along with other dependencies:
sudo apt install python3-venv python3-dev libpq-dev postgresql postgresql-contrib nginx curl -y
Step 2: Configure PostgreSQL Database
Switch to the
postgresuser:sudo -u postgres psqlCreate a new PostgreSQL database and user, replacing
myprojectandmyprojectuserwith your project’s name:CREATE DATABASE myproject; CREATE USER myprojectuser WITH PASSWORD 'password'; 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 the PostgreSQL prompt:
\q
Step 3: Set Up the Python Virtual Environment
Create and navigate to your project directory:
mkdir ~/myprojectdir cd ~/myprojectdirSet up a virtual environment and activate it:
python3 -m venv myprojectenv source myprojectenv/bin/activateInstall Django, Gunicorn, and the PostgreSQL adapter:
pip install django gunicorn psycopg2-binary
Step 4: Create and Configure the Django Project
Start a new Django project:
django-admin startproject myproject .Configure
ALLOWED_HOSTSinmyproject/settings.py:ALLOWED_HOSTS = ['your_domain.com', 'your_server_ip', 'localhost']Set up the PostgreSQL database connection in
myproject/settings.py:DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'myproject', 'USER': 'myprojectuser', 'PASSWORD': 'password', 'HOST': 'localhost', 'PORT': '', } }Set up static files:
STATIC_URL = '/static/' STATIC_ROOT = BASE_DIR / 'static'
Step 5: Complete Django Setup
Migrate the database schema:
python manage.py migrateCreate a Django superuser:
python manage.py createsuperuserCollect static files:
python manage.py collectstatic
Step 6: Test Gunicorn's Ability to Serve the Project
Run Gunicorn to test serving your application:
gunicorn --bind 0.0.0.0:8000 myproject.wsgiVisit
http://your_server_ip:8000to verify that Django is running.
Step 7: Create Gunicorn systemd Socket and Service Files
Create a Gunicorn socket file:
sudo nano /etc/systemd/system/gunicorn.socketAdd the following content:
[Unit] Description=gunicorn socket [Socket] ListenStream=/run/gunicorn.sock [Install] WantedBy=sockets.targetCreate a Gunicorn service file:
sudo nano /etc/systemd/system/gunicorn.serviceAdd the following content, replacing paths and user details as needed:
[Unit] Description=gunicorn daemon Requires=gunicorn.socket After=network.target [Service] User=user_name Group=www-data WorkingDirectory=/home/user_name/myprojectdir ExecStart=/home/user_name/myprojectdir/myprojectenv/bin/gunicorn \ --access-logfile - \ --workers 3 \ --bind unix:/run/gunicorn.sock \ myproject.wsgi:application [Install] WantedBy=multi-user.targetStart and enable the Gunicorn socket:
sudo systemctl start gunicorn.socket sudo systemctl enable gunicorn.socket
Step 8: Configure Nginx as a Reverse Proxy
Create an Nginx configuration file:
sudo nano /etc/nginx/sites-available/myprojectAdd the following content:
server { listen 80; server_name your_domain.com your_server_ip; location / { proxy_pass http://unix:/run/gunicorn.sock; 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; } location /static/ { alias /home/awm/myprojectdir/static/; } }Enable the configuration and restart Nginx:
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled sudo nginx -t sudo systemctl restart nginx
Step 9: Troubleshoot and Complete Setup
If Nginx or Gunicorn is not running, check their logs:
sudo journalctl -u nginx sudo journalctl -u gunicorn
Following this setup, your Django application will be served through Nginx and Gunicorn, backed by PostgreSQL for database management, and secured on Ubuntu.


