Production Server for a Django Application: Ubuntu Server 10.04 LTS + Django 1.4 + Nginx + Gunicorn

Many Django tutorials explain how to quickly get a working debug server running (python manage.py runserver
), but deployment in a production environment is often left unexplored or described using unnecessarily complex methods.
In this post, I’ll describe one way to deploy a Django site in a production environment, starting from choosing a hosting provider to setting up a web server. This guide will be useful for those who have learned Django development but lack experience in server deployment. My approach is one of many, but it’s simple, effective, and easy to maintain. We’ll use VPS hosting, Ubuntu 10.04, Nginx, and Gunicorn.
Table of Contents
- Project Structure
- Hosting
- Ubuntu Server
- Project Deployment
- Configuring the Nginx Web Server
- Configuring Gunicorn and Supervisor
- Troubleshooting
- Conclusion
- Useful Links
Project Structure
To proceed, let’s outline the structure of the deployed project:
myproject/ # Project root; note, this is not the root of the source code
├── env/ # Virtual environment created with virtualenv
├── src/ # Source code directory, convenient for IDEs
│ ├── myproject/ # Project source root, typical for Django developers
│ ├── __init__.py
│ ├── settings.py
│ ├── manage.py
│ ├── urls.py
│ ├── myapp1/
│ ├── myapp2/
├── static_content/ # Folder for static/media files served by Nginx
│ ├── static/ # Static files stored in the repository
│ ├── media/ # Media files created by the site during runtime
├── docs/ # Useful documents, config examples, etc.
├── logs/ # Logs related to the site's operation
├── pids/ # PID files
While the source directory’s nesting might seem excessive, my experience shows that the benefits of better organization outweigh the minor operational overhead.
Hosting
For Django, VPS hosting is the most convenient option. After trying several providers, I settled on FirstVDS for its price/performance ratio. For instance, I use a plan with 1500 MB RAM and 24000 MB HDD for about 4 USD/month. Initially, I used their 150 rubles/month plan, though resource optimization was necessary.
For our needs, choose OpenVZ virtualization—sufficient for the task and providing more memory at the same cost. I recommend Ubuntu Server 10.04 LTS as the operating system. While Ubuntu Server 12.04 LTS is available, its templates are relatively new, and hosting support staff do not yet recommend it for production servers.
Ubuntu Server Setup
Once you receive SSH access details via email, connect to the server. In Windows, you can use Putty or its advanced version, Kitty. In Linux, simply use the terminal:
ssh root@<server-ip>
Upon login, update the system, disable root
SSH access, and create a new user:
passwd # Change the root password
apt-get update
apt-get upgrade
adduser myuser # Create a user for deployment
Grant sudo
privileges to the new user and restrict root
SSH access for added security:
nano /etc/sudoers # Add "myuser ALL=(ALL:ALL) ALL"
nano /etc/ssh/sshd_config # Set "PermitRootLogin no"
Project Deployment
Use virtualenv to isolate the project environment:
sudo easy_install virtualenv
virtualenv --prompt="<myenv>" ./env
Run the provided build_env.sh
script to set up dependencies. Define MySQL database and user credentials, then sync models with the database:
mysql -uroot -p<root-password>
CREATE DATABASE myproject CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE USER 'myproject'@'localhost' IDENTIFIED BY '<password>';
GRANT ALL PRIVILEGES ON myproject.* TO 'myproject'@'localhost';
python manage.py syncdb
python manage.py collectstatic
Configuring Nginx
Add the following configuration for your site at /etc/nginx/sites-available/myproject.conf
and create a symbolic link in /etc/nginx/sites-enabled/
:
upstream myproject.ru {
server localhost:12345 fail_timeout=0;
}
server {
listen 80;
server_name myproject.ru www.myproject.ru;
root /home/myuser/web/myproject/static_content;
location / {
proxy_pass http://myproject.ru;
}
location /static/ {
alias /home/myuser/web/myproject/static_content/static;
}
location /media/ {
alias /home/myuser/web/myproject/static_content/media;
}
}
Restart Nginx:
sudo service nginx restart
Configuring Gunicorn and Supervisor
Gunicorn handles dynamic HTTP requests, while Supervisor manages its lifecycle. Add the following Supervisor config:
[program:myproject]
command=/home/myuser/web/myproject/env/bin/python /home/myuser/web/myproject/src/myproject/manage.py run_gunicorn --bind=localhost:12345 --workers=3
directory=/home/myuser/web/myproject/src/myproject
user=myuser
autostart=true
autorestart=true
Reload Supervisor to apply changes:
sudo supervisorctl reload
sudo supervisorctl status
Conclusion
This deployment method offers:
- Full control over the server with VPS.
- Separation of concerns between Nginx and Gunicorn.
- Efficient handling of static files using Nginx.
- Easy environment isolation with virtualenv.
Feel free to adapt and improve the setup to your needs. Constructive feedback is welcome!
Useful Links
Tags: django
, Ubuntu 10.04
, nginx
, gunicorn
, firstvds
Comments ()