<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>david.copithorne.com &#187; nginx</title>
	<atom:link href="http://david.copithorne.com/category/nginx/feed/" rel="self" type="application/rss+xml" />
	<link>http://david.copithorne.com</link>
	<description></description>
	<lastBuildDate>Fri, 14 Aug 2009 01:29:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Ubuntu 8.04 Server LTS &#8211; Django + Nginx + Apache/mod_wsgi</title>
		<link>http://david.copithorne.com/2009/08/14/ubuntu-8-04-server-lts-django-nginx-apachemod_wsgi/</link>
		<comments>http://david.copithorne.com/2009/08/14/ubuntu-8-04-server-lts-django-nginx-apachemod_wsgi/#comments</comments>
		<pubDate>Fri, 14 Aug 2009 01:29:29 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[postgres]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://david.copithorne.com/?p=28</guid>
		<description><![CDATA[Based on:

Will Larson&#8217;s Django and Ubuntu Intrepid Almanac excellent post. Probably worth looking at that first!
Ubuntu Server Guide
Ubuntu Hardy + Nginx
Rich Leland&#8217;s &#8216;pip and virtualenv&#8217; post

Assumptions

Logged in as root locally.
Network interface has been configured.

Steps

Update your apt-get sources
apt-get upgrade

Add some accounts (using bob as my own account):
useradd django
mkdir /home/django
chown django:django /home/django
useradd bob
mdkir /home/bob
chown bob:bob /home/bob
passwd bob

Change [...]]]></description>
			<content:encoded><![CDATA[<p>Based on:</p>
<ul>
<li><a href="http://lethain.com/entry/2009/feb/13/the-django-and-ubuntu-intrepid-almanac/">Will Larson&#8217;s Django and Ubuntu Intrepid Almanac</a> excellent post. Probably worth looking at that first!</li>
<li><a href="https://help.ubuntu.com/8.04/serverguide/C/index.html">Ubuntu Server Guide</a></li>
<li><a href="http://www.mensk.com/webmaster-toolbox/perfect-ubuntu-hardy-nginx-mysql5-php5-wordpress/">Ubuntu Hardy + Nginx</a></li>
<li><a href="http://mathematism.com/2009/jul/30/presentation-pip-and-virtualenv/">Rich Leland&#8217;s &#8216;pip and virtualenv&#8217; post</a></li>
</ul>
<h3>Assumptions</h3>
<ol>
<li>Logged in as root locally.</li>
<li>Network interface has been configured.</li>
</ol>
<h3>Steps</h3>
<ol>
<li>Update your apt-get sources<br />
<blockquote><p>apt-get upgrade</p></blockquote>
</li>
<li>Add some accounts (using <code>bob</code> as my own account):<br />
<blockquote><p>useradd django<br />
mkdir /home/django<br />
chown django:django /home/django<br />
useradd bob<br />
mdkir /home/bob<br />
chown bob:bob /home/bob<br />
passwd bob</p></blockquote>
</li>
<li>Change the default shell:<br />
<blockquote><p>chsh root -s /bin/bash<br />
chsh bob -s /bin/bash<br />
chsh django -s /bin/bash</p></blockquote>
</li>
<li>
<blockquote><p>passwd bob<br />
passwd django</p></blockquote>
</li>
<li>Add root permission to <code>bob</code> by adding the account to the admin group.<br />
<blockquote><p>usermod -a -Gadmin bob</p></blockquote>
</li>
<li>Try logging in as <code>bob</code>:<br />
<blockquote><p>su bob</p></blockquote>
</li>
<li>If OpenSSH is not installed then visit this <a href="https://help.ubuntu.com/8.04/serverguide/C/openssh-server.html">page about setting it up.</a><br />
<blockquote><p>sudo apt-get install openssh-server<br />
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.original<br />
sudo chmod a-w /etc/ssh/sshd_config.original</p></blockquote>
<p>Check if ssh is running:</p>
<blockquote><p>ps -ef | grep sshd</p></blockquote>
<p>If not try:</p>
<blockquote><p>/etc/init.d/ssh start</p></blockquote>
<p>If you&#8217;re getting a &#8216;Connection refused&#8217; message, check that the <code>/etc/hosts</code> file is set correctly particularly if you <a href="http://www.ubuntugeek.com/change-ubuntu-system-from-dhcp-to-a-static-ip-address.html">changed to a static address</a> by changing <code>/etc/network/interfaces</code>. If there is nothing wrong there double check any firewall settings.</li>
<li>We&#8217;ll be restricting ssh to <code>bob</code> only, so create a special <code>sshers</code> group:<br />
<blockquote><p>sudo groupadd sshers<br />
sudo usermod -a -Gsshers bob</p></blockquote>
</li>
<li>Time to configure <code>ssh</code>:<br />
Make these changes to <code>/etc/ssh/sshd_config</code></p>
<blockquote><p>#Port 22<br />
Port <code>XXXX</code> (pick a <a href="http://www.iana.org/assignments/port-numbers">port number</a>)</p>
<p>#PermitRootLogin yes<br />
PermitRootLogin no</p>
<p>#X11 Forwarding yes<br />
X11 Forwarding no</p></blockquote>
<p>Add these if not found</p>
<blockquote><p>MaxAuthTries 6<br />
UseDNS no<br />
AllowGroups sshers</p></blockquote>
<p>And restart the <code>ssh</code> service:</p>
<blockquote><p>sudo /etc/init.d/ssh restart</p></blockquote>
<p>Check that you can login:</p>
<blockquote><p>ssh bob@xxx.xxx.xxx.xxx -p XXXX</p></blockquote>
<p>If it works you can disable the root password:</p>
<blockquote><p>sudo passwd -l root</p></blockquote>
</li>
<li>Next install Postgres (might need to install gcc and make as well):<br />
<blockquote><p>sudo apt-get install postgresql-8.3 postgresql-server-dev-8.3</p></blockquote>
<p>Change the password for the <code>postgres</code>user:</p>
<blockquote><p>sudo -u postgres psql template1</p></blockquote>
<p>You&#8217;ll get the <code>psql</code> prompt and then just type:</p>
<blockquote>
<ul>
<li>ALTER USER postgres WITH PASSWORD &#8216;<code>somePassword</code>&#8216;;</li>
<li>\q</li>
</ul>
</blockquote>
</li>
<li>The config file for Postgres also needs to be modified:<br />
<blockquote><p>sudo vi /etc/postgresql/8.3/main/pg_hba.conf</p></blockquote>
<p>The end of the file should changed to look like:</p>
<blockquote><p># Database administrative login by UNIX sockets<br />
local   all         postgres                      ident sameuser<br />
# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD<br />
# &#8220;local&#8221; is for Unix domain socket connections only<br />
local   all         all                            <strong>password</strong><br />
# IPv4 local connections:<br />
<strong>#</strong>host    all         all         127.0.0.1/32          md5<br />
# IPv6 local connections:<br />
<strong>#</strong>host    all         all         ::1/128               md5</p></blockquote>
<p>Next, just restart Postgres:</p>
<blockquote><p>sudo /etc/init.d/postgresql-8.3 restart</p></blockquote>
</li>
<li>Nginx will serve static content and proxy requests to Apache2. We&#8217;ll need to install the latest stable version.<br />
<blockquote><p><code>sudo aptitude -y install libpcre3 libpcre3-dev libpcrecpp0 libssl-dev zlib1g-dev<br />
mkdir ~/sources<br />
cd ~/sources/<br />
wget http://sysoev.ru/nginx/nginx-0.7.61.tar.gz<br />
tar -zxvf nginx-0.7.61.tar.gz<br />
cd nginx-0.7.61<br />
./configure --sbin-path=/usr/local/sbin --with-http_ssl_module<br />
make<br />
sudo make install</code></p></blockquote>
<p>Start Nginx</p>
<blockquote><p>sudo /usr/local/sbin/nginx</p></blockquote>
<p>Try viewing it on a browser.<br />
Stop it and create an init script</p>
<blockquote><p>sudo kill `cat /usr/local/nginx/logs/nginx.pid`<br />
sudo vi /etc/init.d/nginx</p></blockquote>
<blockquote><p><code>#! /bin/sh</p>
<p>### BEGIN INIT INFO<br />
# Provides:          nginx<br />
# Required-Start:    $all<br />
# Required-Stop:     $all<br />
# Default-Start:     2 3 4 5<br />
# Default-Stop:      0 1 6<br />
# Short-Description: starts the nginx web server<br />
# Description:       starts nginx using start-stop-daemon<br />
### END INIT INFO</p>
<p>PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin</p>
<p>DAEMON=/usr/local/sbin/nginx<br />
NAME=nginx<br />
DESC=nginx</p>
<p>test -x $DAEMON || exit 0</p>
<p># Include nginx defaults if available<br />
if [ -f /etc/default/nginx ] ; then<br />
        . /etc/default/nginx<br />
fi</p>
<p>set -e</p>
<p>case "$1" in<br />
  start)<br />
        echo -n "Starting $DESC: "<br />
        start-stop-daemon --start --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \<br />
                --exec $DAEMON -- $DAEMON_OPTS<br />
        echo "$NAME."<br />
        ;;<br />
  stop)<br />
        echo -n "Stopping $DESC: "<br />
        start-stop-daemon --stop --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \<br />
                --exec $DAEMON<br />
        echo "$NAME."<br />
        ;;</p>
<p>  restart|force-reload)<br />
        echo -n "Restarting $DESC: "<br />
        start-stop-daemon --stop --quiet --pidfile \<br />
                /usr/local/nginx/logs/$NAME.pid --exec $DAEMON<br />
        sleep 1<br />
        start-stop-daemon --start --quiet --pidfile \<br />
                /usr/local/nginx/logs/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS<br />
        echo "$NAME."<br />
        ;;<br />
  reload)<br />
      echo -n "Reloading $DESC configuration: "<br />
      start-stop-daemon --stop --signal HUP --quiet --pidfile /usr/local/nginx/logs/$NAME.pid \<br />
          --exec $DAEMON<br />
      echo "$NAME."<br />
      ;;<br />
  *)<br />
        N=/etc/init.d/$NAME<br />
        echo "Usage: $N {start|stop|restart|reload|force-reload}" >&#038;2<br />
        exit 1<br />
        ;;<br />
esac</p>
<p>exit 0<br />
</code></p></blockquote>
<blockquote><p>sudo chmod +x /etc/init.d/nginx</p></blockquote>
<p>Add it to the default run levels:</p>
<blockquote><p>sudo /usr/sbin/update-rc.d -f nginx defaults</p></blockquote>
<p>Create folder layout:</p>
<blockquote><p>sudo mkdir /usr/local/nginx/sites-available<br />
sudo mkdir /usr/local/nginx/sites-enabled</p></blockquote>
<p>Change the nginx.conf file:</p>
<blockquote><p>sudo vi /usr/local/nginx/conf/nginx.conf</p></blockquote>
<p>to:</p>
<blockquote><p><code>user www-data www-data;<br />
worker_processes  4;</p>
<p>events {<br />
    worker_connections  1024;<br />
}</p>
<p>http {<br />
    include       mime.types;<br />
    default_type  application/octet-stream;</p>
<p>    sendfile        on;<br />
    tcp_nopush      on;<br />
    tcp_nodelay     off;<br />
    keepalive_timeout  5;</p>
<p>    gzip  on;<br />
    gzip_comp_level 2;<br />
    gzip_proxied any;<br />
    gzip_types      text/plain text/html text/css application/x-javascript text/xml application/xml<br />
    application/xml+rss text/javascript;</p>
<p>    include /usr/local/nginx/sites-enabled/*;<br />
}<br />
</code></p></blockquote>
<p>Next add a <code>proxy.conf</code> file:</p>
<blockquote><p>sudo vi /usr/local/nginx/conf/proxy.conf</p></blockquote>
<blockquote><p><code># proxy.conf<br />
proxy_redirect          off;<br />
proxy_set_header        Host            $host;<br />
proxy_set_header        X-Real-IP       $remote_addr;<br />
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;<br />
client_max_body_size    10m;<br />
client_body_buffer_size 128k;<br />
proxy_connect_timeout   90;<br />
proxy_send_timeout      90;<br />
proxy_read_timeout      90;<br />
proxy_buffers           32 4k;<br />
</code></p></blockquote>
<p>And start Ngninx:</p>
<blockquote><p>sudo /etc/init.d/nginx start</p></blockquote>
<li>Get files for Apache2:<br />
<blockquote><p>sudo apt-get install apache2 libapache2-mod-wsgi</p></blockquote>
<p>Modify <code>ports.conf</code></p>
<blockquote><p>sudo vi /etc/apache2/ports.conf</p></blockquote>
<p>with</p>
<blockquote><p>NameVirtualHost 127.0.0.1:80<br />
Listen 127.0.0.1:80
</p></blockquote>
<p>Need to modify <code>apache2.conf</code></p>
<blockquote><p>sudo vi /etc/apache2/apache2.conf
</p></blockquote>
<p>Change <code>KeepAlive</code> to:</p>
<blockquote><p># KeepAlive On<br />
KeepAlive Off
</p></blockquote>
<p>Then restart:</p>
<blockquote><p>sudo apache2ctl restart
</p></blockquote>
</li>
<li>Create a virtual host file for your site with nginx:<br />
<blockquote><p>sudo vi /usr/local/nginx/sites-available/example.com
</p></blockquote>
<p>and add the following where 255.255.255.255:80 should be replaced with the correct IP:</p>
<blockquote><p><code>server {<br />
    listen   255.255.255.255:80;<br />
    server_name  www.example.com;<br />
    rewrite ^/(.*) http://example.com/$1 permanent;<br />
}<br />
server {<br />
    listen   255.255.255.255:80;<br />
    server_name www.example.com example.com;</p>
<p>    access_log /home/django/domains/example.com/log/access.log;<br />
    error_log /home/django/domains/example.com/log/error.log;</p>
<p>    location / {<br />
        proxy_pass    http://127.0.0.1:80/;<br />
        include       /usr/local/nginx/conf/proxy.conf;<br />
    }</p>
<p>    location /media/ {<br />
            root   /home/django/domains/example.com/public/;<br />
            expires 1d;<br />
    }<br />
}<br />
</code></p></blockquote>
<blockquote><p>sudo ln -s /usr/local/nginx/sites-available/example.com /usr/local/nginx/sites-enabled/example.com</p></blockquote>
</li>
<li>Add some <code>django</code> folders:<br />
<blockquote><p>
sudo usermod -a -G www-data django<br />
sudo usermod -a -G www-data bob<br />
su django<br />
mkdir domains<br />
chgrp -R www-data /home/django/domains<br />
chmod -R 2750 /home/django/domains<br />
mkdir .python-eggs<br />
chown django:www-data .python-eggs<br />
chmod g+w .python-eggs/<br />
cd /home/django/domains<br />
mkdir example.com<br />
mkdir -p example.com/{public,log}<br />
mkdir example.com/public/media<br />
chown -R django:www-data example.com<br />
exit<br />
sudo rm /etc/apache2/sites-enabled/000-default<br />
sudo rm /usr/local/nginx/sites-enabled/default<br />
sudo /etc/init.d/nginx stop<br />
sudo /etc/init.d/nginx start<br />
sudo apache2ctl graceful</p>
</blockquote>
</li>
<li>Install some general libraries<br />
<blockquote><p>sudo apt-get install mercurial git-core curl<br />
sudo apt-get install build-essential python-dev python-setuptools python-psycopg2</p>
<p>sudo easy_install pip<br />
sudo pip install virtualenv<br />
sudo pip install virtualenvwrapper<br />
su django<br />
cd<br />
mkdir virtualenv<br />
chgrp -R www-data virtualenv<br />
vi .bashrc<br />
&#8220;export WORKON_HOME=$HOME/virtualenv<br />
source /usr/bin/virtualenvwrapper_bashrc&#8221;<br />
source .bashrc<br />
cd<br />
virtualenv &#8211;no-site-packages &#8211;unzip-setuptools envName
</p></blockquote>
</li>
<p>Create a <code>pip</code> installation file e.g. &#8216;<code>envName_env.txt</code>&#8216;:</p>
<blockquote><p><code>#Django<br />
Django>=1.1</p>
<p>#PIL<br />
http://effbot.org/downloads/Imaging-1.1.6.tar.gz</p>
<p># egenix-mx-base<br />
# Caused an error with pip: "--single-version-externally-managed"<br />
#http://downloads.egenix.com/python/egenix-mx-base-3.1.2.tar.gz</p>
<p># psycopg2<br />
http://initd.org/pub/software/psycopg/psycopg2-2.0.12.tar.gz</p>
<p></code></p></blockquote>
<p>pip -E envName install -r envName_env.txt<br />
./envName/bin/easy_install egenix-mx-base</p>
</li>
<li>Create a Django project (virtualenvwrapper might be useful here):<br />
<blockquote><p>/home/django/virtualenv/envName/bin/python /home/django/virtualenv/envName/bin/django-admin.py startproject myProject</p></blockquote>
</li>
<li>Link admin/media with public/media/admin and change settings.py<br />
<blockquote><p> ln -s /home/django/virtualenv/envName/lib/python2.5/site-packages/django/contrib/admin/media /home/django/domains/example.com/public/media/admin
</p></blockquote>
<p>Then update the ADMIN_MEDIA_PREFIX setting in your myProject/settings.py file :</p>
<blockquote><p>vi /home/django/domains/example.com/myProject/settings.py</p></blockquote>
<p>It should look like:</p>
<blockquote><p>#ADMIN_MEDIA_PREFIX = &#8216;/media/&#8217;<br />
ADMIN_MEDIA_PREFIX = &#8216;/media/admin/&#8217;
</p></blockquote>
</li>
<li>Create a database:<br />
<blockquote><p>sudo su postgres<br />
createuser -P pg_substanceis<br />
# should not be a superuser<br />
# should not be able to create databases<br />
# should not be able to create more new roles<br />
createdb &#8211;encoding=UNICODE db_example -O pg_example<br />
exit
</p></blockquote>
<blockquote><p>vi /home/django/domains/example.com/myProject/settings.py</p></blockquote>
<p>and add in the details:</p>
<blockquote><p>DATABASE_ENGINE = &#8216;postgresql_psycopg2&#8242;<br />
DATABASE_NAME = &#8216;db_example&#8217;<br />
DATABASE_USER = &#8216;pg_example&#8217;<br />
DATABASE_PASSWORD = &#8216;123456789&#8242;<br />
DATABASE_HOST = &#8221;<br />
DATABASE_PORT = &#8221;
</p></blockquote>
<p>Then just sync the database to check these settings:</p>
<blockquote><p>~/domains/virtualenv/envName/bin/python myProject/manage.py syncdb
</p></blockquote>
</li>
<li>Create a wsgi file for the project:<br />
<blockquote><p>sudo vi /home/django/domains/example.com/myProject/myProject.wsgi</p></blockquote>
<p>And add the following:</p>
<blockquote><p><code>ALLDIRS = ['/home/django/virtualenv/envName/lib/python2.5/site-packages']<br />
# note that the above directory depends on the locale of your virtualenv,<br />
# and will thus be *different for each project!*<br />
import os<br />
import sys<br />
import site</p>
<p>prev_sys_path = list(sys.path)</p>
<p>for directory in ALLDIRS:<br />
    site.addsitedir(directory)</p>
<p>new_sys_path = []<br />
for item in list(sys.path):<br />
    if item not in prev_sys_path:<br />
       new_sys_path.append(item)<br />
       sys.path.remove(item)<br />
sys.path[:0] = new_sys_path</p>
<p># this will also be different for each project!<br />
sys.path.append('/home/django/domains/example.com/myProject/')</p>
<p>os.environ['PYTHON_EGG_CACHE'] = '/home/django/.python-eggs'<br />
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'<br />
import django.core.handlers.wsgi<br />
application = django.core.handlers.wsgi.WSGIHandler()<br />
</code></p></blockquote>
</li>
<li>Create a VirtualHost file for Apache:<br />
<blockquote><p>sudo vi /etc/apache2/sites-available/example.com
</p></blockquote>
<p>Add the VirtualHost definition:</p>
<blockquote><p><code><VirtualHost 127.0.0.1:80><br />
    ServerName www.example.com<br />
    ServerAlias example.com</p>
<p>    <Directory /home/django/domains/example.com/myProject/><br />
        Order deny,allow<br />
        Allow from all<br />
    </Directory></p>
<p>    LogLevel warn<br />
    ErrorLog  /home/django/domains/example.com/log/apache_error.log<br />
    CustomLog /home/django/domains/example.com/log/apache_access.log combined</p>
<p>    WSGIDaemonProcess example.com user=www-data group=www-data threads=25<br />
    WSGIProcessGroup example.com<br />
    WSGIScriptAlias / /home/django/domains/example.com/myProject/myProject.wsgi<br />
</VirtualHost><br />
</code></p></blockquote>
<p>Then just enable it and restart Apache2 &#8211; you should see the Django debug screen:</p>
<blockquote><p>sudo ln -s /etc/apache2/sites-available/example.com /etc/apache2/sites-enabled/example.com<br />
sudo apache2ctl graceful
</p></blockquote>
</li>
<li>Some security: take a look at some <a href="https://help.ubuntu.com/community/StricterDefaults">StricterDefaults</a>. By default /dev/shm is mouted read/write but on servers it should be read only as some exploits may use it. Edit the /etc/fstab file to include the following:<br />
<blockquote><p>sudo vi /etc/fstab</p></blockquote>
<p><code>tmpfs     /dev/shm     tmpfs     defaults,ro     0     0</code></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://david.copithorne.com/2009/08/14/ubuntu-8-04-server-lts-django-nginx-apachemod_wsgi/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
