Card store project #2: Installing Satchmo, Django, PostgreSQL, and Apache on Ubuntu at Slicehost
As I mentioned in my previous post, I'm planning to set up an e-commerce site using the Satchmo shopping cart framework. Satchmo is built on the Django web framework which is written in the Python programming language. Satchmo has a lot of features built in which means it saves you a lot of work implementing them yourself. Check out this video introduction to Satchmo at this year's DjangoCon for more information.
After reading this discussion on the Satchmo mailing list, I decided to use Slicehost for hosting my site. Their cheapest plan provides 256MB of RAM for $20/month. Here are my notes on setting up Satchmo and Django with PostgreSQL, Apache, and mod_python on Ubuntu Intrepid at Slicehost. It seems lighttpd and nginx are popular lightweight alternatives to Apache on VPS setups. I do not know too much about this, but may explore these in the future.
Note, I don't describe how to setup a Satchmo project below. Maybe I will write another post about that later... For more information, see the Satchmo Installation documentation. Update 2008-12-12: I did write another blog post-- see Installing Satchmo, part 2.
Setup Slicehost
- Sign up for an account at http://www.slicehost.com/ I chose Ubuntu Intrepid for my operating system and named my slice "toad".
- I followed the following two excellent Slicehost tutorials: Ubuntu Setup Part 1 and Part 2.
- An important step is setting the system locale. Since I'm in the United States,
I used the following commands (run as root):
locale-gen en_US.UTF-8 update-locale LANG=en_US.UTF-8
Install apache, mod_python, postgresql, and postgres python bindings
- Run as root (or use sudo):
apt-get update apt-get upgrade apt-get dist-upgrade apt-get install apache2 apache2-mpm-prefork apt-get install libapache2-mod-python apt-get install postgresql apt-get install python-psycopg2
Configure apache
- I used the following Slicehost tutorials: Install Apache, Configure Apache Part 1, Configure Apache Part 2
- Of particular note, when installing apache, I got this warning:
apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
Fix it by setting the ServerName in/etc/apache2/apache2.conf:ServerName yourdomain.com ServerTokens Prod
See the Apache docs for more information on ServerName.
Install Django 1.0.2
- Run the following as root:
cd /srv wget http://www.djangoproject.com/download/1.0.2/tarball/ tar zxvf Django-1.0.2-final.tar.gz mkdir python-packages cd python-packages ln -s ../Django-1.0.2-final/django
Test Django (optional)
- Run the following as root:
export PYTHONPATH=/srv/python-packages /srv/Django-1.0.2-final/django/bin/django-admin.py startproject testdjango
- Edit
/etc/apache2/httpd.conf:<location "/"> SetHandler python-program PythonHandler django.core.handlers.modpython SetEnv DJANGO_SETTINGS_MODULE testdjango.settings PythonPath "['/srv', '/srv/python-packages'] + sys.path" PythonDebug On </location> - Restart apache:
/etc/init.d/apache2 restart
Navigate to your slice's IP address in your browser and you should see the Django "It worked!" page.
Install Satchmo
Satchmo requires a number of external Python packages besides Django. Unfortunately, there isn't one standard way of installing Python packages. I decided to install most of them using Ubuntu's APT package management and one of them using easy_install, and one of them from source. Alternatively, I could have installed most of the packages with easy_install, and one of them with APT (and one of them from source). Or, I could have done it another way... sigh.
Note, I use the directory /srv/python-packages to
store symbolic links to my needed python packages. Then I add this
directory to my Python Path in the PYTHONPATH environment variable or in
the Apache httpd.conf file. See my post,
Somewhere on your Python path for more information.
- Install Satchmo prerequisites. Run the following commands as root:
Install APT packages:apt-get update apt-get upgrade apt-get install python-crypto apt-get install python-yaml apt-get install python-imaging apt-get install python-reportlab apt-get install python-trml2pdf
Install django-registration using easy_install:apt-get install python-setuptools python-dev build-essential easy_install django-registration
Install comment_utils source:apt-get install subversion mkdir -p /srv/python-packages/dist cd /srv/python-packages/dist svn co http://django-comment-utils.googlecode.com/svn/trunk/comment_utils/ mv comment_utils comment_utils_rev92 cd /srv/python-packages ln -s dist/comment_utils_rev92 comment_utils
- Install Satchmo 0.8. Run the following as root: Update 2008-12-12:
I changed this to use release 0.8 instead of the SVN trunk version.
cd /srv wget http://www.satchmoproject.com/snapshots/satchmo-0.8.tgz tar zxvf satchmo-0.8.tgz cd /srv/python-packages ln -s ../satchmo-0.8/satchmo
To install the SVN trunk version instead,cd /srv svn co svn://satchmoproject.com/satchmo/trunk mv trunk satchmo_revXXXX cd /srv/python-packages ln -s ../satchmo_revXXXX/satchmo
Setup PostgreSQL¶
I followed the instructions at Punteney.com for setting up Django and Postgres on Slicehost.
- If you didn't already install Postgres above, run the following as root:
apt-get install postgresql apt-get install python-psycopg2
- Change the password for the "postgres" Unix user. (run as root or use sudo)
passwd -d postgres su postgres -c passwd
- Change password for "postgres" user in the database.
(From Punteney's article, "It's convenient
to have the two passwords match, but not required.")
su postgres -c psql template1
ALTER USER postgres WITH PASSWORD 'postgres_user_password'; template1=\q
- Create django user:
su postgres createuser -P django_user
Punteney says to answer no to all here. Remember the password to put in Django settings.py file. (For this example, I set the password tomy_password.) - Create a database. Still
su'ed as the "postgres" user:psql template1
CREATE DATABASE django_db OWNER django_user ENCODING 'UTF8'; \q
exit
(exit from postgres su) - Configure access to the database. Edit
/etc/postgresql/8.3/main/pg_hba.conf:local all postgres ident sameuser local django_db django_user md5
- Restart the postgres server:
/etc/init.d/postgresql-8.3 restart
- In your Django project, use the following database settings in
settings.py:DATABASE_ENGINE = 'postgresql_psycopg2' DATABASE_NAME = 'django_db' DATABASE_USER = 'django_user' DATABASE_PASSWORD = 'my_password' DATABASE_HOST = '' DATABASE_PORT = ''
- Run
syncdb:cd /srv/yourproject python manage.py syncdb
Setup a domain name
- Register for a domain name. Google for "domain registration" for options.
- Follow the Slicehost directions for creating DNS records. This includes setting the nameservers at your domain registration service to use Slicehost's nameservers (ns1.slicehost.net, ns2.slicehost.net, ns3.slicehost.net).
6
Comments
—
Comments feed for this post
#2 Eliot commented on 2008-12-12:
Andrew, is mod_wsgi the preferred way to go? I used mod_python because it was recommended by the Django docs and I had used it in the past. I haven't looked into mod_wsgi but will check it out later.
#3 Andrew commented on 2008-12-12:
I'm no expert on the subject, but there is a page on the mod_wsgi wiki about integration with django. I don't see any reason not to at least check it out, it is in the Ibex repos. Django also has a page on the setup. I've also recently been benchmarking nginx's mod_wsgi (pre-beta code, not ready for production) and it looks quite promising. I have yet to do a comparison with Apache's mod_wsgi (or mod_python), but it is more than twice as fast as paster's internal server (I'm using pylons)
Paster ::
$ ab -n 1000 -c 50 localhost:5000/blog/
Server Software: PasteWSGIServer/0.5
Server Hostname: localhost
Server Port: 5000
Document Path: /blog/
Document Length: 454 bytes
Concurrency Level: 50
Time taken for tests: 52.590574 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 656000 bytes
HTML transferred: 454000 bytes
Requests per second: 19.01 [#/sec] (mean)
Time per request: 2629.529 [ms] (mean)
Time per request: 52.591 [ms] (mean, across all concurrent requests)
Transfer rate: 12.17 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 144 918.7 0 9000
Processing: 186 2427 548.2 2638 3318
Waiting: 173 2381 544.2 2591 3228
Total: 199 2571 992.0 2662 11141
Longest request: 11141 ms
Nginx (2 processes) ::
$ ab -n 1000 -c 50 localhost:5500/blog/
Server Software: nginx/0.7.26
Server Hostname: localhost
Server Port: 5500
Document Path: /blog/
Document Length: 454 bytes
Concurrency Level: 50
Time taken for tests: 17.595767 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 655000 bytes
HTML transferred: 454000 bytes
Requests per second: 56.83 [#/sec] (mean)
Time per request: 879.788 [ms] (mean)
Time per request: 17.596 [ms] (mean, across all concurrent requests)
Transfer rate: 36.32 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 1.9 0 11
Processing: 213 860 858.5 727 6392
Waiting: 212 860 858.4 726 6391
Total: 221 861 860.0 727 6400
Longest request: 6400 ms
#5 Nikolay Kolev commented on 2008-12-18:
I've read that WSGI is the recommended approach and even though not officially yet, Phusion Passenger supports it. I'm not sure how it compares to mod_wsgi though, but it's been working great for Ruby frameworks (in production on many high-volume sites) and I've heard nothing but praises about it.
#6 Eliot commented on 2008-12-18:
I may have to start considering alternatives to Apache/mod_python... Even after moving my media files to S3, my site is still slow. I'm not sure if it is Slicehost or if I just need memcached. I briefly looked into nginx and it looks pretty good. I see from their wiki that they have quickly surpassed lighttpd in domains hosted.
Post a comment
About
I'm Eliot and this is my notepad for programming topics such as Python, Django, Ubuntu, Emacs, etc... more »
Search Blog
Tags
-
algorithms
(6)
-
android
(2)
-
aws
(10)
-
blogproject
(20)
-
c_cplusplus
(12)
-
cardstore
(8)
-
colinux
(2)
-
concurrency
(13)
-
conkeror
(2)
-
core
(2)
-
cygwin
(17)
-
datastructures
(15)
-
datetime
(4)
-
decorators
(4)
-
django
(41)
-
emacs
(22)
-
files_directories
(12)
-
git
(6)
-
hardware
(6)
-
install_setup
(8)
-
javascript
(3)
-
keyboard
(9)
-
matplotlib
(6)
-
mercurial
(4)
-
nginx
(2)
-
persistence
(6)
-
preferences
(7)
-
processes
(4)
-
pyqt
(18)
-
python
(157)
-
ratpoison
(3)
-
regexes
(6)
-
rsync
(3)
-
softwaretools
(17)
-
sql
(14)
-
ssh
(12)
-
subversion
(6)
-
twisted
(7)
-
ubuntu
(66)
-
urxvt
(5)
-
vxworks
(25)
-
webdev
(8)
-
wmii
(7)
Blogroll
- Adam Gomaa
- Alex Clemesha
- Amir Salihefendic
- Armin Ronacher
- David Beazley
- David Ziegler
- Duncan McGreggor
- Gareth Rushgrave
- Glyph Lefkowitz
- Guido van Rossum
- Ian Bicking
- Jacob Kaplan-Moss
- James Bennett
- James Tauber
- Jesper Noehr
- Marty Alchin
- Matt Harrison
- Nikolay Kolev
- Parand Darugar
- Peter Baumgartner
- Peter Bengtsson
- Rob Hudson
- Simon Willison
- Will McGugan
#1 Andrew commented on 2008-12-12:
Is there any reason you chose mod_python over mod_wsgi?