Django Apache
Introduction
Deploying Django applications to production requires a robust, efficient, and secure web server. Apache HTTP Server, often simply called Apache, is one of the most popular web servers that can be used to deploy Django applications. In this tutorial, we'll explore how to configure Apache to serve Django applications using mod_wsgi
, a module that provides a WSGI compliant interface for hosting Python web applications.
Apache offers several advantages for Django deployments:
- Mature and stable platform with excellent documentation
- Highly configurable with many modules available
- Ability to serve multiple applications and static files efficiently
- Robust security features
- Wide adoption across hosting providers
Prerequisites
Before we begin, make sure you have:
- A working Django application
- Ubuntu/Debian or a similar Linux distribution (commands may vary for other distributions)
- Basic knowledge of terminal/command line
- Administrative access to install packages
Understanding Django-Apache Architecture
When deploying Django with Apache, here's what happens:
- Apache receives HTTP requests from clients
- The
mod_wsgi
module passes these requests to your Django application - Django processes the request, generates a response
- The response is sent back through Apache to the client
Client ↔ Apache ↔ mod_wsgi ↔ Django Application
Installation Process
Step 1: Install Apache and mod_wsgi
# Update package lists
sudo apt-get update
# Install Apache and related tools
sudo apt-get install apache2 apache2-utils
# Install mod_wsgi for Python 3
sudo apt-get install libapache2-mod-wsgi-py3
After installation, verify that Apache is running:
sudo systemctl status apache2
Expected output:
● apache2.service - The Apache HTTP Server
Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2023-04-10 12:34:56 UTC; 5s ago
Step 2: Prepare Your Django Project
Make sure your Django project is ready for deployment:
- Set
DEBUG = False
in your settings.py - Configure
ALLOWED_HOSTS
with your domain or IP address - Set up a proper
SECRET_KEY
(preferably from environment variables) - Configure static and media files properly
# settings.py
DEBUG = False
ALLOWED_HOSTS = ['yourdomain.com', 'www.yourdomain.com', 'your-server-ip']
# Static files configuration
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
# Media files configuration
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Step 3: Create a WSGI Configuration File
Create a file named django.wsgi
(or any name you prefer) in your project directory:
import os
import sys
# Add your project directory to the sys.path
path = '/path/to/your/django_project'
if path not in sys.path:
sys.path.insert(0, path)
# Set environment variable to tell Django where your settings.py is
os.environ['DJANGO_SETTINGS_MODULE'] = 'your_project.settings'
# Set up Django
import django
django.setup()
# Import the WSGI application object
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
Step 4: Configure Apache Virtual Host
Create a new virtual host configuration file:
sudo nano /etc/apache2/sites-available/django_project.conf
Add the following configuration (adjust paths according to your setup):
<VirtualHost *:80>
# Set your domain name
ServerName yourdomain.com
ServerAlias www.yourdomain.com
# Set administrator email
ServerAdmin [email protected]
# Set document root
DocumentRoot /path/to/your/django_project
# Configure WSGI
WSGIDaemonProcess django_app python-home=/path/to/your/virtualenv python-path=/path/to/your/django_project
WSGIProcessGroup django_app
WSGIScriptAlias / /path/to/your/django_project/django.wsgi
# Configure static files
Alias /static/ /path/to/your/django_project/staticfiles/
<Directory /path/to/your/django_project/staticfiles>
Require all granted
</Directory>
# Configure media files
Alias /media/ /path/to/your/django_project/media/
<Directory /path/to/your/django_project/media>
Require all granted
</Directory>
# Configure access to the WSGI file
<Directory /path/to/your/django_project>
<Files django.wsgi>
Require all granted
</Files>
</Directory>
# Error log and access log configuration
ErrorLog ${APACHE_LOG_DIR}/django-error.log
CustomLog ${APACHE_LOG_DIR}/django-access.log combined
</VirtualHost>
Step 5: Enable the Site and Restart Apache
# Enable the site
sudo a2ensite django_project.conf
# Enable required Apache modules (if not already enabled)
sudo a2enmod wsgi
# Check Apache configuration for syntax errors
sudo apache2ctl configtest
# Restart Apache
sudo systemctl restart apache2
Common Issues and Troubleshooting
Permissions Problems
One of the most common issues is permission problems. Apache runs as a different user (usually www-data
), so it needs proper permissions to access your files.
# Change ownership of project files to Apache user
sudo chown -R www-data:www-data /path/to/your/django_project
# Make sure the directory is accessible
sudo chmod -R 755 /path/to/your/django_project
500 Internal Server Error
If you're getting 500 errors, check Apache's error logs:
sudo tail -f /var/log/apache2/django-error.log
Static Files Not Loading
Make sure you've run Django's collectstatic command:
python manage.py collectstatic
Also, verify that the STATIC_ROOT
in your Django settings matches the directory specified in the Apache configuration.
Advanced Configuration
Setting Up HTTPS with Let's Encrypt
For a production site, you'll want to enable HTTPS. Let's Encrypt provides free SSL certificates:
# Install certbot
sudo apt-get install certbot python3-certbot-apache
# Obtain and install a certificate
sudo certbot --apache -d yourdomain.com -d www.yourdomain.com
Virtual Environment Integration
Ensure Apache uses your project's virtual environment:
WSGIDaemonProcess django_app python-home=/path/to/your/virtualenv python-path=/path/to/your/django_project
Load Balancing with mod_wsgi Daemon Mode
For high-traffic sites, configure multiple processes:
WSGIDaemonProcess django_app processes=5 threads=15 python-home=/path/to/your/virtualenv python-path=/path/to/your/django_project
Real-world Example: Complete Deployment
Let's walk through a complete example of deploying a blog application:
- Project structure:
/home/user/myblog/
├── blog/
│ ├── __init__.py
│ ├── models.py
│ ├── views.py
│ └── ...
├── myblog/
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ ├── wsgi.py
│ └── ...
├── manage.py
└── requirements.txt
- Create a virtual environment and install dependencies:
cd /home/user/
python3 -m venv myblog_env
source myblog_env/bin/activate
pip install -r myblog/requirements.txt
- Configure Django settings for production:
# myblog/settings.py
DEBUG = False
ALLOWED_HOSTS = ['blog.example.com']
STATIC_ROOT = '/home/user/myblog/staticfiles'
- Create a WSGI file:
# /home/user/myblog/myblog_wsgi.py
import os
import sys
path = '/home/user/myblog'
if path not in sys.path:
sys.path.insert(0, path)
os.environ['DJANGO_SETTINGS_MODULE'] = 'myblog.settings'
import django
django.setup()
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
- Configure Apache:
# /etc/apache2/sites-available/myblog.conf
<VirtualHost *:80>
ServerName blog.example.com
WSGIDaemonProcess myblog python-home=/home/user/myblog_env python-path=/home/user/myblog
WSGIProcessGroup myblog
WSGIScriptAlias / /home/user/myblog/myblog_wsgi.py
Alias /static/ /home/user/myblog/staticfiles/
<Directory /home/user/myblog/staticfiles>
Require all granted
</Directory>
<Directory /home/user/myblog>
<Files myblog_wsgi.py>
Require all granted
</Files>
</Directory>
ErrorLog ${APACHE_LOG_DIR}/myblog-error.log
CustomLog ${APACHE_LOG_DIR}/myblog-access.log combined
</VirtualHost>
- Collect static files and set permissions:
python manage.py collectstatic
sudo chown -R www-data:www-data /home/user/myblog
sudo chown -R www-data:www-data /home/user/myblog_env
- Enable the site and restart Apache:
sudo a2ensite myblog.conf
sudo systemctl restart apache2
Summary
In this tutorial, we've covered how to deploy a Django application with Apache and mod_wsgi
. We've gone through:
- Installing Apache and
mod_wsgi
- Configuring Django for production
- Creating a WSGI file
- Setting up an Apache virtual host
- Handling common issues and troubleshooting
- Advanced configurations including HTTPS setup
- A complete real-world deployment example
Apache with mod_wsgi
is a battle-tested, reliable way to deploy Django applications in production environments. While the initial setup may seem complex compared to some newer deployment methods, it provides a high level of control and excellent performance for Django applications.
Additional Resources
- Official Django Deployment Checklist
- mod_wsgi Documentation
- Apache HTTP Server Documentation
- Let's Encrypt Documentation
Exercises
- Deploy a basic Django "Hello World" app using Apache and
mod_wsgi
. - Configure your deployment to serve both Django and a separate static HTML site under different URLs.
- Set up two different Django projects under different subdomains using the same Apache server.
- Implement HTTPS on your Django deployment using Let's Encrypt.
- Configure Apache to serve a Django application with WebSockets support for features like real-time chat.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)