Skip to main content

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

Published 4 min readMarkdown

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.

17 views

No comments yet. Be the first to comment.