…does nerdy things.

Setting up Ubuntu 10.04 with Apache, memcached, ufw, MySQL, and Django 1.2 on Linode

Filed under: Work — Tags: , , , , , , — Bryan on May 24th, 2010 @ 3:40 am

Call me a sucker, but I love a good server setup as much as the next guy, I just have a little trouble setting it up sometimes. So I thought I’d walk through my process for setting up all this Django goodness on what is basically a LAMP setup (where “P” stands for Python!) with a few extras like memcached and ufw. We’ll get to a level of general security, but not prefect security.

Also, we’ll keep this well within the 360 megabytes allotted for the cheapest Linode. Before we get underway, just create a new Linode with Ubuntu 10.04 (32-bit), set your password. Alright, let’s get going!

Initial Setup
First thing to do is log in via the standard SSH on your Linode’s IP, port 22, and with root as your username. We’ll change the login user away from root, but for now, this will do (plus we can skip all that sudo stuff). First, let’s update and upgrade the system.

apt-get update && apt-get upgrade

Awesome, you should be 100% up-to-date. Now its time to get to the fun part, let’s install some of the software we’ll be using! Below are the commands to install Apache, MySQL, mod_wsgi and the python MySQL bindings, as well as memcached and ufw. If you have any prompts for passwords, you know what to do! Just remember what you set them as.

apt-get install build-essentials
apt-get install apache2 apache2.2-common apache2-mpm-worker apache2-threaded-dev libapache2-mod-wsgi python-dev python-setuptools
apt-get install mysql-server python-mysqldb
apt-get install memcached libmemcache-dev
apt-get install ufw

Really quickly, let’s get python-memcached installed (alternatively, if you need some raw speed, look up cmemcached or python-libmemcached). This will take a few steps…

# create and enter a temp dir in /home
cd /home && mkdir downloads && cd downloads
# get django 1.2 tar and untar it
wget -O pymem.tar.gz ftp://ftp.tummy.com/pub/python-memcached/python-memcached-1.47.tar.gz && tar -zxvf pymem.tar.gz
# enter the directory and install
cd python-memcached-1.47 && python setup.py install

Now its time for Django! Django 1.1.1 is a lot easier to install than Django 1.2.4:

# install django 1.1.1
apt-get install python-django

But let’s say we need Django 1.2.4: its gonna take a few more commands to make this happen. Watch out for that last command, anytime you use rm -r you can run into real trouble if you mistype (but we’re not production yet so no worries, right?).

# enter the downloads directory in /home
cd /home/downloads
# get django 1.2 tar and untar it
wget -O django124.tar.gz http://www.djangoproject.com/download/1.2.4/tarball/ && tar -zxvf django124.tar.gz
# enter the directory and install django 1.2
cd Django-1.2.4 && python setup.py install
# strictly optional delete of downloads directory, be careful with rm -r
cd /home && rm -r downloads

Actual Configuration
Let’s work backwards, we’ll start with the easy stuff and work our way to the more complicated things. Let’s get ufw and the SSH port out of the way first. Go ahead and pick a number between 1024-8000ish for the port we will eventually; I chose 5555 but you can should use something else.

# turn on ufw
ufw enable
# log all activity (you'll be glad you have this later)
ufw logging on
# allow port 80 for tcp (web stuff)
ufw allow 80/tcp
# allow our ssh port
ufw allow 5555
# deny everything else
ufw default deny
# open the ssh config file and edit the port number from 22 to 5555, ctrl-x to exit
nano /etc/ssh/sshd_config
# restart ssh (don't forget to ssh with port 5555, not 22 from now on)
/etc/init.d/ssh reload

Now that you have ufw and SSH locked down, its time to move onto setting up memcached (which is super easy). We’ll just run it as root and be done with it (you will need to repeat this command on each boot):

# replace 24 with however many megabytes of cache is appropriate
memcached -u root -d -m 24 -l 127.0.0.1 -p 11211

Alright, with that out of the way, let’s get MySQL nice and tight. The standard install of MySQL can suck up a lot of memory, so we’ll suggest a few ways to lighten the load:

# open mysql conf and set these settings:
#    key_buffer = 16k
#    max_allowed_packet = 1M
#    thread_stack = 64K
nano /etc/mysql/my.cnf
# restart mysql
/etc/init.d/mysql restart

Now let’s get a new user setup and leave behind this root nonsense for safety’s sake. Your username is going to be bobby for this example. Replace bobby everywhere if you want something different.

# create bobby, you'll be asked to set the password and such
adduser bobby
# edit the ssh file and add the line: AllowUsers bobby
# ctrl-x to exit and save
nano /etc/ssh/sshd_config
# restart ssh
/etc/init.d/ssh reload
# log out and login as bobby from now on!

It’s time for the nitty gritty stuff: setting up Apache and mod_wsgi with Django for the domain you own called examplesite.com (creative, I know). We need to make a public_html folder in bobby’s home folder and place a folder called examplesite.com (as well as a few more). We’ll do that first.

cd /home/bobby/
mkdir public_html
mkdir public_html/examplesite.com
mkdir public_html/examplesite.com/logs
mkdir public_html/examplesite.com/private

Right now you should place your Django project into the public_html/examplesite.com folder. For example, if the project is housed in demoproject (eg: demoproject/manage.py, demoproject/urls.py, etc.) you’ll want it placed ALA public_html/examplesite.com/demoproject. Time to get the Apache config files up and running. Here we go!

cd /home/bobby/public_html/examplesite.com/demoproject/
mkdir apache
nano apache/demoproject.wsgi

First, in the demoproject.wsgi file you should paste and save:

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/bobby/public_html/examplesite.com/demoproject')
 
os.environ['DJANGO_SETTINGS_MODULE'] = 'demoproject.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

We’re so close, let’s get the other Apache files setup. Oh, and don’t worry about that www-data thing just yet, we’ll get to that in a second.

# give the www-data user/group permission on public_html
sudo chown -R www-data:www-data /home/bobby/public_html
sudo nano /etc/apache2/sites-available/examplesite.com

Place the text below in the examplesite.com config file (remember the www-data part from the last command?). You can modify the threads and processes numbers to suit your moods and load.

    #Basic setup
    ServerAdmin your@email.com
    ServerName www.examplesite.com
    ServerAlias examplesite.com
 
        Order deny,allow
        Allow from all
 
    LogLevel warn
    ErrorLog  /home/bobby/public_html/examplesite.com/logs/apache_error.log
    CustomLog /home/bobby/public_html/examplesite.com/logs/apache_access.log combined
 
    WSGIDaemonProcess examplesite.com user=www-data group=www-data threads=20 processes=2
    WSGIProcessGroup examplesite.com
 
    WSGIScriptAlias / /home/bobby/public_html/examplesite.com/demoproject/apache/demoproject.wsgi

A few more final things:

sudo a2ensite examplesite.com
sudo /etc/init.d/apache2 restart

Time to admire your handiwork.

Congrats! You’re all set up and ready to roll! Nothing can stop you now! Here’s a neat command to measure your memory usage as mine rarely gets over 160mb. This gives lots of room for growth as you can always increase the memcached size, MySQL settings, and Apache/mod_wsgi instances/threads.

# measure your memory usage in kb
ps aux | awk '{print $3"\t"$6"\t"$11;sum+=$6;cpu+=$3} END {print "Total RSS", sum, "\nTotal CPU", cpu}'

Also, under Ubuntu 10.04 (Lucid), Python’s site-packages is now called dist-packages. Just a FYI.

16 Comments »
  1. Nice. I tried using this guide to set it up on a VM, but once finished, and when I ping the VM through http://192.168.1.2, I get the “It works” default page for Apache, but if I add the name of my project after the URL, I don’t find it. I had it take the form of projectname, without the ‘.com’. And instead of starting the daemon for xyz.com, I had it started for localhost. What would the path then be for my project?

    Comment by bunny — June 5, 2010 @ 12:27 pm
  2. Nicely put together article. I used most of it for an EC2 EBS instance (no ufw). Thanks!

    Comment by Luke K. — June 25, 2010 @ 5:24 pm
  3. I suppose you’ve got to check your apache2.conf directives, also the vitualhost’s ones (sites-available, sites-enabled) could help …

    Comment by kOoLiNuS — July 9, 2010 @ 2:26 pm
  4. Just a trivial and minor reminder. Followed the steps, I ran into a minor issue since I don’t have python-setuptools in my env:
    root@ubuntu-vm01:/home/downloads/python-memcached-1.45# python setup.py install
    Traceback (most recent call last):
    File “setup.py”, line 3, in
    from setuptools import setup
    ImportError: No module named setuptools

    Fixed it by install python-setuptools.
    apt-get install python-setuptools

    Comment by Dennis — July 27, 2010 @ 1:10 pm
  5. Is it: apt-get install build-essentials or build-essential?

    The singular form worked for me, and the plural was not found.

    Comment by Andrew Cronk — August 6, 2010 @ 8:46 am
  6. You are my hero.

    Comment by Kevin — October 19, 2010 @ 11:44 am
  7. Very helpful, i got a server and this is what i needed to do :)

    Comment by Heinrich — October 22, 2010 @ 12:21 am
  8. is it possible to configure ufw before enabling it? i just locket myself out of my server, d*mn

    Comment by jan — November 8, 2010 @ 12:35 am
  9. Hi Bryan

    Great article/tutorial! I bookmarked it for future reference.

    However I did notice something that only just made sense after reading the UFW documentation and it seems one that’s easy to miss but I think important to make clear.

    Deny rules go first!

    Your example seems fine since ufw does set deny as the default (I have seen varying opinions posted though. Maybe older versions?)

    The link to the docs-
    https://help.ubuntu.com/community/UFW?action=show&redirect=Uncomplicated_Firewall_ufw

    I don’t mean to criticize, but it seems like a good habit when using ufw (and iptables?) is to set all deny rules first. Your example might lead some to set their deny rules after allowing which might not do the job…

    Again, great job! I’m using your advice for the mysql settings and am happy with the results.

    Thanks!

    Comment by sdebaun — November 17, 2010 @ 3:00 am
  10. HI,

    Your guide has been very helpful. However, I’m encountering the same problem as bunny. I get the ‘It Works’ page generated by apache, but do you know why it is not giving me the django default page? Thanks for your help!

    Comment by peter — December 4, 2010 @ 7:25 pm
  11. Great starter article, thanks! The ufw stuff was especially useful for me – first time building my own server.

    Comment by axolotl — March 5, 2011 @ 12:17 am
  12. Thanks for the great tutorial Bryan!

    For all those getting the Apache “It Works” page, but not seeing Django default page: this happened to me too. I fixed it by editing /etc/apache2/httpd.conf and adding the following line:

    WSGIScriptAlias / /home/bobby/public_html/examplesite.com/demoproject/apache/demoproject.wsgi

    …followed by an apache restart. Seems to work fine now!

    Comment by Dan Delany — April 16, 2011 @ 6:27 pm
  13. You have a typo…

    “apt-get install build-essentials”

    should be

    “apt-get install build-essential”

    Comment by Mike Curry — May 25, 2011 @ 9:52 am
  14. “Syntax error on line 4 of /etc/apache2/sites-enabled/examplesite.com:
    ServerAlias only used in ”

    Ideas?

    Comment by lemiant — August 27, 2011 @ 1:47 am
  15. deny rules go first before allow rules (ufw,iptables, etc. )

    Comment by s — November 4, 2011 @ 1:30 am
  16. Nice tutorial…. thanks !!!

    Comment by junkiest — November 16, 2011 @ 7:23 am
Leave a comment

All articles are licensed under a Attribution-Noncommercial-Share Alike 3.0 Unported License. All files/themes are released under the GPL License where applicable. © 2012 Bryan Helmig Hosted on Webfaction.