Django - Apache Setup
Deploying Django with Apache and mod_wsgi
Section titled “Deploying Django with Apache and mod_wsgi”Throughout this tutorial, we’ve relied on Django’s built-in development server (manage.py runserver). While excellent for development and testing due to its automatic reloading features, it is not suitable for production environments. It hasn’t undergone security audits and isn’t designed to handle high traffic loads.
For production deployment, you need a robust web server like Apache or Nginx, combined with a WSGI (Web Server Gateway Interface) server. WSGI is the standard interface between Python web applications and web servers. Django includes a wsgi.py file in your project structure specifically for this purpose.
Project Structure Reminder:
Section titled “Project Structure Reminder:”myproject/ manage.py myproject/ __init__.py settings.py urls.py wsgi.py <-- This file connects Django to the WSGI serverThis chapter focuses on deploying Django using Apache with the mod_wsgi module. While still a valid option, many modern deployments prefer using Nginx with a dedicated WSGI server like Gunicorn or uWSGI for potentially better performance and easier configuration, especially in containerized setups (like Docker). However, understanding Apache/mod_wsgi is still valuable.
Prerequisites
Section titled “Prerequisites”- Apache web server installed.
- The
mod_wsgimodule for Apache installed and enabled. Ensure you install the version compatible with your Python 3 installation (e.g.,python3-mod-wsgior similar package name depending on your OS). - Your Django project code deployed to the server (e.g., in
/srv/myproject).
Apache Configuration (using Virtual Host)
Section titled “Apache Configuration (using Virtual Host)”It’s best practice to configure Apache using virtual hosts rather than editing the main httpd.conf or apache2.conf directly. Create a configuration file for your site (e.g., /etc/apache2/sites-available/myproject.conf on Debian/Ubuntu or /etc/httpd/conf.d/myproject.conf on CentOS/RHEL).
Here’s a basic example configuration:
<VirtualHost *:80> ServerName your_domain.com ServerAlias www.your_domain.com
# Alias for static files (collected via collectstatic) Alias /static/ /srv/myproject/staticfiles/ <Directory /srv/myproject/staticfiles> Require all granted </Directory>
# Alias for media files (user uploads) Alias /media/ /srv/myproject/mediafiles/ <Directory /srv/myproject/mediafiles> Require all granted </Directory>
# WSGI configuration WSGIDaemonProcess myproject python-home=/srv/myproject/venv python-path=/srv/myproject WSGIProcessGroup myproject WSGIScriptAlias / /srv/myproject/myproject/wsgi.py
<Directory /srv/myproject/myproject> <Files wsgi.py> Require all granted </Files> </Directory>
ErrorLog ${APACHE_LOG_DIR}/myproject_error.log CustomLog ${APACHE_LOG_DIR}/myproject_access.log combined</VirtualHost>Key Configuration Directives Explained:
Section titled “Key Configuration Directives Explained:”ServerName,ServerAlias: Define the domain(s) this configuration applies to.Alias /static/ ...: Tells Apache to serve files requested under/static/directly from yourSTATIC_ROOTdirectory (e.g.,/srv/myproject/staticfiles). You must runpython manage.py collectstaticfirst.<Directory ...> Require all granted </Directory>: Grants Apache permission to serve files from these directories (using Apache 2.4+ syntax).Alias /media/ ...: Similar to static files, but for user-uploaded content defined byMEDIA_ROOT(e.g.,/srv/myproject/mediafiles).WSGIDaemonProcess: Defines a daemon process group to run your Django application.python-homeshould point to your virtual environment, andpython-pathto your project’s base directory.WSGIProcessGroup: Assigns the application to the defined daemon process group.WSGIScriptAlias / /path/to/myproject/myproject/wsgi.py: The core directive mapping the root URL (/) to your Django project’swsgi.pyfile, telling Apache to pass requests to Django via mod_wsgi.
After creating or modifying the configuration:
Section titled “After creating or modifying the configuration:”- Enable the site (e.g.,
sudo a2ensite myproject.confon Debian/Ubuntu). - Check the Apache configuration for errors (e.g.,
sudo apache2ctl configtestorsudo httpd -t). - Restart or reload Apache (e.g.,
sudo systemctl restart apache2orsudo systemctl reload httpd).
Ensure File Permissions
Section titled “Ensure File Permissions”The user Apache runs as (e.g., www-data, apache) needs read access to your project files and your virtual environment, and potentially write access to your media directory and database file (if using SQLite). Adjust permissions accordingly.
Accessing Your Site
Section titled “Accessing Your Site”If everything is configured correctly, accessing http://your_domain.com (or the server’s IP address if testing locally without a domain) should now serve your Django application, not just list directories.
Alternative: Nginx + Gunicorn/uWSGI
Section titled “Alternative: Nginx + Gunicorn/uWSGI”As mentioned, a popular alternative is using Nginx as a reverse proxy in front of a dedicated WSGI server like Gunicorn or uWSGI. Gunicorn is often favored for its simplicity.
- Install Nginx and Gunicorn (
pip install gunicorn). - Run Gunicorn, telling it to serve your Django app (e.g.,
gunicorn --bind 0.0.0.0:8000 myproject.wsgi). Often managed via a process supervisor likesystemdorsupervisor. - Configure Nginx as a reverse proxy to pass requests to Gunicorn (running on port 8000 in this example). Nginx would also handle serving static and media files directly.
- Detailed configuration for this setup is beyond the scope of this chapter but widely documented online. Search for ‘deploy django nginx gunicorn’.
Further Reading:
Section titled “Further Reading:”- Django Deployment Documentation: https://docs.djangoproject.com/en/stable/howto/deployment/
- mod_wsgi Documentation: https://modwsgi.readthedocs.io/en/master/