This tutorial will show you how to serve a Django application by using PostgreSQL, Gunicorn, and NGinx on an Ubuntu server. I created this tutorial because when I started configuring my server, I had a lot of trouble finding anything useful when it came to serving Django apps built in Python 3. I found that virtually all the tutorials I could find still insisted on using Python 2. So, this will show you how to turn your Python 3 Django app into a fully fledged website. This tutorial uses the following software with the corresponding versions:
The only thing that I am going to assume is that you already have an up-to-date Ubutnu 14.04 server running. The rest of the tutorial will take you through each and every step.
NGinx (pronounced Engine-X), is a lightweight web server. We will be using it to serve our static files and to proxy requests to Gunicorn. To install NGinx, issue the following command:
sudo apt-get install nginx
PostgreSQL is an open source database system that we will setup Django to use. To install PostgreSQL, we first need to install some dependencies that Django requires to work with PostgreSQL.
sudo apt-get install libpq-dev python-dev
Then, install PostgreSQL with the following command, then switch to the Postgres user.
sudo apt-get install postgresql postgresql-contrib sudo su - postgres
Then create a new database:
createdb mydb
Additionally, you should create a new user also:
createuser -P [username]
Lastly, grant the new user access to the database:
psql GRANT ALL PRIVILEGES ON DATABASE mydb TO username; \q logout
A Python virtual environment allows you to run different versions of Python on the same server. It also has the benefit of allowing you to separate the dependencies of different apps, because they are completely different Python installations. Change directories to the directory you want your virtual environment to be. I’ve found that the recommended place to put your virtual environments is in /opt/env/
, where env/
contains one or many python virtual environments.
cd /opt/env
Starting in Python 3.3, a tool named venv, or pyvenv, has been being shipped with Python 3 installations. However, Python 3.4 shipped with a broken version of pyvenv which leads to some errors when it tries installing things. To counter this, we can install the virtual environment with the following commands, replacing the string “myvenv” with your chosen virtual environment folder name:
pyvenv-3.4 --without-pip myvenv source ./myvenv/bin/activate wget https://pypi.python.org/packages/source/s/setuptools/setuptools-3.4.4.tar.gz tar -vzxf setuptools-3.4.4.tar.gz cd setuptools-3.4.4 python setup.py install cd .. wget https://pypi.python.org/packages/source/p/pip/pip-1.5.6.tar.gz tar -vzxf pip-1.5.6.tar.gz cd pip-1.5.6 python setup.py install cd ..
In order to use the virtual environment, you need to activate it using the command source ./myvenv/bin/activate
. When activated, all python commands will execute through this virtual environment. To deactivate the virtual environment, run deactivate
.
Be careful using sudo
when executing Python scripts meant to be run in your virtual environment. When you execute a python script with sudo
, your virtual environment will not be active in the scope that the script is run in. So it may actually be better to issue a su
command first, activate the virtual environment, and then run the Python command. Or better yet, set the permissions to your directories correctly so root access isn’t needed.
First, make sure your virtual environment is activated. If it is not, run source ./myvenv/bin/activate
. Then, install Django with:
pip install django
After Django successfully installs, install Gunicorn, the Python web server.
pip install gunicorn
Lastly, install the python connector for PostgreSQL.
pip install psycopg2
If your application has any other dependencies, you may as well take a minute now to install them.
If you would like to import an existing Django project, you should do so here. However, if not, then create a new project. The location of your project is entirely up to you. From what I’ve found, it’s recommended to put your django project in /opt/env/myvenv/mysite
, where mysite
is your Django project. However, I like to put my projects in /var/www/project_name/mysite
. Anyways, first make sure the virtual environment is activated:
source ./myvenv/bin/activate
Then, create the new Django project:
django-admin.py startproject mysite
Edit settings.py to contain the following database settings:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'mydb', 'USER': 'username', 'PASSWORD': 'password', 'HOST': 'localhost', 'PORT': '' } }
Now, sync the database by navigating to the same directory as your manage.py file, and running:
python manage.py syncdb
Create a gunicorn_config.py file; I like to place this at:/opt/env/myvenv/gunicorn_config.py
. Add the following:
command = '/opt/env/myvenv/bin/gunicorn' pythonpath = '/opt/env/myvenv/mysite' bind = '127.0.0.1:8001' workers = 3
Save the file and run the following command to start Gunicorn with the above settings:
/opt/env/myvenv/bin/gunicorn -c /opt/env/myvenv/gunicorn_config.py mysite.wsgi
If NGinx is not already running, start it with:
sudo service nginx start
Then, in your settings.py file, set your STATIC_ROOT
to the path that you want to host static files at. For me, this would be /var/www/project_name/static
. Now, we are going to configure the site in Nginx. Create a new file /etc/nginx/sites-available/project_name
and edit it to contain the following:
server { server_name yourdomainorip.com; access_log off; location /static/ { alias /var/www/project_name/static/; } location / { proxy_pass http://127.0.0.1:8001; proxy_set_header X-Forwarded-Host $server_name; proxy_set_header X-Real-IP $remote_addr; add_header P3P 'CP="ALL DSP COR PSAa PSDa OUR NOR ONL UNI COM NAV"'; } }
This does two things:
Now, we need to create a symbolic link to the above file:
cd /etc/nginx/sites-enabled sudo ln -s ../sites-available/project_name
You may also want to remove the default configuration in this directory. Restart NGinx with sudo service nginx restart
The site should now work, so long as your Gunicorn server is running.
We obviously don’t want to have to manually start the Gunicorn server all the time, so we’re going to automate it using supervisor. First, install supervisor:
sudo apt-get install supervisor
Let’s create a start script for gunicorn at /opt/env/myvenv/gunicorn_start
:
#!/bin/bash #activate the virtual environment source /opt/env/myvenv/bin/activate #launch gunicorn /opt/env/myvenv/bin/gunicorn -c /opt/env/myvenv/gunicorn_config.py mysite.wsgi
After gunicorn_start is saved, make it executable using your preferred method. To get it working, you can run chmod +x gunicorn_start
, but you should consider more strict permissions for production servers.
Then, create a new file at /etc/supervisor/conf.d/mysite.conf
with the following contents:
[program:mysite] command=/opt/env/myvenv/gunicorn_start autostart=true autorestart=true
Gunicorn should now start automatically, and your Django website should be live!
If you have any suggestions or problems with this tutorial, please let me know by using some form of contact method which can be found on my home page.