08:30
WordPress to Django+PostgreSQL, Part 4: Configuring Apache, Django, PostgreSQL
19 October 2009
In the previous installment of this series (in which we’re migrating this blog from WordPress to Django and PostgreSQL), we installed Apache, Python 2.6, psycopg
and mod_wsgi
on the server.
A note about the pace: I’m taking this very slowly, spelling out each and every setp. I realize that those of you with more Centos experience (which is probably pretty much everyone) or Django experience are probably tapping your feet and thinking, “Come on, get a move on here!” To those, I beg your indulgence. When reading about a topic I am unfamiliar with, I appreciate a high level of detail, so I don’t hit a weird error message only to be told, “Oh, right, you have to install an old version of x. I skipped that step.”
Installing Django
We have choices here: We can install Django directly from the current Subversion repository, or from an official release. We also have the choice of installing Django as local to a particular user, or global for the whole system. For this install, we’ll do an official release (1.1.1 is current), and install it for the whole system.
[xof@blog ~]$ cd builds
[xof@blog builds]$ wget http://www.djangoproject.com/download/1.1.1/tarball/
[xof@blog builds]$ tar xvfz Django-1.1.1.tar.gz
[xof@blog builds]$ cd Django-1.1.1
[xof@blog Django-1.1.1]$ sudo python2.6 setup.py install
[xof@blog Django-1.1.1]$ python2.6
Python 2.6.3 (r263:75183, Oct 17 2009, 18:29:55)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>>
Where is the project going to live?
Before we configure Apache and mod_wsgi
to serve up our new Django project, we should decide where the project is going to live. I like to keep my builds and maintenance account separate from the user that contains the actual stuff being served up by the web server… so let’s create a new user just to hold the project:
[xof@blog ~]$ sudo /usr/sbin/adduser thebuild
[xof@blog ~]$ sudo passwd thebuild
[xof@blog ~]$ sudo /usr/sbin/usermod -a -G apache thebuild
Note: Depending on the permissions your installation sets on /home
directories by default, you may need to adjust them so that mod_wsgi
can get at the files it needs.
Set up the Django project
Logging in as the project user, first, we’ll make sure that we get the right Python installation by adding an alias to our .bash_profile
:
alias python='/usr/bin/python2.6'
Just checking!
[thebuild@blog ~]$ which python
alias python='/usr/bin/python2.6'
/usr/bin/python2.6
And we can now create the project:
[thebuild@blog ~]$ cd thebuild.com
[thebuild@blog thebuild.com]$ python /opt/python2.6/lib/python2.6/site-packages/django/bin/django-admin.py startproject thebuild
We also need to create a directory for any Python eggs that our application might download (this is, by the way, a “feature” of Python that I really do not care for).
[thebuild@blog thebuild.com]$ mkdir .python-eggs
[thebuild@blog thebuild.com]$ chmod 770 .python-eggs
Now, we need to create a .wsgi file. The .wsgi file is the glue that connects the mod_wsgi
module in Apache to our particular application. The Django project itself doesn’t (and shouldn’t) live under the webroot of the web server, but the .wsgi file does:
[thebuild@blog thebuild.com]$ cd ~/thebuild.com
[thebuild@blog ~]$ mkdir apache
[thebuild@blog ~]$ cd apache
[thebuild@blog apache]$ cat >>django.wsgi
#!/opt/python2.6/bin/python
import os, sys
sys.path.append('/home/thebuild/thebuild.com')
os.environ['DJANGO_SETTINGS_MODULE'] = 'thebuild.settings'
os.environ['PYTHON_EGG_CACHE'] = '/home/thebuild/thebuild.com/.python-eggs'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
[thebuild@blog apache]$
Next, let’s create the media and admin-media directories, and move the admin media over from the source distribution:
[thebuild@blog apache]$ mkdir admin-media
[thebuild@blog apache]$ mkdir media
[thebuild@blog apache]$ cd admin-media
[thebuild@blog admin-media]$ cp -R /opt/python2.6/lib/python2.6/site-packages/django/contrib/admin/media/* .
Creating a User in PostgreSQL for the Blog
Right now, the only user in the PostgreSQL cluster is the default superuser; that’s not a great choice for the user that Django will use to connect to the database.
It’s also not idea to allow the Django user to create objects in the public
schema, but it needs to be able to create objects in some schema if we’re going to use the cool Django model mechanism for table and field creation.
First, let’s create a database for the site:
[postgres@blog ~]$ createdb thebuild
[postgres@blog ~]$ psql thebuild
psql (8.4.1)
Type "help" for help.
thebuild=# CREATE USER django ENCRYPTED PASSWORD 'password';
CREATE ROLE
Then, let’s create a schema just to hold objects related to the site:
thebuild=# CREATE SCHEMA thebuild AUTHORIZATION django;
CREATE SCHEMA
And set an appropriate search path:
thebuild=# ALTER ROLE django SET search_path TO thebuild, public;
ALTER ROLE
… and revoke CREATE on the public schema from the user:
thebuild=# REVOKE CREATE ON SCHEMA public FROM django;
REVOKE
This means that, by default, anything that the django
user creates will go into the schema thebuild
, while it still has access to the schema public
. However, it won’t be able to create new objects in public
.
(Note that we still have rather a barn door open here: We haven’t done anything with pg_hba.conf
to require passwords or other security to log in.)
Django Settings
We’ll need to update the settings.py file to match all of the various changes we made. So far, we’ve changed:
DATABASE_ENGINE = 'postgresql_psycopg2'
DATABASE_NAME = 'thebuild'
DATABASE_USER = 'django'
DATABASE_PASSWORD = 'password'
TIME_ZONE = 'America/Los_Angeles'
MEDIA_ROOT = '/home/thebuild/thebuild.com/apache/media/'
MEDIA_URL = 'http://new.thebuild.com/media/'
ADMIN_MEDIA_PREFIX = '/admin-media/'
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
)
Note that we’ve turned on the admin site by adding django.contrib.admin
to installed apps. Now, we can do a syncdb
to create the databases the installed apps require:
thebuild@blog thebuild]$ python manage.py syncdb
Creating table django_admin_log
Creating table auth_permission
Creating table auth_group
Creating table auth_user
Creating table auth_message
Creating table django_content_type
Creating table django_session
Creating table django_site
You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Username (Leave blank to use 'thebuild'): admin
E-mail address: xof@thebuild.com
Password:
Password (again):
Superuser created successfully.
Installing index for admin.LogEntry model
Installing index for auth.Permission model
Installing index for auth.Message model
[thebuild@blog thebuild]$
Configure Apache
Apache can be tweaked endlessly, of course, but we’re going to do the minimum required to get the server up and ticking. Assuming we’ve done the basics (ServerName, etc.), we add the module info for mod_wsgi
:
LoadModule wsgi_module modules/mod_wsgi.so
AddHandler wsgi-script .wsgi
Now, we need to point to the .wsgi file we created above. Moving over to /etc/httpd/conf.d
, we can create a file thebuild.conf
to contain the virtual host:
<IfModule mod_alias.c>
Alias /media /home/thebuild/thebuild.com/apache/media
Alias /admin-media /home/thebuild/thebuild.com/apache/admin-media
</IfModule>
<IfModule mod_wsgi.c>
WSGIScriptAlias / /home/thebuild/thebuild.com/apache/django.wsgi
WSGIDaemonProcess thebuild processes=5 threads=6 display-name=%{GROUP}
WSGIProcessGroup thebuild
WSGIApplicationGroup %{GLOBAL}
WSGISocketPrefix run/wsgi
</IfModule>
… restart Apache …
[xof@blog conf]$ sudo /etc/init.d/httpd graceful
… and did it work?
Exciting! Now, time to start actually designing our blog application.
There are no comments yet.