In this post I will show how to deploy a Django applications using Apache with mod-wsgi and nginx.
nginx is used to serve static content as well as proxy requests to Apache. This means faster page loads for users, and lower server loads.
Install Apache2, mod-wsgi and nginx
Install all required packages from repositories:
apt-get install apache2 apache2.2-common apache2-mpm-prefork \ libapache2-mod-wsgi apache2-utils libexpat1 ssl-cert nginx
Install Django
Same as above:
sudo apt-get install python-django
Create Django site folders
sudo mkdir -p /home/sites/domain.tld/{public_html,logs,static} sudo chown -R www-data:www-data /home/sites/
public_html directory will be used for publicly accessible files served by nginx
log directory will store the Apache and Nginx logs for the domain
static directory will store the static content
Create a Django project called proj using django-admin tool:
cd /home/sites/domain.tld/public_html/ django-admin startproject proj
Alter settings.py file and set the MEDIA_URL and MEDIA_ROOT settings appropriately in project settings file /home/sites/domain.tld/public_html/proj/settings.py
MEDIA_ROOT = '/home/sites/domain.tld/static/' MEDIA_URL = 'http://www.domain.tld/static/'
This variables allow to specify the location of static files server by nginx
Configure Apache
To accomplish this, setup a virtual host that tells Apache where is located WSGI file. Open /etc/apache2/sites-available/domain.tld and fill it with following content:
ServerName domain.tld ServerAlias www.domain.tld WSGIScriptAlias / /home/sites/domain.tld/public_html/proj.wsgi
Any request to Apache will execute the WSGI Script from
To tell mod_wsgi how to handle the requests, create a WSGI file located at /home/sites/domain.tld/public_html/proj.wsgi with following contents:
import os import sys sys.path.append('/home/sites/domain.tld/public_html/') os.environ['DJANGO_SETTINGS_MODULE'] = 'proj.settings' import django.core.handlers.wsgi application = django.core.handlers.wsgi.WSGIHandler()
Once the request is passed to mod_wsgi to invoke the above Django code.
Configure nginx
Make small changes to nginx configuration file /etc/nginx/nginx.conf:
worker_processes 4; tcp_nopush on;
This tells nginx to use four worker processes and to send the HTTP response headers in one packet
Create an Nginx virtual host for the domain, by opening in editor /etc/nginx/sites-available/domain.tld and filling it with content:
server { listen ip.address:80; server_name www.domain.tld; access_log /home/sites/domain.tld/logs/access.log; error_log /home/sites/domain.tld/logs/error.log; location / { proxy_pass http://127.0.0.1:80/; include /etc/nginx/proxy.conf; } location /static/ { root /home/sites/domain.tld/static/; expires 1d; } }
The above config tells nginx to pass requests for dynamic content to Apache and to serve the static content if request contains /static location.
Create a /etc/nginx/proxy.conf file with the following contents:
proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 10m; client_body_buffer_size 128k; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90; proxy_buffers 32 4k;
The file tells to nginx how to serve the proxy requests
Apache should listen on local address. Open /etc/apache2/ports.conf and alter the following lines:
NameVirtualHost 127.0.0.1:80 Listen 127.0.0.1:80
Disable KeepAlive in /etc/apache2/apache2.conf:
KeepAlive Off
Because, nginx doesn't yet support the persistent connections.
Enable site
Create a symlinks to the desired virtual hosts. For Apache it could be done with command:
a2ensite domain.tld
For nginx, it is done manually, by symlinking it from sites-available to sites-enabled:
ln -s /etc/nginx/sites-available/domain.tld /etc/nginx/sites-enabled/domain.tld
Run site
Remove the symlinks for default sites and restart the webservers:
rm /etc/nginx/{sites-available,sites-enabled}/default rm /etc/apache2/{sites-available,sites-enabled}/000-default
Restart the webservers to make the updates take effect:
/etc/init.d/apache2 restart /etc/init.d/nginx restart
Navigating to your site address will show the default 'It worked'.