Skip to content

Instantly share code, notes, and snippets.

@WillSams
Forked from epicserve/ubuntu-server-django-guide.rst
Last active September 9, 2021 22:12
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save WillSams/5382802 to your computer and use it in GitHub Desktop.
Save WillSams/5382802 to your computer and use it in GitHub Desktop.

Ubuntu Server Setup Guide for Django Websites

This guide is a walk-through on how to setup Ubuntu Server for hosting Django websites. The Django stack that will be used in this guide is Ubuntu, Nginx, Gunicorn and Postgres. I needed an example site for this guide you can use Django Base Site which is available on Github. For more useful information on Ubuntu server installs, please see the documentation here: https://help.ubuntu.com/12.10/serverguide/

This walk-through goes over configuring a VM in VirtualBox using a bridged network connection so that we can access the Internet. This walk-through doesn't fully go over hardening your server, but please read this fine tutorial to get a fairly good understanding of what you need to do to secure your web servers: http://www.thefanclub.co.za/how-to/how-secure-ubuntu-1204-lts-server-part-1-basics.

Note: Before you begin, in Virtual Box just set up a bridged adapter on the first interface, eth0. There are security concerns in this configuration but we aren't going to run the webserver for long periods of time.

Step 1: Install Ubuntu Server

The version of Ubuntu I'm using for this guide is Ubuntu 12.10 64 bit Server. I've installed Ubuntu Server in a VirtualBox VM. During the installation of Ubuntu Server I answered the prompts with the following:

Language: English
Install Menu: Install Ubuntu Server
Select a language: English
Select your location: United States
Configure the Keyboard: No
Configure the keyboard: English (US)
Configure the keyboard: English (US)
Configure the network (if you have multiple virtual NICs): eth1
Hostname: webapps1
Set up users and passwords: William Sams
Set up users and passwords: (Enter a username)
Set up users and passwords: ********
Set up users and passwords: *******
Set up users and passwords: No
Configure the clock: Yes
Partition disks: Guided - use entire disk and set up LVM
Partition disks: SCSI1 (0,0,0) (sda) - 22.5 GB ATA VBOX HARDDISK
Partition disks: Yes
Partition disks: Continue
Partition disks: Yes
Configure the package manager: <blank>
Configure taskse1: No automatic updates
Software selection: OpenSSH server, PostgreSQL database
Install the GRUB boot loader on a hard disk: Yes
Installation complete: <Continue>

Step 2: Setup Basic Server Security -----------------------------First, let's setup a static IP for our server. We will need to open up the interfaces configuration in a text editor. The text editor I will be using throughout this walk-through is VIM, but any command line based editor (i.e., Nano) would be fine:

$ sudo vi /etc/network/interfaces

Modify your entries to match your network configuration:

iface eth1 inet static
address 192.168.1.145
netmask 255.255.255.0
gateway 192.168.1.254

And then to make all of your changes stick:

$ sudo apt-get remove isc-dhcp-client && sudo stop networking && sudo start networking

Next, we want to enable Ubuntu's Uncomplicated Firewall (UFW) and allow HTTP on port 8080 and SSH on port 2222. We will be using alternate ports instead of the well-known 80 for HTTP and 22 for SSH:

$ sudo ufw enable
$ sudo ufw allow 8080/tcp && sudo ufw deny 80
$ sudo ufw allow 2222/tcp && sudo ufw deny 22

Double-check your changes:

$ sudo ufw status

To ensure SSH works on a different port other than the standard port 22 we will need to modify ssh configuration:

$ sudo vi /etc/ssh/sshd_config

Once Vim opens, modify these settings necessary modifications:

Port 2222
Protocol 2

Now restart ssh (alternatively, you can do sudo stop ssh && sudo start ssh):

$ sudo stop ssh && sudo start ssh

Edit your hosts file to add the web server:::

$ sudo vi /etc/hosts

Once Vim opens, add this to the contentss:

192.168.1.145     webapps1

Now that we have an alternate port set up for SSH, you should now be able to open up your Terminal on the host machine and connect to your Ubuntu Server using the following:

$ ssh webapps1 -p 2222

We will finish the rest of our steps in the Terminal from your host machine and not on the server.

Step 3: Install Software

Python Header Files

The Python header files are needed in order to compile binding libraries like psycopg2. :

$ sudo aptitude install python2.7-dev

Nginx

$ sudo aptitude install nginx

Git

$ sudo aptitude install git

PostgreSQL

Install Postgres:

$ sudo aptitude install postgresql-server-dev-9.1

We installed PostgreSQL during our initial setup of the server. Make your Ubuntu user a PostgreSQL superuser:

$ sudo su postgres
$ createuser --superuser <your username>
$ exit

Restart PostgreSQL:

$ sudo /etc/init.d/postgresql restart

Step 4: Setup a Generic Deploy User

The reason we are setting up a generic deploy user is so that if you have multiple developers who are allowed to do deployments you can easily add the developer's SSH public key to the deploy user's /home/deploy/.ssh/authorized_keys file in order to allow them to do deployments.

$ sudo useradd -d /home/deploy -m -s /bin/bash deploy

Step 5: Install an Example Site

Setup a virtualenv:

$ sudo apt-get install python-setuptools
$ sudo easy_install pip
$ sudo pip install virtualenv
$ cd /usr/local/
$ sudo mkdir virtualenvs
$ sudo chown deploy:deploy virtualenvs
$ sudo su deploy
$ cd virtualenvs
$ virtualenv --no-site-packages example-site
$ exit

Note

I personally use and setup virtualenvwrapper on all my servers and local development machines so that I can use workon <virtualenv> to easily activate a virtualenv. This is why I put all my virtualenvs in /usr/local/virtualenvs.

Make a location for the example site:

$ cd /srv/
$ sudo mkdir sites
$ sudo chown deploy:deploy sites
$ sudo su deploy
$ cd sites
$ sudo mkdir example-site/
$ cd example-site/
$ echo `pwd` > /usr/local/virtualenvs/example-site/lib/python2.7/site-packages/django_project_root.pth
$ mkdir -p static/cache
$ exit
$ sudo chown www-data:www-data /srv/sites/example-site/static/cache
$ sudo su deploy

Install the sites required python packages:

$ source /usr/local/virtualenvs/example-site/bin/activate
$ cd /srv/sites/example-site/

Install Django:

$ pip install django

Install Gunicorn:

$ pip install gunicorn

Install psycopg2:

$ pip install psycopg2

Create a PostgreSQL user and database for your example-site:

# exit out of the deploy user account
$ exit
$ createuser webuser -P
$ Enter password for new role: [enter the same password you used in the local.py file from above]
$ Enter it again: [enter the password again]
$ Shall the new role be a superuser? (y/n) n
$ Shall the new role be allowed to create databases? (y/n) y
$ Shall the new role be allowed to create more new roles? (y/n) n
$ createdb northwind -O webuser

Create the file /srv/sites/example-site/config/settings/local.py and add the following.:

from base import *

LOCAL_SETTINGS_LOADED = True

DEBUG = True

INTERNAL_IPS = ('127.0.0.1', )

ADMINS = (
    ('Your Name', 'username@example.com'),
)

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'example_site',
        'USER': 'example_site',
        'PASSWORD': '<enter a new secure password>',
        'HOST': 'localhost',
    }
}

Create the site:

$ django-admin.py startproject example-site

Step 6: Daemonize Gunicorn using Ubuntu's Upstart

Create your Upstart configuration file:

$ sudo vi /etc/init/gunicorn_example-site.conf

Add the following and save the file:

description "upstart configuration for gunicorn example-site"

start on net-device-up
stop on shutdown

respawn

exec /usr/local/virtualenvs/example-site/bin/gunicorn_django -u www-data -c /srv/sites/example-site/config/gunicorn/example-site.py /srv/sites/example-site/config/settings/__init__.py

Start the gunicorn site:

$ sudo start gunicorn_example-site

Step 7: Setup Nginx to proxy to your new example site

Create a new file sudo vi /etc/nginx/sites-available/example-site.conf and add the following to the contents of the file:

server {

    listen       80;
    server_name  localhost;
    access_log   /var/log/nginx/example-site.access.log;
    error_log    /var/log/nginx/example-site.error.log;

    location = /biconcave {
        return  404;
    }

    location  /static/ {
        root  /srv/sites/example-site/;
    }

    location  /media/ {
        root  /srv/sites/example-site/;
    }


    location  / {
        proxy_pass            http://127.0.0.1:8001/;
        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;
    }

}

Enable the new site:

$ cd /etc/nginx/sites-enabled
$ sudo rm default
$ sudo ln -s ../sites-available/example-site.conf

Start nginx:

$ sudo /etc/init.d/nginx start

Step 8: Test the new example site

While still connected to your Ubuntu server via SSH run the following, which should spit out the HTML for your site:

wget -qO- 127.0.0.1:80

Since you setup port forwarding in step 2 for web, you should also be able to open up your browser on your local host machine and pull up the website using the URL, http://127.0.0.1:8080.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment