Skip to main content

Command Palette

Search for a command to run...

Setting Up a Secure Django Environment with PostgreSQL, Nginx, and Gunicorn on Ubuntu

Updated
4 min read

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

  1. First, update your package lists:

     sudo apt update
     sudo apt upgrade -y
    
  2. Next, 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

  1. Switch to the postgres user:

     sudo -u postgres psql
    
  2. Create a new PostgreSQL database and user, replacing myproject and myprojectuser with 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;
    
  3. Exit the PostgreSQL prompt:

     \q
    

Step 3: Set Up the Python Virtual Environment

  1. Create and navigate to your project directory:

     mkdir ~/myprojectdir
     cd ~/myprojectdir
    
  2. Set up a virtual environment and activate it:

     python3 -m venv myprojectenv
     source myprojectenv/bin/activate
    
  3. Install Django, Gunicorn, and the PostgreSQL adapter:

     pip install django gunicorn psycopg2-binary
    

Step 4: Create and Configure the Django Project

  1. Start a new Django project:

     django-admin startproject myproject .
    
  2. Configure ALLOWED_HOSTS in myproject/settings.py:

     ALLOWED_HOSTS = ['your_domain.com', 'your_server_ip', 'localhost']
    
  3. 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': '',
         }
     }
    
  4. Set up static files:

     STATIC_URL = '/static/'
     STATIC_ROOT = BASE_DIR / 'static'
    

Step 5: Complete Django Setup

  1. Migrate the database schema:

     python manage.py migrate
    
  2. Create a Django superuser:

     python manage.py createsuperuser
    
  3. Collect static files:

     python manage.py collectstatic
    

Step 6: Test Gunicorn's Ability to Serve the Project

  1. Run Gunicorn to test serving your application:

     gunicorn --bind 0.0.0.0:8000 myproject.wsgi
    
  2. Visit http://your_server_ip:8000 to verify that Django is running.


Step 7: Create Gunicorn systemd Socket and Service Files

  1. 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
    
  2. Create a Gunicorn service file:

     sudo nano /etc/systemd/system/gunicorn.service
    

    Add 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.target
    
  3. Start and enable the Gunicorn socket:

     sudo systemctl start gunicorn.socket
     sudo systemctl enable gunicorn.socket
    

Step 8: Configure Nginx as a Reverse Proxy

  1. Create an Nginx configuration file:

     sudo nano /etc/nginx/sites-available/myproject
    

    Add 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/;
         }
     }
    
  2. 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

  1. 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.

15 views