Table of Contents
What you will read?
- 1 Verify RHEL version and update packages
- 2 Install Python 3 and pip from AppStream
- 3 Create a dedicated Django user (optional)
- 4 Create and activate a Python virtual environment
- 5 Install Django with pip
- 6 Create a new Django project
- 7 Run the development server
- 8 Allow port 8000 in the firewall (temporary for dev)
- 9 Install Gunicorn for production
- 10 Create a systemd service for Gunicorn
- 11 Install and configure Nginx as reverse proxy
- 12 Adjust SELinux and firewall for Nginx
- 13 Collect static files (production)
To install Django on RHEL 8 or RHEL 9, use the following dnf commands to set up dependencies, create a virtual environment, and run a sample project. Both development and production setups are outlined briefly, with notes on handling common issues such as SELinux and firewall configurations.
Verify RHEL version and update packages
Confirm the OS version and refresh repositories. Having sudo/root is required.
cat /etc/redhat-release
sudo dnf -y update
sudo dnf -y install sudo curl tar git
Example output:
Red Hat Enterprise Linux release 9.x (Plow)
Install Python 3 and pip from AppStream
Use RHEL modules to select a supported Python stream, then install pip and headers.
sudo dnf module list python
# RHEL 9 (recommended):
sudo dnf module enable -y python:3.9
# Optional on RHEL 9 if you prefer newer:
# sudo dnf module enable -y python:3.11
# RHEL 8 (use the highest available, often 3.9 on newer 8.x):
# sudo dnf module enable -y python:3.9
sudo dnf -y install python3 python3-pip python3-devel gcc
Verify versions:
python3 --version
pip3 --version
Create a dedicated Django user (optional)
Run Django under an unprivileged account to reduce risk and keep files organized.
sudo useradd --create-home --shell /bin/bash django
# Lock password-based login if using SSH keys only:
sudo passwd -l django
Create and activate a Python virtual environment
Isolate project dependencies to avoid system-wide conflicts.
# As root or your admin user:
sudo -iu django
python3 -m venv ~/venvs/djangoenv
source ~/venvs/djangoenv/bin/activate
python -V
pip install --upgrade pip setuptools wheel
Install Django with pip
Install an LTS or the latest stable series. Pinning improves reproducibility.
# LTS (stable for long-term):
pip install "Django>=4.2,<4.3" # Or current stable (example): # pip install "Django>=5.1,<5.2"
python -m django --version
Create a new Django project
Initialize a clean project skeleton and apply initial migrations.
django-admin startproject mysite ~/apps/mysite
cd ~/apps/mysite
python manage.py migrate
Run the development server
Launch the built-in server for quick validation. Bind to 0.0.0.0 to test remotely.
python manage.py runserver 0.0.0.0:8000
Example output:
Starting development server at http://0.0.0.0:8000/
Allow port 8000 in the firewall (temporary for dev)
Open the port to access from your browser. Close after testing or move behind a reverse proxy.
sudo firewall-cmd --add-port=8000/tcp --permanent
sudo firewall-cmd --reload
Install Gunicorn for production
Use Gunicorn as the WSGI HTTP server. Keep it inside the same virtual environment.
# Inside the venv:
pip install "gunicorn>=21.2,<22"
# Quick test:
cd ~/apps/mysite
gunicorn --bind 0.0.0.0:8000 mysite.wsgi:application
Create a systemd service for Gunicorn
Run Gunicorn as a managed service that restarts on failure.
sudo tee /etc/systemd/system/gunicorn-mysite.service >/dev/null <<'EOF'
[Unit]
Description=Gunicorn for Django mysite
After=network.target
[Service]
User=django
Group=django
WorkingDirectory=/home/django/apps/mysite
Environment="PATH=/home/django/venvs/djangoenv/bin"
ExecStart=/home/django/venvs/djangoenv/bin/gunicorn --workers 3 --bind unix:/run/gunicorn-mysite.sock mysite.wsgi:application
RuntimeDirectory=gunicorn
RuntimeDirectoryMode=0755
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now gunicorn-mysite
sudo systemctl status gunicorn-mysite --no-pager
Install and configure Nginx as reverse proxy
Terminate HTTP and proxy to the Gunicorn UNIX socket. SELinux remains enforcing-friendly.
sudo dnf -y install nginx
sudo tee /etc/nginx/conf.d/mysite.conf >/dev/null <<'EOF'
server {
listen 80;
server_name _;
access_log /var/log/nginx/mysite_access.log;
error_log /var/log/nginx/mysite_error.log;
location / {
proxy_pass http://unix:/run/gunicorn-mysite.sock;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
EOF
sudo nginx -t
sudo systemctl enable --now nginx
Adjust SELinux and firewall for Nginx
Allow Nginx to connect to Gunicorn and expose HTTP/HTTPS.
sudo setsebool -P httpd_can_network_connect on
sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --add-service=https --permanent
sudo firewall-cmd --reload
Collect static files (production)
Prepare static assets for efficient serving via Nginx.
# In settings.py set: STATIC_ROOT = "/home/django/apps/mysite/static/"
# Then:
sudo -iu django bash -lc 'source ~/venvs/djangoenv/bin/activate && cd ~/apps/mysite && python manage.py collectstatic --noinput'
# Point an Nginx location /static to that directory if desired.
For more guides, visit dropvps.com — You can also explore DropVPS for server purchases, support, and more technical resources.
