Skip to content

Django - Apache Setup

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.

myproject/
manage.py
myproject/
__init__.py
settings.py
urls.py
wsgi.py <-- This file connects Django to the WSGI server

This 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.

  • Apache web server installed.
  • The mod_wsgi module for Apache installed and enabled. Ensure you install the version compatible with your Python 3 installation (e.g., python3-mod-wsgi or similar package name depending on your OS).
  • Your Django project code deployed to the server (e.g., in /srv/myproject).

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>
  • ServerName, ServerAlias: Define the domain(s) this configuration applies to.
  • Alias /static/ ...: Tells Apache to serve files requested under /static/ directly from your STATIC_ROOT directory (e.g., /srv/myproject/staticfiles). You must run python manage.py collectstatic first.
  • <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 by MEDIA_ROOT (e.g., /srv/myproject/mediafiles).
  • WSGIDaemonProcess: Defines a daemon process group to run your Django application. python-home should point to your virtual environment, and python-path to 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’s wsgi.py file, telling Apache to pass requests to Django via mod_wsgi.

After creating or modifying the configuration:

Section titled “After creating or modifying the configuration:”
  1. Enable the site (e.g., sudo a2ensite myproject.conf on Debian/Ubuntu).
  2. Check the Apache configuration for errors (e.g., sudo apache2ctl configtest or sudo httpd -t).
  3. Restart or reload Apache (e.g., sudo systemctl restart apache2 or sudo systemctl reload httpd).

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.

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.

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.

  1. Install Nginx and Gunicorn (pip install gunicorn).
  2. 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 like systemd or supervisor.
  3. 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.
  4. Detailed configuration for this setup is beyond the scope of this chapter but widely documented online. Search for ‘deploy django nginx gunicorn’.