James Gardner


Good Ingredients, AWS and App Engine

Posted in Python, Web, Debian, EC2, Hosting by thejimmyg on the April 8th, 2008

So, today’s been an interesting day. I finally decided on Sunday against building my future projects with Amazon web services on the basis that I’m more likely to be able to build a faster responding and more tailored solution to each of my needs with other tools. I decided to investigate MogileFS as an alternative to Amazon S3 and at the same time I decided to start work on a new set of Python tools to be named "good ingredients" which would basically be very low level components using a more genericised version of the WSGI spec which also allows services (something I’ve been thinking about recently). I mentioned some of my ideas to some of the Rails community including one of the core comitters but didn’t get a lot of interest. I’m not too suprised becuase I haven’t had a lot of interest from the Pylons community either and the Rails community are far more in favour of abstractions than the Pylons community and abstractions are precicely what good ingredients were not going to be about.

Anyway, the plan was to put together existing tools that provide the sorts of very scalable infrastructure which would otherwise require something like AWS and expose useful a useful low-level web framework stack with the good ingredients.

Then after all this planning Google go an release their App Engine which offers both a scalable infrastructure and a new set of Python modules which seem farily low-level and support WSGI. Still the infrastructure isn’t customisable and the modules don’t use anything akin to the modular WSGI services API I am planning so I think it makes sense for me to carry on with my ideas anyway. Interesting times though.

Migrating a 32bit server to a 64bit server as a Xen image

Posted in Debian, Virtulization, Hosting by thejimmyg on the February 25th, 2008

I’ve got a 32bit intel Mac Mini server running Ubuntu Dapper Drake and I wanted to package it up as a Xen image to run on an AMD 64 server running Debian. Here’s what I did.

First create the Xen image on the 64bit server:

sudo mkdir /var/xen
sudo xen-create-image --debootstrap --dir=/var/xen --size=60Gb --memory=512Mb --fs=ext3 --dist=etch --hostname=vm2 --ip 78.47.146.253 --netmask 255.255.255.248 --initrd=/boot/initrd.img-2.6.18-4-xen-amd64 --kernel=/boot/vmlinuz-2.6.18-4-xen-amd64 --mirror=http://ftp.freenet.de/debian/ --swap=1024Mb

Then mount it:

sudo mkdir /mount/vm2
sudo mount -t ext3 -o loop /var/xen/domains/vm2/disk.img /mount/vm2

Then sync the filesystems:

cd /mount/vm2/
sudo rsync -aHxvzgop  --progress --delete --numeric-ids root@pauli.3aims.com:/ .

Now shutdown the old server because any changes will be lost.

Create a new fstab for the copy on the 64bit server after backing up the old one:

sudo cp -p /mount/vm2/etc/fstab /mount/vm2/etc/fstab.bak

Make the new one like this:

/dev/sda1     /     ext3     errors=remount-ro   0     1
proc          /proc proc     rw,nodev,nosuid,noexec              0     0
/dev/sda2     none  swap     sw                    0     0

Unmount the disk and boot the image:

# You can't unmount a directory you are still in so we move out.
cd ..
sudo umount /mount/vm2
# You might want to skip this, it takes ages.
sudo cp /var/xen/domains/vm2/disk.img /var/xen/domains/vm2/disk.img.bak
sudo xm create -c /etc/xen/vm2.cfg

Check the server is up and can ping and be pinged then change the DNS settings to point all the services to the new server.

You might need the lib64 modules:

sudo mount -t ext3 -o loop /var/xen/domains/vm2/disk.img /mount/vm2
sudo cp -r /lib/modules/2.6.18-4-xen-amd64 /mount/vm2/lib/modules/
sudo ln -s /mount/vm2/lib /mount/vm2/lib64
sudo umount /mount/vm2
sudo xm create -c /etc/xen/vm2.cfg

Also need to mess with any files containing the wrong IP. Some of these commands might be handy:

sudo mount -t ext3 -o loop /var/xen/domains/vm2/disk.img /mount/vm2
sudo cp -pr /mount/vm2/etc /mount/vm2/etc.bak
cd /mount/vm2/etc
sudo grep -rl "212.69.38.27" . 2> /dev/null
sudo perl -pi -e 's/212.69.38.27/78.47.146.253/g' /apache2/vhosts/*
sudo grep -rl "212.69.38.27" . 2> /dev/null
cd /
sudo umount /mount/vm2
sudo xm create -c /etc/xen/vm2.cfg

Finally you’ll need to update your networking configuration, here’s how mine look, /etc/network/interfaces:

auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet static
 address 78.47.146.253
 network 78.47.146.248
 netmask 255.255.255.248
 up route add 78.46.35.5 dev eth0
 up route add default gw 78.46.35.5
 down route del default gw 78.46.35.5
 down route del 78.46.35.5 dev eth0

and /etc/resolve.conf:

### Hetzner Online AG installimage
# nameserver config
nameserver 213.133.99.99
nameserver 213.133.100.100
nameserver 213.133.98.98

I run ISPConfig too so I also need to update its database so changes it makes for bind are correct:

mysql> update dns_a set ip_adresse='78.47.146.253' where ip_adresse='212.69.38.27';
mysql> update dns_isp_dns set dns_soa_ip= '78.47.146.253' where dns_soa_ip='212.69.38.27';

Oracle DB XML (was Sleepycat)

Posted in Software Releases, Talks and Conferences, Debian, XML by thejimmyg on the February 12th, 2008

At Geek Night 5 I bumped into an old friend of mine John Snelson who I haven’t seen for ages. He’s now working for Oracle on DB XML, a project he’s been involved with for a long time since the Sleepycat days. I promised to have a play with the Python bindings so for anyone following in my footsteps, here’s how you do it, it’s a lot easier than it appears from the docs and forum posts…

Download the latest version from the link below by clicking the "Free Download" button in the top right: http://www.oracle.com/technology/products/berkeley-db/xml/index.html

The dbxml-2.3.10.tar.gz file is about 30.9Mb. You’ll also need a standard GNU toolchain, I happen to have the following installed although you may not need them all:

sudo apt-get install build-essential make libc6-dev gcc g++ patch zlib1g-dev libncurses5-dev libssl-dev flex bison sharutils subversion python gettext autoconf2.13 pkg-config

Next extract the source and build it:

tar zxfv dbxml-2.3.10.tar.gz
cd dbxml-2.3.10
sh buildall.sh

This takes quite a while (about an hour on my Thinkpad R50e laptop) but compiles without any problems producing an install directory with bin, docs, lib and include directories containing everything you need.

Now for the Python bindings which are equally as easy because the main distribution also comes with a compatible source tree for the Python bsddb library. Compile and install it all like this:

cd dbxml/src/python
python setup.py build
python setup.py install
cd bsddb3-4.5.0
python setup.dbxml.py build
python setup.dbxml.py install

If you were to have any problems the README files contain plenty of tips. To test the Python bindings you simply need to add the library directory to your LD_LIBRARY_PATH since the original buildall.sh script is polite enough not to actually install the files to the system locations (although there is an option to have it do this). In my case this meant:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/james/Desktop/dbxml-2.3.10/install/lib

Now you can test the example:

cd ../../../../examples/python
python examples.py test

Everything should work perfectly.

Now that I’ve got the software compiled I need to start using it ;-). Here were some links I found were a useful introduction to native XML databases but the links on the Oracle page linked to earlier are no doubt worth a read too.

http://www-128.ibm.com/developerworks/xml/library/x-mxd4.html http://www.rpbourret.com/xml/XMLAndDatabases.htm http://www.w3.org/TR/xquery-use-cases/ http://www.regdeveloper.co.uk/2007/07/18/berkeley_db_xml/

Embedded Linux Server: Midge and the Edimax BR6104K(P)

Posted in Web, Debian, Embedded by thejimmyg on the February 10th, 2008

I’ve been chatting with Trevor (a colleague from work and the person who introduced me to diving) about the possibilities for modifying the firmware on simple router boards to do useful things in the home.

This page will document the progress I’ve made and the things I needed to buy to get it to work.

First of all you’ll need a router board. I chose the Edimax BR6104K(P) board which has an adm5120 processor, 16MB of RAM and 2MB of flash. Most usefully it comes with two USB headers already attached and is available in the UK for about £22 inc VAT from http://www.omnima.co.uk/store/catalog/Embedded-controller-p-16140.html

It comes with a power adapter and a few printed sheets which don’t really give you any more information than is already available on the website. One important thing to note is that the board come pre-installed with Midge, a derivative of OpenWRT which is a linux-based operating system designed so that it can be built automatically on a linux PC using GNU tools to enable you to produce your own firmware. This makes it a brilliant choice for anyone who wants to experiment with an embedded platform.

Out of the box, the board is configured like this:

root@midge:~# cat /etc/network/interfaces
# Configure Loopback
#
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

auto eth1
iface eth1 inet static
    address 192.168.1.1
    netmask 255.255.255.0

auto eth2
iface eth2 inet static
    address 192.168.2.1
    netmask 255.255.255.0

auto eth3
iface eth3 inet static
    address 192.168.3.1
    netmask 255.255.255.0

auto eth4
iface eth4 inet static
   address 192.168.4.1
   netmask 255.255.255.0

This means all the ports except eth0 are configured with fairly useless static IP addresses. The kernel routing table looks like this:

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.4.0     *               255.255.255.0   U     0      0        0 eth4
192.168.3.0     *               255.255.255.0   U     0      0        0 eth3
192.168.2.0     *               255.255.255.0   U     0      0        0 eth2
192.168.1.0     *               255.255.255.0   U     0      0        0 eth1

If you want to be able to sign in to the operating system running on the board you will therefore need to plug eth0 into your router so that the board can obtain an IP address. The silly thing is that the ports are numbered 0-4 as you look at the board starting from the right so eth0 is the right-most Ethernet socket. The appropriate LEDs come on once you plug it in. Once plugged in you’ll need to restart the router otherwise it doesn’t trigger DHCP.

Edimax board

After less than a minute you’ll be able to sign in with SSH. You’ll have to check your router’s DHCP table to find out which IP address it assigned the board. Once you’ve found out use SSH to sign in with the username root and the password midge and this is what you’ll see:

james@bose:~$ ssh root@192.168.1.3
The authenticity of host '192.168.1.3 (192.168.1.3)' can't be established.
RSA key fingerprint is 71:ed:8e:16:24:39:d9:93:28:cd:3e:ee:3a:e1:89:8c.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.1.3' (RSA) to the list of known hosts.
root@192.168.1.3's password:


BusyBox v1.1.2 (2007.06.07-14:35+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

         _nnnn_
        dGGGGMMb
       @p~qp~~qMb
       M|@||@) M|
       @,----.JM|
      JS^\__/  qKL                 _     _
     dZP        qKRb     _ __ ___ (_) __| | __ _  ___
    dZP          qKKb   | '_ ` _ \| |/ _` |/ _` |/ _ \
   fZP            SMMb  | | | | | | | (_| | (_| |  __/
   HZM            MMMM  |_| |_| |_|_|\__,_|\__, |\___|
   FqM            MMMM                     |___/
 __| ".        |\dS"qML
 |    `.       | `' \Zq
_)      \.___.,|     .'
\____   )MMMMMP|   .'
     `-'       `--' hjm


kamikaze (c) OpenWrt Team 200x-2006
midge (c) Vladislav Moskovets 2005-2006

Revision: r728
Builded at: 20070607 14:53

root@midge:~#

As you can see we have the 20070607 firmware which corresponds to revision 728 from the source tree at http://midge.vlad.org.ua/svn/trunk/

You can also see we have BusyBox v1.1.2 which is a set of command-line tools which behave very similarly to their GNU counterparts but are designed to be run on much leaner devices (ours only has 2Mb of storage remember).

Now you have signed in you can have a play, ping google etc.

One thing to be aware of is that there are a large number of iptables firewall walls set up by the /etc/init.d/S60fw script which don’t seem very sensible to me because they appear to have been hardcoded for a particular gateway. They’ll probably need changing if you want to be able to access the board on any port other than SSH or for pinging otherwise the kernel will simply drop the packets. This is a pain if you want to run a web server for example.

If you can’t sign into the board it is likely that your network configuration is conflicting in some way with this default setup as mine was to start with. The only solution is to build the serial cable mentioned later so that you can re-configure the network settings. Here’s what I had to run for the system to work on eth0 with my router (192.168.1.1):

ifdown eth0
ifdown eth1
ifdown eth2
ifdown eth3
ifdown eth4
ifup eth0
echo "nameserver 192.168.1.1" > /etc/resolv.conf

After that the basics worked fine. Some firewall configuration might be needed though depending on what you are trying to do.

Default Setup

Let’s have a look around the default install:

The fstab looks like this:

# /etc/fstab: static file system information.
#
# <file system> <mount pt>      <type>          <options>                       <dump>  <pass>
# /dev/root     /               ext2            rw,noauto                       0       1
proc            /proc           proc            defaults                        0       0
devpts          /dev/pts        devpts          defaults,gid=5,mode=620         0       0

root@midge:~# cat /proc/cpuinfo
system type             : ADM5120 Demo Board
processor               : 0
cpu model               : MIPS 4Kc V0.11
BogoMIPS                : 174.48
wait instruction        : yes
microsecond timers      : yes
tlb_entries             : 16
extra interrupt vector  : yes
hardware watchpoint     : yes
VCED exceptions         : not available
VCEI exceptions         : not available

root@midge:~# cat /proc/filesystems
nodev   rootfs
nodev   bdev
nodev   proc
nodev   sockfs
nodev   tmpfs
nodev   shm
nodev   pipefs
nodev   ramfs
nodev   devfs
nodev   devpts
        squashfs
        ext2

root@midge:~# cat /proc/meminfo
        total:    used:    free:  shared: buffers:  cached:
Mem:  15101952 12439552  2662400        0  1212416  5296128
Swap:        0        0        0
MemTotal:        14748 kB
MemFree:          2600 kB
MemShared:           0 kB
Buffers:          1184 kB
Cached:           5172 kB
SwapCached:          0 kB
Active:           3684 kB
Inactive:         2700 kB
HighTotal:           0 kB
HighFree:            0 kB
LowTotal:        14748 kB
LowFree:          2600 kB
SwapTotal:           0 kB
SwapFree:            0 kB

root@midge:~# cat /proc/version
Linux version 2.4.32 (root@builder) (gcc version 3.4.5 (OpenWrt-2.0)) #2 Thu Jun 7 14:51:02 UTC 2007

It is worth noting that any changes you make to the router a lost when you power cycle it unless you type flash save to save the changes.

Building a Cable

To be able to upgrade the firmware (or even to be able to connect to the board if the default network settings aren’t working for you) you will need to build a serial cable. This isn’t particularly straightforward because the voltages on the board and the serial connection on your computer are different so you need to build a simple circuit to adjust the voltages.

To make your own lead, you’ll need some bits and pieces:

MAX3232ECPE chip for adjusting the voltages between the board and the serial port so it is a valid RS232 connection: Maplin (check stock) http://www.maplin.co.uk/module.aspx?ModuleNo=11979&#038;doy=search

RS232 plug Maplin: RK60Q or chop the end off an existing lead with a 9-pin D-type plug. (Note this is not the one you’d plug directly into the PC serial port but its inverse so that you can easily add an extension cable. If you want to plug in directly you’ll need a female 9-pin plug)

A breadboard or if you like soldering, a pre-drilled board

Soldering iron, solder and wire for soldering the wires to the 9-pin plug

4 x 0.1 micro farad ceramic capacitors (Maplin BX03D)

IDC header (maplin JB59 is 2×5 pin, will work but 2×4 pin is better) (These are the black headers you get on the ends of ribbon cables for plugging hard drives into motherboards etc. The board has a 2×4 set of pins so a 2×4 IDC header would be best. I actually used an old hard disk ribbon cable whose IDC header was obviously much to long but there are no other electronics in the way so this is OK)

Strip of ribbon cable 8 cables wide. You can always get a thicker one and tear it down the middle though.

Extension lead and two plugs so that you can connect your cable to a computer more easily.

Once you have all your components wire them altogether according to this circuit diagram provided by Trevor:

MAX3232 Diagram for Edimax Board to Serial

You might find the chip specifications on page 14 of this manual useful too: http://datasheets.maxim-ic.com/en/ds/MAX3222-MAX3241.pdf

If things don’t work, double check all your connections, the circuit does work.

Connecting via the Serial Cable

To connect to the board using your cable you’ll need minicom:

sudo apt-get install minicom

You’ll then need to set it up to use your serial port (probably /dev/ttyS0) and with hardware flow control disabled. Here’s how:

sudo minicom

Now change some settings. Press Ctrl+A then o:

+-----[configuration]------+
| Filenames and paths      |
| File transfer protocols  |
| Serial port setup        |
| Modem and dialing        |
| Screen and keyboard      |
| Save setup as test       |
| Save setup as..          |
| Exit                     |
+--------------------------+

Choose Serial port setup then press A to change the Serial Device to the correct one, probably /dev/ttyS0. Press E to change the Bps/Par/Bits setting to 115200 8N1 and press F to change Hardware Flow Control to No. It should now look like this:

+-----------------------------------------------------------------------+
| A -    Serial Device      : /dev/ttyS0                                |
| B - Lockfile Location     : /var/lock                                 |
| C -   Callin Program      :                                           |
| D -  Callout Program      :                                           |
| E -    Bps/Par/Bits       : 115200 8N1                                |
| F - Hardware Flow Control : No                                        |
| G - Software Flow Control : No                                        |
|                                                                       |
|    Change which setting?                                              |
+-----------------------------------------------------------------------+
        | Screen and keyboard      |
        | Save setup as test       |
        | Save setup as..          |
        | Exit                     |
        +--------------------------+

Press Esc to exit the menu and then choose Save setup as.. and give it the name edimax. From now on, whenever you want to connect to the board you can just type:

sudo minicom edimax

To exit minicom type Ctrl+A followed by q.

You can now login with username root and password midge. If you power cycle the router you’ll also be able to see it boot.

Installing Extra Software

Midge comes with a package manager which allows you to install extra software. You’ll need to run this command to get the latest list though and networking must obviously be working by now, try pinging google.com if you have any problems:

ipkg update

Find out which software is available with:

ipkg list | more

Search for vfat package with:

ipkg list | grep vfat

Install the elinks and libopenssl packages with:

ipkg install elinks libopenssl

You get the idea.

Building Custom Firmware

The real fun starts when you can build your own firmware. First install the tools you need:

sudo apt-get install make libc6-dev gcc g++ patch zlib1g-dev libncurses5-dev libssl-dev flex bison sharutils subversion python gettext autoconf2.13 pkg-config

Then check out the source:

svn co http://midge.vlad.org.ua/svn/trunk/openwrt-midge

Now copy the config file you wish to build:

cd openwrt-midge
cp target/linux/adm5120-2.4/openwrt-config-midge-cirouter .config
make menuconfig DEVELOPER=1
make V=99

The build system will now download source versions of all the tools it needs and compile them so that they can cross compile to the ADM5120 platform (it can’t just use the i386 versions since the target processor is not i386). This takes about an hour but once it is done it will build the firmware. Any future builds will be a lot quicker.

The firmware files are in the bin directory:

-rw-r--r-- 1 james james 1901568 2008-02-09 23:11 openwrt-adm5120-2.4-squashfs.bin
-rw-r--r-- 1 james james 1901568 2008-02-09 23:11 openwrt-adm5120-2.4-squashfs.bin.csys

The .bin file is for testing the firmware in RAM. The .bin.csys version is for installing to flash.

Uploading Firmware

To transfer the firmware plug in the serial cable you made and start minicom. You’ll need to set up minicom so that hardware flow control is off as described earlier. Get minicom connected and turn off the board. As soon as you turn the router on press SPACE three times in succession. You have about two seconds to do this otherwise the bootloader boots the standard firmware. If successful you’ll see this:

Linux Loader Menu
=======================
(a) Download vmlinuz to flash ...
(b) Download vmlinuz to sdram (for debug) ...
(c) Exit

We just want to test our firmware so we choose option (b) to start with. It will say:

Downloading.........

Next you need to use xmodem to transfer the file. This can be a bit temporamanetal so experiment with the delays and the number of key presses. I find if I wait for about 8 seconds (or until 8 characters are displayed) then press the up arrow a few times the transfer usually works. After you’ve done the waiting and the up arrow pressing press Ctrl+A followed by s to have minicom send a file. Choose the xmodem protocol then enter the path to the .bin version of the firmware.

Note

You don’t have too much time to do this before it times out so you might want to put the firmware somewhere close to the directory you ran minicom from to save on typing.

If all goes well the firmware will start transferring:

+-----------[xmodem upload - Press CTRL-C to quit]------------+
|Xmodem sectors/kbytes sent:   0/ 0kRetry 0: NAK on sector    |
|Retry 0: NAK on sector                                       |
|Retry 0: NAK on sector                                       |
|Retry 0: NAK on sector                                       |
|Retry 0: NAK on sector                                       |
|Retry 0: NAK on sector                                       |
|Xmodem sectors/kbytes sent: 11764/1470k                      |
+-------------------------------------------------------------+

Once transfer is complete it will play a short tune and display this:

+-----------[xmodem upload - Press CTRL-C to quit]------------+
|Retry 0: NAK on sector                                       |
|Retry 0: NAK on sector                                       |
|Bytes Sent:1901568   BPS:7826                                |
|                                                             |
|Transfer complete                                            |
|                                                             |
| READY: press any key to continue...                         |
+-------------------------------------------------------------+

Then it will boot the firmware you loaded into RAM, once again you can sign in with root and midge:

root@midge:~# uname -a
Linux midge 2.4.32 #2 Sat Feb 9 23:09:17 GMT 2008 mips unknown

root@midge:~# cat /proc/version
Linux version 2.4.32 (james@bose) (gcc version 3.4.5 (OpenWrt-2.0)) #2 Sat Feb 9 23:09:17 GMT 2008

This time you are running your own firmware, congratulations.

USB Disk Access

To get more storage space you can plug a USB flash drive or hard disk into one of the USB 1.1 ports. Most of these devices are formatted with a FAT filesystem so you’ll need to ensure the board has the necessary kernel modules to deal with USB and the FAT filesystem. Here are the commands you need:

ipkg install kmod-fs-ext2
ipkg install kmod-usb-core
ipkg install kmod-usb-ohci
ipkg install kmod-usb-shci
ipkg install kmod-usb-storage
ipkg install kmod-fs-vfat

insmod scsi_mod
insmod sd_mod
insmod ext2
insmod usbcore
insmod usb-storage
insmod usb-shci
insmod fat
insmod vfat

You’ll probably find that many of these are already present. Once you’ve got the required software you can mount the disk:

mkdir /mnt/usbdisk
mount /dev/scsi/host0/bus0/target0/lun0/part1 /mnt/usbdisk

You can work out the device to mount because when you plug in the disk you’ll see something like this printed by the kernel to the serial cable:

hub.c: new USB device adm5120-hcd-1, assigned address 2
scsi0 : SCSI emulation for USB Mass Storage devices
  Vendor: Kingston  Model: DataTravelerMini  Rev: PMAP
  Type:   Direct-Access                      ANSI SCSI revision: 02
Attached scsi removable disk sda at scsi0, channel 0, id 0, lun 0
SCSI device sda: 2015232 512-byte hdwr sectors (1032 MB)
sda: Write Protect is off
Partition check:
 /dev/scsi/host0/bus0/target0/lun0: p1

The last line tells you that you are using partition 1 of device /dev/scsi/host0/bus0/target0/lun0.

You can now read and write to the drive (although it is a bit slow because it is USB 1.1, not 2.0):

root@midge:~# ls /mnt/usbdisk
Essentials                     otp_mibs.pdf
debugger.pdf                   programming_examples.pdf
design_principles.pdf          reference_manual.pdf
docbuilder.pdf                 runtime_tools.pdf
edoc.pdf                       sasl.pdf
efficiency_guide.pdf           snmp.pdf
erts.pdf                       ssh.pdf
getting_started.pdf            ssl.pdf
inets.pdf                      system_architecture_intro.pdf
james.txt                      system_principles.pdf
mnesia.pdf                     tools.pdf
mnesia_overview.pdf            tutorial.pdf
odbc.pdf                       webtool.pdf
otp_doc_html_R12B-0.tar.gz

Building a More Useful Firmware

I want to run a web server on my board so I’m going to compile a firmware with the BusyBox httpd program and the haserl package installed. I’d have liked to install the bluetooth tools too but doing this makes the firmware too big to install on the board with the standard bootloader (the firmware I compiled was about 1.45Mb).

KERNEL_MAXSIZE=655360 (640k) SQUASHFS_MAXSIZE=1245184 (1216k)

You can’t add the BusyBox httpd program as a package because the whole of BusyBox has to be compiled at once. To create the firmware run these commands again (any existing firmware in the bin directory will be over-written):

make clean
cp target/linux/adm5120-2.4/openwrt-config-midge-cirouter .config
make menuconfig DEVELOPER=1

Go into OpenWrt Package Selection  —> then “Base system  —> then busybox then “ Busybox Configuration“ then Networking Utilities and select httpd so it has a * character by it. This also takes you slightly over the limit so I went through the other options and removed clear, sed, awk, more and xargs which I didn’t expect to need. which, grep and hexdump are required so don’t remove them even if it is tempting to do so.

Exit all the way out of the program and save the configuration. Then build it with this command (the V=99 means maximum verbosity):

make V=99

Once the firmware is built you’ll want to write it to the board. Connect the serial cable, turn the rooter off and on and press three times to get the menu as before. This time though choose option (a) to save the firmware to flash. You follow exactly the same procedure as before except you choose the .bin.csys version of the firmware and after the upload is done you’ll see this:

Downloading.........||||||PASS

Eraseing nor flash.......PASS

Programming nor flash...PASS

If you turn the router on and off and on again it will boot the new firmware and once you sign in with root and midge again you’ll get this:

BusyBox v1.1.2 (2008.02.10-14:44+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

         _nnnn_
        dGGGGMMb
       @p~qp~~qMb
       M|@||@) M|
       @,----.JM|
      JS^\__/  qKL                 _     _
     dZP        qKRb     _ __ ___ (_) __| | __ _  ___
    dZP          qKKb   | '_ ` _ \| |/ _` |/ _` |/ _ \
   fZP            SMMb  | | | | | | | (_| | (_| |  __/
   HZM            MMMM  |_| |_| |_|_|\__,_|\__, |\___|
   FqM            MMMM                     |___/
 __| ".        |\dS"qML
 |    `.       | `' \Zq
_)      \.___.,|     .'
\____   )MMMMMP|   .'
     `-'       `--' hjm


kamikaze (c) OpenWrt Team 200x-2006
midge (c) Vladislav Moskovets 2005-2006

Revision: r899
Builded at: 20080210 15:04

Notice the updated dated and version numbers.

Setting up the Web Server

Now that you have the new firmware with the http server you can configure it. Mount the USB drive to /mnt/usbdisk and create a new folder called www. Within www create a cgi-bin directory. Now edit /etc/httpd.conf to comment out the password protection on the cgi-bin directory so it looks like this:

D:172.28.202                # Deny address from 172.20.0.0/16
D:10.0.0.0/25               # Deny any address from 10.0.0.0-10.0.0.127
D:10.0.0.0/255.255.255.128  # Deny any address that previous set
#D:127.0.0.1                # Deny local loopback connections
A:*                         # Allow from other IP connections
#/cgi-bin:admin:123          # Require user foo, pwd bar on urls starting with /cgi-bin/
/adm:admin:setup            # Require user admin, pwd setup on urls starting with /adm/
/adm:toor:PaSsWd            # or user toor, pwd PaSsWd on urls starting with /adm/
.au:audio/basic             # additional mime type for audio.au files
*.php:/path/php             # running cgi.php scripts through an interpreter

Now we need a CGI script, we’ll write it in C. Save this as test.c

#include <stdio.h>
int main(int argc, char** argv)
{
    printf("Content-Type: text/html\n\n<html>Hello Trevor!</html>\n");
    return 0;
}

You can compile it with:

/home/james/Desktop/openwrt-midge/staging_dir_mipsel/bin/mipsel-linux-uclibc-gcc -o test test.c

mipsel-linux-uclibc-gcc is the equivalent of gcc on the Linux PC and it seems to be able to find the headers and libraries it needs. You can now copy the output to the USB memory stick in the www/cgi-bin directory and ensure it has executable permissions by running chmod 755 test. Mount the USB drive on the board again and start the HTTP server:

httpd -d /mnt/usbdisk/www/

Finally change the firewall to allow port 80 by editing /etc/network/fw to add this line under the line for port 22:

$ADD INPUT $ACCEPT $TCP --dport 80

and reload the firewall rules:

/etc/init.d/S60fw restart

Now if you visit http://<your-board’s-ip>/cgi-bin/test your CGI script should run to produce the message Hello Trevor!.

Bluetooth (Not Working)

Here’s what I ran to try to get bluetooth working:

ipkg update
ipkg install kmod-bluetooth bluez-libs bluez-utils picocom

insmod bluez
insmod l2cap
insmod hci_usb
insmod rfcomm
insmod sco
insmod hci_uart

When I plug in the bluetooth dongle (a modern Belkin one) I get this message which doesn’t bode well:

hub.c: new USB device adm5120-hcd-2, assigned address 3
usb.c: USB device 3 (vend/prod 0x50d/0x131) is not claimed by any active driver.

When I try to load the device the kernel crashes:

root@midge:~# hciconfig hci0 up
Unable to handle kernel paging request at virtual address 00000000, epc == c007b6f8, ra == c007bc9c
Oops in fault.c::do_page_fault, line 206:
$0 : 00000000 10008400 a0a53180 a0a53190 801c6800 0001a780 0094b7c4 00000011
$8 : 801fe600 80109638 00000000 8014c9d0 00000519 10008400 00000000 00000001
$16: 00000000 801b89e0 0094b7c4 80514414 00000011 00000004 0001a780 0094b780
$24: ba2e8ba3 8015e5b4                   808be000 808bfd90 801b89e0 c007bc9c
Hi : 00000002
Lo : 00000002
epc   : c007b6f8    Not tainted
Status: 10008402
Cause : 10800008
PrId  : 0001800b
Process hciconfig (pid: 2201, stackpage=808be000)
Stack:    00000001 a0a7a2c0 80514414 00418280 80514454 00000004 00000000
 80514414 000000aa 801c6800 01000000 c007bc9c 801a81cc 809d3a40 ffffffbf
 801553c0 80514414 00000004 00000011 801c6800 801b89e0 10008400 a0a53180
 801c6800 00000000 a0a7a2c0 80514414 00418280 80030000 c007d2fc 8090903c
 809d3c20 0040f184 80f79520 809d3c20 80035214 802519a0 2ab9c200 809d3c20
 801a84e4 ...
Call Trace:   [<c007bc9c>] [<80030000>] [<c007d2fc>] [<80035214>] [<c0130000>]
 [<80030000>] [<c0137778>] [<c012d388>] [<800448c9>] [<80049fb8>] [<80049fb8>]
 [<8009fa6c>] [<80009bc0>] [<80109224>] [<800448c9>] [<8005c80c>]

Code: 00151880  00621821  8c700030 <8e020000> 04410005  3c028001  3c04c008  24424534  0040f809
Segmentation fault

Looks like I’ll have to save bluetooth for another day. Some clues though:

http://midge.vlad.org.ua/forum/viewtopic.php?t=461&#038;sid=84bdddddb305bc7b25950c6975d95910 http://forum.amilda.org/viewtopic.php?pid=649 http://midge.vlad.org.ua/forum/viewtopic.php?p=4357&#038;sid=a4c2a20158761bbea68efab649f43e39

Nginx Proxying to Pylons with SSL on Debian Etch

Posted in Pylons, Web, Debian, Hosting by thejimmyg on the December 7th, 2007

The easy way to install Nginx is like this:

sudo aptitude install nginx

The problem is that this installs an old version (0.4) and doesn’t have SSL support built in. Nginx is designed to be super fast so and modules need to be compiled in manually. This means you need remove the Nginx package if you want SSL support.

If you try sudo apt-get remove –purge nginx you get this error:

Reading package lists... Done
Building dependency tree... Done
The following packages will be REMOVED
  nginx*
0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded.
Need to get 0B of archives.
After unpacking 524kB disk space will be freed.
Do you want to continue [Y/n]? y
(Reading database ... 26362 files and directories currently installed.)
Removing nginx ...
Stopping nginx: invoke-rc.d: initscript nginx, action "stop" failed.
dpkg: error processing nginx (--purge):
 subprocess pre-removal script returned error exit status 1
Starting nginx: 2007/12/07 14:45:03 [emerg] 29441#0: unknown directive "ssl" in /etc/nginx/nginx.conf:30
invoke-rc.d: initscript nginx, action "start" failed.
dpkg: error while cleaning up:
 subprocess post-installation script returned error exit status 1
Errors were encountered while processing:
 nginx
E: Sub-process /usr/bin/dpkg returned an error code (1)

The solution is to edit /var/lib/dpkg/info/nginx.prerm and comment out the line with invoke-rc.d which gives the stop statement for nginx. If you run the command again it will remove successfully, purging your nginx.conf config file too. If this isn’t what you want make a backup first.

You can then remove your logs with:

sudo rm -rf /var/log/nginx/

Now to install Nginx 0.6 from source. Fisrt you will need some build tools:

sudo aptitude install build-essential

Then we need some libraries:

sudo aptitude install libpcre3 libpcre3-dev libpcrecpp0 libssl-dev zlib1g-dev

Check what the latest version is at http://nginx.net. At the time of writing the latest stable version is 0.5.33 so download that:

wget http://sysoev.ru/nginx/nginx-0.5.33.tar.gz
tar zxfv nginx-0.5.33.tar.gz
cd nginx-0.5.33

Now you are ready to compile Nginx. As mentioned earlier many of the options are set at compile time so have a look at the Compile Time Options page and decide which you need. We are going to set two options. The first is:

--with-http_ssl_module

This enables the SSL module. The second option is to customise where Nginx is installed to. The default is /usr/local/nginx but this means the Nginx binary will be /usr/local/nginx/sbin/nginx which isn’t on the PATH. A better place is /usr/local/sbin where it is easily accessible by root or by users with sudo access:

--sbin-path=/usr/local/sbin

Now we are ready to configure:

./configure --sbin-path=/usr/local/sbin --with-http_ssl_module

There is a useful configuration summary:

nginx path prefix: "/usr/local/nginx"
nginx binary file: "/usr/local/sbin"
nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
nginx pid file: "/usr/local/nginx/logs/nginx.pid"
nginx error log file: "/usr/local/nginx/logs/error.log"
nginx http access log file: "/usr/local/nginx/logs/access.log"
nginx http client request body temporary files: "/usr/local/nginx/client_body_temp"
nginx http proxy temporary files: "/usr/local/nginx/proxy_temp"
nginx http fastcgi temporary files: "/usr/local/nginx/fastcgi_temp"

Then compile and install:

make
sudo make install

The first thing I do next is create a backup of the original file:

sudo cp /usr/local/nginx/conf/nginx.conf  /usr/local/nginx/conf/nginx.conf.bak

Then start the server:

sudo /usr/local/sbin/nginx

If you visit http://yourdomain.com you should see the Nginx welcome message Welcome to nginx!. If you don’t it might be because you have another server such as Apache running.

To kill the server you can use the pid file:

sudo kill `cat /usr/local/nginx/logs/nginx.pid`

Notice this uses the ` character (normally underneath Esc) not the ‘ character. Obviously it is nicer to have an init.d setup so you can start and stop Nginx the same way as Apache and other servers. We’ll use the script from Slicehost which is itself based on the Debian package:

wget http://articles.slicehost.com/assets/2007/10/19/nginx
sudo chmod +x nginx
sudo mv nginx /etc/init.d

Now we can add this script to the runlevels:

sudo /usr/sbin/update-rc.d -f nginx defaults

Now you can start, stop and restart Nginx with these commands as normal:

sudo /etc/init.d/nginx start
sudo /etc/init.d/nginx stop
sudo /etc/init.d/nginx restart

Now let’s setup Nginx to proxy to a Pylons application. Replace these lines in /usr/local/nginx/conf/nginx.conf:

location / {
    root   html;
    index  index.html index.htm;
}

with these:

location / {
    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;
    proxy_set_header        X-Forwarded-Host $host;
    proxy_set_header        X-Forwarded-Port $server_port;
    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;
    proxy_pass  http://127.0.0.1:5000;
    proxy_redirect  default;
}

Update: Added X-Forwarded-Port and X-Forwarded-Host to the above since I use them both so much.

This will proxy all requests to another server running on port 5000, for example a running Pylons application. To test this you should start your Pylons application (making sure debug is set to false if this is a production setup):

paster serve development.ini

Now restart Nginx:

sudo /etc/init.d/nginx restart

and f you visit the site you should see your Pylons application.

Now for the SSL:

sudo aptitude install openssh-server

First create a the key, pem and certificate files:

openssl genrsa 1024 > host.key
chmod 400 host.key
openssl req -new -x509 -nodes -sha1 -days 365 -key host.key > host.cert
cat host.cert host.key > host.pem
chmod 400 host.pem

Make sure the Common Name is the same as the domain name the certificate is for.

Now we need to setup SSL on Nginx. This is described in detail here but it really just requires making the server section look like this:

worker_processes 1;
http {
    ...
    server {
        listen               443;
        ssl                  on;
        ssl_certificate      /path/to/host.pem;
        ssl_certificate_key  /path/to/host.key;
        keepalive_timeout    70;
    }
}

Restart Nginx again:

sudo /etc/init.d/nginx restart

Now if you visit http://yourdomain.com you’ll get no response but if you visit https://yourdomain.com you’ll get a certificate warning because the SSL certificate is not signed by a certificate authority. Click OK and you will have access to your application.

The final part of the setup is to setup a static file which redirects from the http version of the site to the https version. The easy way to do this is by setting up another server listening on port 80 and creating an error 404 page which redirects to the https version. Add this to the nginx config just before the existing server:

server {
    listen 80;
    server_name  yourdomain.com;
    error_page  404              /404.html;
    location = /404.html {
        root   /path/to/directory/containing/404/doc/;
    }
}

Then create a 404.html file which looks something like this but adjusted for your URL instead of yourdomain.com:

<html>
<head>
<meta http-equiv="refresh" content="2;URL=https://yourdomain.com/">

</head>
<body>
<h2>Redirecting</h2>
<p>You are being redirected to the <a href="https://yourdomain.com/">secure version of this site.</a></p>
</body>
</html>

Then restart Nginx again.

You should now have a secure Pylons app on the https port and a redirect page on the http port.

Further Reading:

http://articles.slicehost.com/2007/10/19/debian-etch-installing-nginx http://ubuntuforums.org/showthread.php?t=453053 http://sudhanshuraheja.com/2007/09/remove-nginx-from-ubuntu-fiesty-fawn.html http://www.rkblog.rk.edu.pl/w/p/pylons-and-nginx/

Subversion over SVN+SSH on Debian

Posted in Debian, Hosting by thejimmyg on the December 4th, 2007

The traditional way of setting up subversion is via Apache but what if you don’t want to install Apache? In that case you can use svnserve but what if your host won’t let you run a persistant server? In that case you can create a linux system account for every user and give them induvidual SSH logins. You then give your users a URL starting svn+ssh:// instead of the usual http://. The Subversion client recognises this form of URL and invokes a local ssh process, connecting to the host, authenticating as the user, then spawning a private svnserve process on the remote machine running as that user. The svnserve command is being invoked in tunnel mode (-t) and its network protocol is being tunneled over the encrypted connection by ssh, the tunnel-agent. svnserve is aware that it’s running as the user, and if the client performs a commit, the authenticated username will be attributed as the author of the new revision.

This is all well and good but you might not wa nt to have to create user accounts for each of the users you want to give access to subversion. In this case you can create one system user account and use a different SSH private key for each user you want to grant access to. You then setup the ~/.ssh/authorized_keys file so that each user only has access to svnserve and that each svnserve process is started with their particular username so that all the commits are handled correctly. This is only possible with subversion 1.1.0 and above.

This is what we are going to do for two users, james and mike. james is a linux user, mike is a Windows user.

First let’s setup the server:

sudo apt-get install subversion openssh-server

Then create a subversion user svn, a home directory, an .ssh directory and finally set the correct permissions:

sudo useradd svn
sudo mkdir /home/svn
sudo mkdir /home/svn/.ssh
sudo chown -R svn:svn /home/svn

If you intend to be able to login as svn for testing purposes later you should set a password:

sudo passwd svn

Create the directory for the repositories:

sudo mkdir /var/svn

Setup a repo repository and commit the first import:

sudo mkdir /var/svn/repo
sudo mkdir /tmp/repo
sudo mkdir /tmp/repo/branches
sudo mkdir /tmp/repo/tags
sudo mkdir /tmp/repo/trunk
sudo svnadmin create /var/svn/repo
sudo svn import /tmp/repo file:///var/svn/repo -m "initial import"
sudo rm -rf /tmp/repo

Change the permissions so that the svn user and svn group have access:

sudo chown -R svn:svn /var/svn/repo

Set the permissions to 770 and the umask to 2 so that any files are created have the correct permissions:

sudo chmod 2770 -R /var/svn/repo

At this point you can test the setup manually. As a user other than svn try this:

svn co svn+ssh://svn@localhost/var/svn/repo .

This should prompt you for the password a couple of times and then checkout the repository.

We are half way there, next we need to set up two SSH public-private key pairs, one for Mike, one for James. As the svn user run:

ssh-keygen -t rsa -b 1024 -f mike.key
ssh-keygen -t rsa -b 1024 -f james.key

With each command you can just press <Enter> twice unless you want to set a password. You will now have the files mike.key, mike.key.pub, james.key and james.key.pub in the current directory. The .key files are the private keys. They should be given securely to Mike and James repsectively. Anyone who gets hold of the files will have the same permissions to the repository as James and Mike so they should be treated with the same respect as a password and not posted online!

Since Mike is on Windows he will need WinSCP, PuTTY, PuTTYgen and TortoiseSVN (the latter requires adminsitrator access to install).

Here’s what he does:

  • Use WinSCP to copy the mike.key file to his desktop if he didn’t recieve it any other way

  • Open PuTTYgen and from the Conversions menu, select Import, then browse to and select mike.key. Leave the passphrase boxes blank and select Save private key. Click Yes on the confirmation box, and save the key with a .ppk extension, like mike.ppk. This is now a key that PuTTY can use.

  • Start PuTTY again. Fill out the hostname box, then scroll down to SSH > Auth. Browse for the mike.ppk file. Then go back up to Sesson, give the session a name (for example mike) and save it. Test by logging in with the username ssh. You should see something like this:

    login as: svn
    Authenticating with public key "imported-openssh-key"
    ( success ( 1 2 ( ANONYMOUS EXTERNAL ) ( edit-pipeline svndiff1 absent-entries ) ) )
    
  • With this in place you can set up TortoiseSVN with the key, [I haven’t tested this next bit yet] First, create a new folder, then right-click it and select SVN Checkout. In the dialog box, enter this in the URL field svn+ssh://svn@mike/var/svn/repo. svn+ssh is how TortoiseSVN will access your server, svn@mike is your credentials for logging in (mike is the session we set up using the keys in PuTTY), and /var/svn/repo is where the repository is located on the server. Later on in this tutorial we’ll configure the server so this can be accessed as svn+ssh://svn@mike/repo.

From James’s point of view the process is a bit simpler becasue on Linux the .key file doesn’t need to be converted to a .ppk file:

  • Create a ~/.ssh directory:

    mkdir ~/.ssh
    
  • Copy the private key to ~/.ssh/id_dsa you don’t already have it:

    scp svn@example.com:/home/svn/james.key ~/.ssh/id_dsa
    

Now that the private keys are set up it is time to setup the public keys on the subversion server. Copy the contents of mike.key.pub and james.key.pub to /home/svn/.ssh/authorized_keys so that the each publick key is on a separate line:

touch .ssh/authorized_keys
cat mike.key.pub >> .ssh/authorized_keys
cat james.key.pub >> .ssh/authorized_keys

It should look something like this but with lots of characters in place of :

ssh-rsa AAA...acFHU= svn@example
ssh-rsa AAA...acBDH= svn@example

The three columns are TYPE KEY COMMENT. Since the last part is a comment it makes sense to change it to the names of the users so you remember which line referrs to who:

ssh-rsa AAA...acFHU= mike
ssh-rsa AAA...acBDH= james

This is all well and good but at the moment Mike and James can also SSH directly into the svn account so we want to restrict their access. Each line in the authorized_keys file can also have a command="COMMAND" section at the start. The subversion client executes svnserve -t when it SSHs in but you can also specify the executable to use explicitly:

command="/usr/bin/svnserve -t" ssh-rsa AAA...acFHU= mike
command="/usr/bin/svnserve -t" ssh-rsa AAA...acBDH= james

Now you might want to limit the users to a particular repository, you can do this with the -r option:

command="/usr/bin/svnserve -t -r /var/svn/" ssh-rsa AAA...acFHU= mike
command="/usr/bin/svnserve -t -r /var/svn/" ssh-rsa AAA...acBDH= james

James and Mike can access the repo repository with svn+ssh://svn@localhost/repo instead of svn+ssh://svn@localhost/var/svn/repo

You will probably want to limit the other things the users can do with the svn account so you’d probably add no-port-forwarding,no-pty,no-agent-forwarding,no-X11-forwarding to the command like this:

command="/usr/bin/svnserve -t -r /var/svn/",no-port-forwarding,no-pty,no-agent-forwarding,no-X11-forwarding ssh-rsa AAA...acFHU= mike
command="/usr/bin/svnserve -t -r /var/svn/",no-port-forwarding,no-pty,no-agent-forwarding,no-X11-forwarding ssh-rsa AAA...acBDH= james

So far, the svnserve command still doesn’t know which username it is supposed to be using so we add the –tunnel-user option to tell it explicitly:

command="/usr/bin/svnserve -t -r /var/svn/ --tunnel-user=mike",no-port-forwarding,no-pty,no-agent-forwarding,no-X11-forwarding ssh-rsa AAA...acFHU= mike
command="/usr/bin/svnserve -t -r /var/svn/ --tunnel-user=james",no-port-forwarding,no-pty,no-agent-forwarding,no-X11-forwarding ssh-rsa AAA...acBDH= james

At this point everything should now work as expected. Both James and Mike should be able to access and commit to the repository without needing a password and their commits should be logged as james and mike respectively because they are using different private keys and we are using the –tunnel-user approach. No other users should be able to access the repository except the svn user if you know the password.

Further reading:

http://svnbook.red-bean.com/en/1.1/ch06s03.html http://allyourtech.com/content/articles/23_12_2005_setting_up_subversion_and_tortoisesvn.php http://allyourtech.com/content/articles/24_12_2005_ditching_the_password_prompts_in_tortoisesvn.php http://svn.collab.net/repos/svn/trunk/notes/ssh-tricks http://svn.haxx.se/dev/archive-2004-03/0253.shtml http://bitworking.org/news/Getting_subversion_svn_ssh____to_work_with_PuTTY http://www.linuxfromscratch.org/blfs/view/svn/server/svnserver.html

For testing it is also possible to set the $SVN_SSH variable specifying the private key to use with -i so that you can try connecting as different users. For example:

export SVN_SSH="ssh -i /home/james/.ssh/mike.key

Pylons 0.9.7-dev Nginx Deployment on a Two-Way Routed Xen Setup

Posted in Pylons, Debian, Virtulization by thejimmyg on the November 10th, 2007

On Dom0 set up port forwarding from port 80 to the DomU running NginX, in this case 10.0.0.1:

sudo -i
iptables -A PREROUTING -t nat -p tcp -i eth0 --dport 80 -j DNAT --to 10.0.0.1:80
exit

These get lost on each reboot unless you put them into a script in /etc/network/if-up.d/iptables but that’s OK for the moment.

First install Nginx:

sudo apt-get install nginx

If you visit the URL of the Dom0 server you should see the Welcome to nginx! message served from Nginx on the DomU.

Next you need to setup Python and Pylons. Install python:

sudo apt-get install python mercurial

Get vitualenv:

wget http://pypi.python.org/packages/source/v/virtualenv/virtualenv-0.9.1.tar.gz
tar zxfv virtualenv-0.9.1.tar.gz
cp virtualenv-0.9.1/virtualenv.py ./
rm virtualenv-0.9.1.tar.gz
rm -r virtualenv-0.9.1

Decide where you want your Pylons applications. I like mine in /var/web so lets create a test project:

sudo mkdir /var/web
sudo mkdir /var/web/test
sudo chown james:james /var/web/test

Setup a virtual environment:

james@vm2:~$ python virtualenv.py /var/web/test
New python executable in /var/web/test/bin/python
Installing setuptools.............................done.
james@vm2:~$ cd /var/web/test

Now you can install Pylons:

mkdir dep
cd dep
hg clone http://pylonshq.com/hg/pylons-dev
cd pylons-dev
../../bin/python setup.py develop

Now create a project:

mkdir src
cd src
../bin/paster create -t pylons Test

Now edit Test/test/config/middleware.py and set use_webop=True. Serve the app with:

cd Test/
../../bin/python setup.py develop
../../bin/easy_install sqlalchemy                        <-- So that beaker doesn't break
../../bin/paster serve --reload development.ini

That’s it. Now you just need to setup Nginx to reverse proxy to the paste server running on port 5000.

Edit the /etc/nginx/nginx.conf file so that the location / part looks like this:

location / {
    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;
    proxy_pass  http://127.0.0.1:5000;
    proxy_redirect  default;
}

You’ll then need to restart nginx and the paster server:

sudo /etc/init.d/nginx restart
../../bin/paster serve --reload development

If you press refresh in your browser you should see the Pylons welcome page.

Debain 4.0 Etch AMD 64 X2 Server from Hetzner

Posted in Debian, Hardware, Virtulization, Hosting by thejimmyg on the November 9th, 2007

I bought a new server from Hetzner (German) on Sunday 4th November and on the evening of the 5th I received my sign in details by email in both German and English for the server, already installed with the 64bit version of Debian Etch. This post documents my progress setting it up.

Exploring the Control Panel

The first email you get gives you a sign in to the Hetzner control panel (they call it Robot). Everything is in German but here are some translations of the interface (thanks to Google Translate):

Verwaltung                           Administration
        Sicherheit                           Security
        E-Mail-Adressen                      Emails
        Support-Anfragen                     Support requests
        Status-Benachrichtigung              Status Notification
        Newsletter                           Newsletter
        RIPE-Registration                    RIPE-Registration
Rechnungen                           Bills
        Offene Posten                        Open Item
Traffic-Statistik                    Traffic Statistics
        Traffic-Limit-Reporting              Traffic limit Reporting
        Tagesbericht                         Daily Report
        Monatsbericht                        Monthly Report
        Jahresbericht                        Annual Report
Leistungsübersicht                   Performance Overview
        Resetaufträge                        Reset orders
        Rescuesystem                         Rescue System
        VNC-Installation                     VNC-Installation
        neuen Server bestellen               New server order
        Separater Admin-Zugang               Separate Admin Access
Reverse-DNS-Einträge                 Reverse-DNS
        Eintrag anlegen                      Entry
        Eintrag löschen                      Delete Entry
Dokumentation                        Documentation
        Daten-Export-Schnittstelle           Data Export interface

Perhaps the two most useful entries are Resetaufträge and Rescuesystem. The Resetaufträge page gives you three main options:

``Automatischen Hardware-Reset auslösen`` - Perform an automatic hardware reset.

STRG+ALT+ENTF an den Server senden - Send a CTRL+ALT+DEL signal to the server

Manuellen Hardware-Reset beauftragen - Request a member of the Hetzner staff manually reboot your server.

There is a warning with this last one which translates as:

Please note that manual Hardware-Resets only during our business hours, Monday through Friday 6:30-22:45 pm, Saturday 10-17 hours delay Edited. Outside of business hours, you can Robot menu under "support requests" our 24-h-Rufbereitschaft contact. Also available in the Guide for support operations valuable information.

I’m not sure if there is a charge for the manual reset.

The Rescuesystem sets up a config file for 5 minutes so that if you server reboots it will boot over the network using DHCP into a Hetzner-specific rescue system as long as you have a modern machine (mine was bought in November 2007 and works perfectly). The message translates as:

When activating the rescue system is a DHCP server on our configuration file. When rebooted your server will be booted from the network grabs this configuration file for the rescue system and loads a minimal base system from our TFTP. You can rescue the system will use as long as you need it. The order for the rescue system remains 5 minutes activated. If you then reboot your server will return your usual system of hard.

Caution:

Whether your server about the rescue system can boot depends on whether the network card on the server network is set to boot. This is only the latest in servers as a default by us so. If it is still not set, the server after activating the rescue system at the next reboot with the existing system from the hard disks. Should your server will be converted, then send an e-mail to support@hetzner.de or if you know where your server is equal to the appropriate data center. Indicate whether the change immediately, or at any time any of us can be carried out or by appointment only. The conversion is associated with down-time of about 5 minutes. We ask for your understanding if it in the handling of the changeover contracts to small delays can occur.

You have to choose whether to use the 32bit or 64bit system and then when you clcik the Aktivieren button the rescue system config is set up and you are given a password you’ll need to login then if you reboot your server within 5 mins you will be booted in to the rescue system. Very handy.

It is well worth reading the help files (in this case run through Google translate) for more information about the Hetzner setup.

Checking the Stats

Here are some stats showing what a fresh setup looks like:

Debian-40-etch-64-minimal:~# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda2             365G  520M  346G   1% /
tmpfs                 2.0G     0  2.0G   0% /lib/init/rw
udev                   10M   36K   10M   1% /dev
tmpfs                 2.0G     0  2.0G   0% /dev/shm
Debian-40-etch-64-minimal:~# cat /etc/issue
Debian GNU/Linux 4.0 \n \l

Debian-40-etch-64-minimal:~# uname -a
Linux Debian-40-etch-64-minimal 2.6.18-5-amd64 #1 SMP Tue Oct 2 20:37:02 UTC 2007 x86_64 GNU/Linux
Debian-40-etch-64-minimal:~# free -m
             total       used       free     shared    buffers     cached
Mem:          3926         73       3853          0         12         19
-/+ buffers/cache:         41       3885
Swap:         2055          0       2055

These commands show I’m using Debian 4.0 with a 364Gb hard disk on an AMD 64 machine and that I have 3853Mb of free RAM, using only 73Mb in total.

Re-Installing The Operating System

The first time I tried to setup the server with Xen it all went horribly wrong. This is because Xen expects Grub to be present but the default Hetzner Etch AMD64 image comes with Lilo. I tried removing lilo and setting up grub manually but to no avail although I did learn a lot about Grub as a result of my experiments and can recommend this excellent guide to grub.

Following the instructions in the previous section I initialed the rescue system, rebooted and then used SSH to connect. Since this isn’t the same install you get an error from your SSH client until you remove the existing host from the known hosts file on your local machine:

james@dirac:~$ ssh root@doppler.3aims.com
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
50:10:6b:5f:dc:e7:45:17:73:00:d0:50:f0:0e:48:be.
Please contact your system administrator.
Add correct host key in /home/james/.ssh/known_hosts to get rid of this message.
Offending key in /home/james/.ssh/known_hosts:1
RSA host key for doppler.3aims.com has changed and you have requested strict checking.
Host key verification failed.

Sign in as root with the password you got after clicking Aktivieren. Once you are in you see this:

Linux rescue 2.6.22.2 #2 SMP Tue Aug 28 09:28:15 CEST 2007 x86_64

------------------------------------------------------------------

  Welcome to the Hetzner Rescue System.

  This Rescue System is based on Debian 4.0 (etch) with a newer
  kernel. You can install software like in a normal system.

  To install a new operating system from one of our prebuilt
  images, run 'installimage' and follow the instructions.

  For more information take a look at http://wiki.hetzner.de

------------------------------------------------------------------

root@rescue ~ #

I ran the install script installimage choosing 64bit Debian 4.0 Etch and then editing the following settings in the config file:

FORMATDRIVE2 = 1
This sets up the second hard drive so you can actually use it.
BOOTLOADER = grub
This sets up the bootloader to use grub so that you can install Xen.

When you’re done the install sets to work:

        Hetzner Online AG - installimage


#~ server will be installed now. this will take a few minutes.
#~ you can abort at any time with CTRL+C ..
#~ ( init) ~ reading vars...                            [ OK ]
#~ ( 1/11) ~ deleting partitions...                     [ OK ]
#~ ( 2/11) ~ creating partitions and fstab...           [ OK ]
#~ ( 3/11) ~ formatting partitions...                   [ OK ]
#~ ( 4/11) ~ mounting partitions...                     [ OK ]
#~ ( 5/11) ~ extracting imagefile from local...         [ OK ]
#~ ( 6/11) ~ setting up network config for eth0...      [ OK ]
#~ ( 7/11) ~ chrooting some commands...                 [ OK ]
#~ ( 8/11) ~ clearing logfiles...                       [ OK ]
#~ ( 9/11) ~ setting up some files...                   [ OK ]
#~ (10/11) ~ setting up rootpassword...                 [ OK ]
#~ (11/11) ~ setting up bootloader grub...              [ OK ]


#~~~ INSTALLATION COMPLETE ~~~#
you may now reboot into your new system
you can login to your new system with the same
password as you logged in into the rescue system


root@rescue ~ #

When you type reboot the server reboots back into a new Debian Etch install, this time using Grub and with the second hard disk available.

Installing Xen

Now that we have grub set up, installing Xen is as simple as entering two commands:

apt-get install xen-linux-system-2.6.18-4-xen-amd64
reboot

The OS will then reboot into the Xen DomU. You’ll probably want the 5 free IP addresses Hetzner offer so that each Xen virtual machine can have its own IP address. You can request them from the Support-Anfragen section of the control panel. Choose the Subnetze für DS2000/DS3000/DS5000/DS7000/DS8000/DS9000 beantragen option.

According to this article about Xen on Hetzner you cannot use bridging on Hetzner. Instead you have to use routing via DomU.

Edit /etc/xen/xend-config.sxp so that it only contains these lines:

# -*- sh -*-
(network-script network-route)
(vif-script vif-route)

Restart xend:

/etc/init.d/xend restart

According to this page you will also need to run this command:

echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp

Xen is now setup ready for you to create some images.

Checking the Stats Again

Here are some stats showing what the new Xen setup looks like:

Debian-40-etch-64-minimal:~# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda2             365G  612M  346G   1% /
tmpfs                 1.7G     0  1.7G   0% /lib/init/rw
udev                   10M   36K   10M   1% /dev
tmpfs                 1.7G     0  1.7G   0% /dev/shm
Debian-40-etch-64-minimal:~#  cat /etc/issue
Debian GNU/Linux 4.0 \n \l

Debian-40-etch-64-minimal:~# uname -a
Linux Debian-40-etch-64-minimal 2.6.18-4-xen-amd64 #1 SMP Fri May 4 02:40:51 UTC  2007 x86_64 GNU/Linux
Debian-40-etch-64-minimal:~# free -m
             total       used       free     shared    buffers     cached
Mem:          3366        200       3165          0          1         15
-/+ buffers/cache:        182       3183
Swap:         2055          0       2055
Debian-40-etch-64-minimal:~# fdisk -l

Disk /dev/sda: 400.0 GB, 400088457216 bytes
255 heads, 63 sectors/track, 48641 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1               1         262     2104514+  82  Linux swap / Solaris
/dev/sda2             263       48641   388604317+  83  Linux

Disk /dev/sdb: 400.0 GB, 400088457216 bytes
255 heads, 63 sectors/track, 48641 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System

As you can see, using Xen takes a bit more memory but it doesn’t look like the second disk has any paritions or has been formatted by the Hetzner install after all.

Mounting the Other Hard Disk

Let’s create a partition:

Debian-40-etch-64-minimal:~# fdisk -u /dev/sdb

The number of cylinders for this disk is set to 48641.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
   (e.g., DOS FDISK, OS/2 FDISK)

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First sector (63-781422767, default 63):
Using default value 63
Last sector or +size or +sizeM or +sizeK (63-781422767, default 781422767):
Using default value 781422767

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

And then format it using an ext3 filesystem:

Debian-40-etch-64-minimal:~# /sbin/mkfs -t ext3 /dev/sdb1
mke2fs 1.40-WIP (14-Nov-2006)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
48840704 inodes, 97677838 blocks
4883891 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=4294967296
2981 block groups
32768 blocks per group, 32768 fragments per group
16384 inodes per group
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968

Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 37 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.

Add this line to /etc/fstab:

/dev/sdb1 /mount/sdb1 ext3 defaults 0 0

Then mount the partition:

mkdir /mount
mkdir /mount/sdb1
mount /dev/sdb1

Checking the stats again we have:

Debian-40-etch-64-minimal:~# fdisk -l

Disk /dev/sda: 400.0 GB, 400088457216 bytes
255 heads, 63 sectors/track, 48641 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1               1         262     2104514+  82  Linux swap / Solaris
/dev/sda2             263       48641   388604317+  83  Linux

Disk /dev/sdb: 400.0 GB, 400088457216 bytes
255 heads, 63 sectors/track, 48641 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1       48642   390711352+  83  Linux
Debian-40-etch-64-minimal:~# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda2             365G  612M  346G   1% /
tmpfs                 1.7G     0  1.7G   0% /lib/init/rw
udev                   10M   40K   10M   1% /dev
tmpfs                 1.7G     0  1.7G   0% /dev/shm
/dev/sdb1             367G  195M  348G   1% /mount/sdb1

Much better, 674Gb free space.

Setting up Domain and Host Names

All my machines have hostnames named after famous Physicists so this one is doppler.3aims.com named after Christian Doppler. I set up its DNS entries through the DynDNS control panel as follows:

doppler.3aims.com.  1440  A   78.46.35.5

Then I SSH’d into the machine, set a new root password and changed /etc/hostname to doppler and replaced the line after localhost with this in /etc/hosts:

78.46.35.5 doppler doppler.3aims.com

You then run hostname doppler to save yourself a reboot. More info on etch hostnames here:

Debian-40-etch-64-minimal:~# vim /etc/hostname
Debian-40-etch-64-minimal:~# vim /etc/hosts
Debian-40-etch-64-minimal:~# hostname doppler

All good so far.

Basic Configuration

Rather than doing everything as root it is best to add a normal user account and grant sudo privileges:

Debian-40-etch-64-minimal:~# apt-get install sudo
Debian-40-etch-64-minimal:~# adduser james
Adding user `james' ...
Adding new group `james' (1000) ...
Adding new user `james' (1000) with group `james' ...
Creating home directory `/home/james' ...
Copying files from `/etc/skel' ...
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Changing the user information for james
Enter the new value, or press ENTER for the default
        Full Name []: James Gardner
        Room Number []:
        Work Phone []:
        Home Phone []:
        Other []:
Is the information correct? [y/N] y

You can then grant privileges with the visudo command and at the end of the file add james   ALL=(ALL) ALL then become james with su james.

Now you can become james with su james. Notice that the Bash prompt will now pick up the hostname change:

Debian-40-etch-64-minimal:~# su james
james@doppler:/root$

Locales

The first thing to set up are locales before you install any extra packages:

$ sudo dpkg-reconfigure locales

I chose en_GB.UTF-8 UTF-8 and also left en_US.ISO-8859-15 ISO-8859-15 selected too, choosing en_GB.UTF-8 UTF-8 as the default.

Timezones

The default setup has the German timezone. Lets change that to UTC:

james@doppler:/root$ sudo tzconfig
Your current time zone is set to Europe/Berlin
Do you want to change that? [n]: y

Please enter the number of the geographic area in which you live:


        1) Africa                       7) Australia

        2) America                      <img src='http://jimmyg.org/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> Europe

        3) US time zones                9) Indian Ocean

        4) Canada time zones            10) Pacific Ocean

        5) Asia                         11) Use System V style time zones

        6) Atlantic Ocean               12) None of the above


Then you will be shown a list of cities which represent the time zone
in which they are located. You should choose a city in your time zone.

Number: 8

Amsterdam Andorra Athens Belfast Belgrade Berlin Bratislava Brussels
Bucharest Budapest Chisinau Copenhagen Dublin Gibraltar Guernsey Helsinki
Isle_of_Man Istanbul Jersey Kaliningrad Kiev Lisbon Ljubljana London
Luxembourg Madrid Malta Mariehamn Minsk Monaco Moscow Nicosia Oslo Paris
Podgorica Prague Riga Rome Samara San_Marino Sarajevo Simferopol Skopje
Sofia Stockholm Tallinn Tirane Tiraspol Uzhgorod Vaduz Vatican Vienna
Vilnius Volgograd Warsaw Zagreb Zaporozhye Zurich

Please enter the name of one of these cities or zones
You just need to type enough letters to resolve ambiguities
Press Enter to view all of them again
Name: [] London
Your default time zone is set to 'Europe/London'.
Local time is now:      Fri Nov  9 16:53:52 GMT 2007.
Universal Time is now:  Fri Nov  9 16:53:52 UTC 2007.

SSH Config

Next we’ll change the default SSH configuration to make it more secure:

Make a backup of /etc/ssh/sshd_config and then check or change the following:

Port 30000         <-- change to a port other than 22
PermitRootLogin no
AllowUsers james

These are self-explainatory. This will disable root logins, allow only the user james to login, only on port 30000. If you like you can also set:

PasswordAuthentication no

This will mean you will only be able to login via an SSH private/public key pair which you will have needed to set up in advance. I didn’t do this.

Note that if you get them wrong you might not be able to login to the machine so be careful. Once you happy with the settings restart:

doppler:~# /etc/init.d/ssh restart
Restarting OpenBSD Secure Shell server: sshd.

Don’t exit that shell though before you’ve loaded up another terminal and checked you can connect again. This time you’ll need to use this:

ssh james@doppler.3aims.com -p 30000

If you do make a mistake and can’t reconnect, boot into the rescue system and mount the drive with this command:

mount /dev/sda2 /mnt -t ext3

You will then be able to edit the file as /mnt/etc/ssh/sshd_config and then reboot back into your normal setup.

Also, publishing the settings you’ve chosen on a blog like this defeats the purposes of setting them so choose something different if you are going to publish them!

Firewall

You set up the firewall walls using iptables. This can’t be done using sudo so you have to become the root user:

james@doppler:~$ sudo -i
Password:
doppler:~# whoami
root

You can see the firwall rules like this:

doppler:~# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

If there were any rule you could save them like this:

iptables-save > /etc/iptables.current.rules

Here’s a simple firewall configuration from the Slicehost Blog which you can use to block all access apart from on SSH, HTTP and HTTPS. Save this as /etc/iptables.test.rules. Feel free to modify it for your own use and be aware that if you have didn’t change the SSH port to 30000 or you chose another port, you’ll need to update the firewall config before you apply it.

Now load the rules with:

iptables-restore < /etc/iptables.test.rules

Again, test that you can still sign in using SSH before you exit the shell.

If you list the rules again you will see this:

doppler:~# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     0    --  anywhere             anywhere
REJECT     0    --  anywhere             loopback/8          reject-with icmp-port-unreachable
ACCEPT     0    --  anywhere             anywhere            state RELATED,ESTABLISHED
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:www
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:https
ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:30000
ACCEPT     icmp --  anywhere             anywhere            icmp echo-request
LOG        0    --  anywhere             anywhere            limit: avg 5/min burst 5 LOG level debug prefix `iptables denied: '
REJECT     0    --  anywhere             anywhere            reject-with icmp-port-unreachable

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
REJECT     0    --  anywhere             anywhere            reject-with icmp-port-unreachable

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     0    --  anywhere             anywhere

Once you are happy with the rules, save them permanently:

iptables-save > /etc/iptables.up.rules

Now we need to ensure that the iptables rules are applied when we reboot the server. At the moment, the changes will be lost and it will go back to allowing everything from everywhere.

Edit /etc/network/interfaces and add a pre-up line (shown below) just after iface lo inet loopback:

...
auto lo
iface lo inet loopback
pre-up iptables-restore < /etc/iptables.up.rules
...

This line will restore the iptables rules from the /etc/iptables.up.rules file.

Updating

Next I installed any updates from the repositories listed in /etc/apt/sources.list:

sudo apt-get update
sudo apt-get upgrade

perl-base was the only package upgraded. After I’d made all these changes I rebooted to ensure they were all applied.

That’s as far as I can get until I recieve the new IP addresses. Might be some updates to the above if I run into any problems.

Note

Now you can create your virtual machines. See my previous article for how to do this. Start reading from the xen-create-image line.

HP LaserJet 1022 Printer Debian Etch

Posted in Debian, Hardware by thejimmyg on the November 1st, 2007

I bought the HP LaserJet 1022 for £139 from PC world today. Not exactly cheap I know but I wanted a decent reliable printer to replace my melted Samsung ML-1610 which always gave slightly grey prints. The HP 1022 does exactly what it says on the tin. It produces nice quality black and white prints very quickly.

The OpenPrinting page here suggests it works perfectly with Linux. It works perfectly now with Debian Etch but just following the Gnome CUPS wizard didn’t do it. In playing around I performed the following and but I’m not sure which step was the one that made it work.

  • Used the standard Gnome add printer wizard (gnome-cups-add) which auto-detected the printer and suggested the foo2zjs driver.
  • Installed sudo apt-get install foo2zjs. Not sure why it why it wasn’t already installed since I’d selected it in the wizzard.
  • Plugged it into a USB 2.0 plug rather than 1.1
  • Visited http://localhost:631/printers/ and clicked "Print Test Page"

It then printed the CUPS test page and still works fine even when connected to a USB 1.1 port. It still won’t print a test page from the Gnome CUPS manager though but prints from anywhere else so it is possible it was working straight away anyway before I started trying other things.

Anyway, bottom line is that it seems to work perfectly on Debian Etch so you can buy with confidence.

Audit Tables in PostgreSQL with Debian

Posted in Debian, PostgreSQL by thejimmyg on the October 9th, 2007

In many computer systems it is very important to be able to log every change made to the database for audit purposes. One way of doing this is in PostgreSQL is with an audit table, an audit function and some triggers.

The solution described here was originally proposed by Lorenzo Alberton so all credit for solving this problem goes to him. This entry is nothing more than an extension to his ideas. One drawback with the approcah described is that tables that are logged can only have one primary key whose name must be 30 charcters or less and whose value must be 40 characters or less. You can change the size limits by altering the audit table definition. As long as you can live with these constraints the solution described here works really well. Lorenzo’s solution also crashes if you try to save any value in any table which uses an akward character like , this version doesn’t because it properly quotes the values it logs.

First of all you’ll need to install the PL/TCL language used by PostgreSQL. We need this because apparantly it is not possible to create the trigger to get the old and new values of a field using PostgreSQL’s PL/SQL language (see email thread here although I’m not really convinced):

sudo apt-get install postgresql-pltcl-8.1

This will also install TCL 8.4 which you