Installing Django on Ubuntu Intrepid: Django, Nginx, Apache, mod_wsgi, cmemcache
A complete start to finish guide.
This guide will cover the complete setup of an Ubuntu Intrepid server as well as the software below:
- Uncomplicated Firewall (UFW)
- Nginx serving only static content
- Apache with mod_wsgi serving only dynamic content
- Memcached and the cmemcache library
- Subversion
- Django
Please note, this guide was written for Ubuntu Intrepid, but will likely work on other versions of Ubuntu barring any software version differences.
Install Summary
- SSH Setup
- Configure firewall
- Update system and set locale
- Install Build Essentials
- Configure DNS
- Nginx
- Apache
- Install Subversion
- Install Django
- Install Memcached
- Create layout for domains
- Grant Apache Write Permissions
- Install source code
- Create Nginx virtual host
- Create Apache virtual host
Log in (for Windows users)
- Download and install PuTTY
- Configure and connect
- Click 'yes' when prompted with security warning
Log in (for Linux users)
$ ssh root@<slice ip>
Setup SSH and add new user
Replace sylink with better shell
$ ln -sf /bin/bash /bin/sh
Change root password
$ passwd
Add a new admin user
$ adduser <username>
Grant new user sudo privileges
$ visudo
Add this to end of file and save
$ <username> ALL=(ALL) ALL
Linux users and SSH key
Create folder to hold keys (on local workstation)
(local)$ mkdir ~/.ssh
Create SSH keys (on local workstation)
(local)$ ssh-keygen -t rsa
Copy public key onto slice (on local workstation)
(local)$ scp ~/.ssh/id_rsa.pub <username>@<slice ip>:/home/<username>/
Create directory in <username>/home folder to hold public key (on slice)
$ mkdir /home/<username>/.ssh $ mv /home/<username>/id_rsa.pub /home/<username>/.ssh/authorized_keys
Set permissions on key (on slice)
$ chown -R <username>:<username> /home/<username>/.ssh $ chmod 700 /home/<username>/.ssh $ chmod 600 /home/<username>/.ssh/authorized_keys
Disable root login
Switch to new user
$ su <username>
Verify use has sudo before disabling. Should print 'root'
$ sudo whoami
Change default SSH config to be more secure
$ sudo nano /etc/ssh/sshd_config
Port 30000 <--- change to a port of your choosing Protocol 2 PermitRootLogin no PasswordAuthentication no <--- yes if windows X11Forwarding no UsePAM no UseDNS no AllowUsers <username>
Reload SSH config
$ sudo /etc/init.d/sshd reload
Configure firewall
Install firewall
$ sudo aptitude install ufw
Turn on firewall
$ sudo ufw enable
Enable/disable logging
$ sudo ufw logging on
Enable port 80 for TCP only
$ sudo ufw allow 80/tcp
Enable SSH port you chose before
$ sudo ufw allow <SSH port>
Lock down system
$ sudo ufw default deny
Update system and set locale
Update
$ sudo aptitude update
Set locale. This setting is for the US. If you live in another country you will need to use another setting.
$ sudo locale-gen en_US.UTF-8 $ sudo /usr/sbin/update-locale LANG=en_US.UTF-8
Safe upgrade
$ sudo aptitude safe-upgrade
Full upgrade
$ sudo aptitude full-upgrade
Install Build Essentials
$ sudo aptitude install build-essential
Configure DNS
Creating DNS records on SliceHost
If you aren't hosted on SliceHost the process for creating your DNS records will be different.
Install Nginx
Install Nginx
$ sudo aptitude install nginx
Start Nginx server
$ sudo /etc/init.d/nginx start
Test Nginx is running by opening your favorite browser and navigating to http://<slice ip>. Should display "Welcome to nginx!"
Configure Nginx
Disable default site
$ sudo rm /etc/nginx/sites-enabled/default
Modify config file
$ sudo nano /etc/nginx/nginx.conf
worker_processes 4; <--- set equal to the number of cores on your server tcp_nopush on; keepalive_timeout 2; gzip on; gzip_comp_level 2; gzip_proxied any; gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;
Shutdown Nginx
$ sudo /etc/init.d/nginx stopCreate proxy.conf file
$ sudo nano /etc/nginx/proxy.conf
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_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k;
Install Apache
Ignore the error after install
$ sudo aptitude install apache2 apache2.2-common apache2-mpm-worker apache2-threaded-dev libapache2-mod-wsgi python-dev
Configure Apache
Modify config file
$ sudo nano /etc/apache2/apache2.conf
Timeout 90 KeepAlive Off ServerName <server name>
Restart Apache
$ sudo apache2ctl graceful
Test Apache is running by opening your favorite browser and navigating to http://<slice ip>. Should display "It works!"
Disable default site
$ sudo a2dissite 000-default
Change listening port and virtual host to 8080
$ sudo nano /etc/apache2/ports.conf
Change security settings
$ sudo nano /etc/apache2/conf.d/security
Restart Apache, ignore the error
$ sudo apache2ctl graceful
Start Nginx
$ sudo /etc/init.d/nginx start
Install Subversion
$ sudo aptitude install subversion
Install Django
Change directory
$ cd /usr/lib/python2.5/site-packages
Checkout code from Django SVN
$ sudo svn co http://code.djangoproject.com/svn/django/tags/releases/1.0.2/django django
Create symlink
$ sudo ln -s /usr/lib/python2.5/site-packages/django/django/bin/django-admin.py /usr/local/bin/django-admin.py
Install Memcached
Install Memcached and dependencies
$ sudo aptitude install memcached $ sudo aptitude install libmemcache-dev
Download cmemcached
$ cd /usr/local/src/ $ sudo wget http://gijsbert.org/downloads/cmemcache/cmemcache-0.95.tar.bz2
Install cmemcache
$ sudo tar xjvf cmemcache-0.95.tar.bz2 $ cd cmemcache-0.95 $ sudo python setup.py install
Edit test.py
$ sudo nano test.py
# get stats
#stats = mc.get_stats()
#self.failUnlessEqual(len(stats), 1)
#self.assert_(self.servers[0] in stats[0][0])
#self.assert_('total_items' in stats[0][1])
#self.assert_('bytes_read' in stats[0][1])
#self.assert_('bytes_written' in stats[0][1])
Start Memcached. Be sure to set memory size
$ memcached -d -m <memory size> -l 127.0.0.1 -p 11211
Run test.py
$ python test.py
Create layout for domains
Create parent directory layout
$ mkdir /home/<username>/public_html
Create sub-folders for domain
$ mkdir -p /home/<username>/public_html/<domain name> $ mkdir -p /home/<username>/public_html/<domain name>/private $ mkdir -p /home/<username>/public_html/<domain name>/logs
Grant Apache write permissions
Add main user to Apache group
$ sudo usermod -a -G www-data <username>
Make sure public_html folder is owned by <username> and is in the www-data group
$ sudo chgrp -R www-data /home/<username>/public_html
Make sure any new files put into public_html will inherit permissions
$ sudo chmod -R 2750 /home/<username>/public_html
Grant Apache write permissions to private folder (if needed)
$ sudo chmod -R 2770 /home/<username>/public_html/<domain name>/private
Install source code
Change directory and install your source code in this directory
$ cd /home/<username>/public_html/<domain name>
Create .wsgi file
$ mkdir /home/<username>/public_html/<domain name>/<django project name>/apache $ cd /home/<username>/public_html/<domain name>/<django project name>/apache $ nano <django project name>.wsgi
import os, sys
apache_configuration= os.path.dirname(__file__)
project = os.path.dirname(apache_configuration)
workspace = os.path.dirname(project)
sys.path.append(workspace)
sys.path.append('/usr/lib/python2.5/site-packages/django/')
sys.path.append('/home/<username>/public_html/<domain name>/<django project name>')
os.environ['DJANGO_SETTINGS_MODULE'] = '<django project name>.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
Create symlink for admin media
$ sudo ln -s /usr/lib/python2.5/site-packages/django/contrib/admin/media /home/<username>/public_html/<domain name>/<django project name>/media/admin
Modify settings.py file of your project
$ sudo nano settings.py
ADMIN_MEDIA_PREFIX = '/media/admin/'
.
.
.
MIDDLEWARE_CLASSES = (
'django.middleware.http.SetRemoteAddrFromForwardedFor',
)
Create Nginx virtual host
Create new virtual host file
$ sudo nano /etc/nginx/sites-available/<domain name>
upstream backend {
server 127.0.0.1:8080;
}
server {
listen 80;
server_name www.<domain name> <domain name>;
access_log /home/<username>/public_html/<domain name>/logs/nginx_access.log;
error_log /home/<username>/public_html/<domain name>/logs/nginx_error.log;
location / {
proxy_pass http://backend;
include /etc/nginx/proxy.conf;
}
location /media/ {
root /home/<username>/public_html/<domain name>/<django project name>/;
}
}
Create symlink to enable new domain
$ sudo ln -s /etc/nginx/sites-available/<domain name> /etc/nginx/sites-enabled/<domain name>
Restart Nginx
$ sudo /etc/init.d/nginx stop $ sudo /etc/init.d/nginx start
Create Apache virtual host
Create new virtual host file
$ sudo nano /etc/apache2/sites-available/<domain name>
<VirtualHost *:8080>
#Basic setup
ServerAdmin <admin email>
ServerName www.<domain name>
ServerAlias <domain name>
<Directory /home/<username>/public_html/<domain name>/<django project name>/apache/>
Order deny,allow
Allow from all
</Directory>
LogLevel warn
ErrorLog /home/<username>/public_html/<domain name>/logs/apache_error.log
CustomLog /home/<username>/public_html/<domain name>/logs/apache_access.log combined
WSGIDaemonProcess <domain name> user=www-data group=www-data threads=25
WSGIProcessGroup <domain name>
WSGIScriptAlias / /home/<username>/public_html/<domain name>/<django project name>/apache/<django project name>.wsgi
</VirtualHost>
Enable new site
$ sudo a2ensite <domain name> $ sudo /etc/init.d/apache2 reload
Your new server should now be up and running. If you'd like more information on the above directions please consult the sources below:
- http://www.punteney.com/writes/setting-django-slicehost-ubuntu-hardy-postgres-apa/
- http://thisweekindjango.com/screencasts/episode/21/django-ground-episode-13/
- http://wiki.slicehost.com/doku.php?id=dream_geodjango_server/
- http://www.technobabble.dk/2008/aug/25/django-mod-wsgi-perfect-match/
- http://blog.dscpl.com.au/search/label/mod_wsgi/
- http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango/
- http://articles.slicehost.com/2007/9/18/apache-virtual-hosts-permissions/
- http://articles.slicehost.com/2008/5/16/ubuntu-hardy-nginx-virtual-hosts/
- http://articles.slicehost.com/2008/5/15/ubuntu-hardy-nginx-configuration/
- http://articles.slicehost.com/2007/12/13/ubuntu-gutsy-nginx-configuration-1/
- http://articles.slicehost.com/2007/12/17/ubuntu-gutsy-nginx-virtual-hosts-2/
- http://articles.slicehost.com/2008/12/11/ubuntu-intrepid-apache-configuration-1/
- http://articles.slicehost.com/2008/12/11/ubuntu-intrepid-apache-configuration-2/
- http://articles.slicehost.com/2008/12/17/ubuntu-intrepid-apache-virtual-hosts-1/
- http://articles.slicehost.com/2008/12/17/ubuntu-intrepid-apache-virtual-hosts-2/
- http://articles.slicehost.com/2008/11/28/ubuntu-intrepid-setup-page-1/
- http://articles.slicehost.com/2008/11/28/ubuntu-intrepid-setup-page-2/
- http://articles.slicehost.com/2007/9/13/multiple-hosts-layout
- http://www.davidcramer.net/code/django/108/setup-mod_wsgi-for-django-and-shared-hosting.html
blog comments powered by Disqus