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
Step 1: Install Required Packages
First, update your package lists:
sudo apt update
sudo apt upgrade -y
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
Switch to the postgres user:
sudo -u postgres psql
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;
Exit the PostgreSQL prompt:
\q
Step 3: Set Up the Python Virtual Environment
Create and navigate to your project directory:
mkdir ~/myprojectdir
cd ~/myprojectdir
Set up a virtual environment and activate it:
python3 -m venv myprojectenv
source myprojectenv/bin/activate
Install Django, Gunicorn, and the PostgreSQL adapter:
pip install django gunicorn psycopg2-binary
Start a new Django project:
django-admin startproject myproject .
Configure ALLOWED_HOSTS in myproject/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 migrate
Create a Django superuser:
python manage.py createsuperuser
Collect 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.wsgi
Visit http://your_server_ip:8000 to 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.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 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
Start and enable the Gunicorn socket:
sudo systemctl start gunicorn.socket
sudo systemctl enable gunicorn.socket
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/;
}
}
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.