<?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>John&#039;s Tidbits &#187; Sysadmin</title>
	<atom:link href="http://inodes.org/category/sysadmin/feed/" rel="self" type="application/rss+xml" />
	<link>http://inodes.org</link>
	<description>Moo - Development, Trouble-shooting and Random thoughts...</description>
	<lastBuildDate>Thu, 19 Apr 2012 10:15:45 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.1</generator>
		<item>
		<title>Careful what you call your server!</title>
		<link>http://inodes.org/2010/03/01/careful-what-you-call-your-server/</link>
		<comments>http://inodes.org/2010/03/01/careful-what-you-call-your-server/#comments</comments>
		<pubDate>Mon, 01 Mar 2010 00:09:19 +0000</pubDate>
		<dc:creator>johnf</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[kvm]]></category>
		<category><![CDATA[lvm]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[virtialisation]]></category>

		<guid isPermaLink="false">http://inodes.org/?p=236</guid>
		<description><![CDATA[I was setting up a server recently and I was using KVM to virtualise a whole lot of hosts. Being fairly unimaginative I decided to call the machine kvm. As usual I used LVM for the disks. Now on Ubuntu this means that by default the VG will be called the same as the host [...]]]></description>
			<content:encoded><![CDATA[<p>I was setting up a server recently and I was using KVM to virtualise a whole lot of hosts. Being fairly unimaginative I decided to call the machine kvm. As usual I used LVM for the disks. Now on Ubuntu this means that by default the VG will be called the same as the host name. This means the root LV will appear on the system as <strong>/dev/kvm/root</strong>.</p>
<p>When they KVM modules are loaded, they try and create a device called <strong>/dev/kvm</strong>. This fails pretty miserably since <strong>/dev/kvm</strong> is already a directory due to LVM shenanigans.</p>
<p>Not all is lost though if you&#8217;ve done a lot of setup like I had. You can rename VGs. Simply boot from your Ubuntu install CD, choose rescue mode and then jump into a shell. First you deactivate the LVs using</p>
<pre>
vgchange -a n
</pre>
<p>then you can rename the VG using</p>
<pre>
vgrename kvm kvmvg
</pre>
<p>Not sure whether I should file this problem as a bug. It is a bit of a weird situation.</p>
]]></content:encoded>
			<wfw:commentRss>http://inodes.org/2010/03/01/careful-what-you-call-your-server/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>rm -rf /usr/lib</title>
		<link>http://inodes.org/2009/09/15/rm-rf-usrlib/</link>
		<comments>http://inodes.org/2009/09/15/rm-rf-usrlib/#comments</comments>
		<pubDate>Tue, 15 Sep 2009 04:06:55 +0000</pubDate>
		<dc:creator>johnf</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[rm updatedb recovery backups]]></category>

		<guid isPermaLink="false">http://inodes.org/blog/?p=198</guid>
		<description><![CDATA[So in another case of tab completion gone wrong I ended up staring at the following on my laptop. johnf@zoot:~/dev/vquence/metrics/trunk$ sudo rm -rf /usr/lib ^C The command only ran for a few seconds so the damage wasn&#8217;t to bad, but what did I lose? The locate command came to my rescue. locate runs out of [...]]]></description>
			<content:encoded><![CDATA[<p>So in another case of tab completion gone wrong I ended up staring at the following on my laptop.</p>
<pre>
johnf@zoot:~/dev/vquence/metrics/trunk$ sudo rm -rf /usr/lib
^C
</pre>
<p>The command only ran for a few seconds so the damage wasn&#8217;t to bad, but what did I lose?</p>
<p>The <strong>locate</strong> command came to my rescue. locate runs out of cron, usually once a day, and creates a database with a list of every file on your machine. You can then use it to search for files. So to work out what was missing I did the following.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># Get the list of files before we removed them</span>
<span style="color: #c20cb9; font-weight: bold;">locate</span> <span style="color: #660033;">--regexp</span> <span style="color: #ff0000;">'.'</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span>before_rm
&nbsp;
<span style="color: #666666; font-style: italic;"># update the locate database</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">updatedb</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Get the list of current files on the system</span>
<span style="color: #c20cb9; font-weight: bold;">locate</span> <span style="color: #660033;">--regexp</span> <span style="color: #ff0000;">'.'</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span>after_rm
&nbsp;
<span style="color: #666666; font-style: italic;"># Create a list of what's missing</span>
<span style="color: #c20cb9; font-weight: bold;">diff</span> <span style="color: #660033;">-u</span> <span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span>before_rm <span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span>after_rm <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span>diff_rm
<span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #ff0000;">'^-'</span> <span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span>diff_rm <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/^-//'</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span>missing_rm
&nbsp;
<span style="color: #666666; font-style: italic;"># Ask the dpkg system what packages those files belong to</span>
<span style="color: #000000; font-weight: bold;">for</span> i <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span>missing_rm<span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #000000; font-weight: bold;">do</span>
    <span style="color: #c20cb9; font-weight: bold;">dpkg</span> <span style="color: #660033;">-S</span> <span style="color: #007800;">$i</span>;
<span style="color: #000000; font-weight: bold;">done</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">awk</span> <span style="color: #ff0000;">'{print $1}'</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/:$//;s/,//g'</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span>packages
&nbsp;
<span style="color: #666666; font-style: italic;"># Reinstall those packages</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">aptitude</span> reinstall <span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span>packages<span style="color: #000000; font-weight: bold;">`</span></pre></div></div>

<p>After this process it is probably worth running the step from updatedb again to work out what is still missing.</p>
<p>For the record I lost 102 files and had to reinstall 97 packages.</p>
<p>Now back to real work!</p>
]]></content:encoded>
			<wfw:commentRss>http://inodes.org/2009/09/15/rm-rf-usrlib/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Building a Private PPA on Ubuntu</title>
		<link>http://inodes.org/2009/09/14/building-a-private-ppa-on-ubuntu/</link>
		<comments>http://inodes.org/2009/09/14/building-a-private-ppa-on-ubuntu/#comments</comments>
		<pubDate>Mon, 14 Sep 2009 06:59:12 +0000</pubDate>
		<dc:creator>johnf</dc:creator>
				<category><![CDATA[FOSS]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[ppa]]></category>
		<category><![CDATA[rebuildd]]></category>
		<category><![CDATA[reprepro]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://inodes.org/blog/?p=189</guid>
		<description><![CDATA[One of the things I love about the Ubuntu project and launchpad is the Personal Package Archive. PPAs make it so simple and easy to backport packages. The only problem with PPAs is that they are public. I had a need to be able to host some private internal packages as well as squid with [...]]]></description>
			<content:encoded><![CDATA[<p>One of the things I love about the Ubuntu project and launchpad is the Personal Package Archive. PPAs make it so simple and easy to backport packages. The only problem with PPAs is that they are public. I had a need to be able to host some private internal packages as well as squid with SSL support, which you can&#8217;t distribute in binary form due to licensing restrictions.</p>
<p>Basically I wanted to create the equivalent of an Ubuntu PPA service running on our own servers so we could place it behind our firewall. This post is basically the process I followed to integrate <a href="http://julien.danjou.info/rebuildd/">rebuilld</a> and <a href="http://mirrorer.alioth.debian.org/">reprepro</a> to replicate a PPA setup.</p>
<p>So first up install reprepro</p>
<pre>
aptitude install reprepro
</pre>
<p>next we need do create a reprepro repository</p>
<pre>
mkdir -p /srv/reprepro/{conf,incoming,incomingtmp}
</pre>
<p>Now we need to tell reprepro which distributions we care about. Create /srv/reprepro/conf/distributions with the following contents</p>
<pre>
Suite: hardy
Version: 8.04
Codename: hardy
Architectures: i386 amd64 source
Components: main
Description: Local Hardy
SignWith: repository@inodes.org
DebIndices: Packages Release . .gz .bz2
DscIndices: Sources Release .gz .bz2
Tracking: all includechanges keepsources
Log: logfile
  --changes /srv/reprepro/bin/build_sources

Suite: intrepid
Version: 8.10
Codename: intrepid
Architectures: i386 amd64 source
Components: main
Description: Local Intrepid
SignWith: repository@inodes.org
DebIndices: Packages Release . .gz .bz2
DscIndices: Sources Release .gz .bz2
Tracking: all includechanges keepsources
Log: logfile
  --changes /srv/reprepro/bin/build_sources

Suite: jaunty
Version: 9.04
Codename: jaunty
Architectures: i386 amd64 source
Components: main
Description: Local Jaunty
SignWith: repository@inodes.org
DebIndices: Packages Release . .gz .bz2
DscIndices: Sources Release .gz .bz2
Tracking: all includechanges keepsources
Log: logfile
  --changes /srv/reprepro/bin/build_sources
</pre>
<p>I also like to create reprepro options file to setup some defaults, edit /srv/reprepro/conf/options</p>
<pre>
verbose
verbose
verbose
verbose
verbose
</pre>
<p>Next we need to setup an incoming queue so that we can use dput to get the source packages into reprepro,<br />
vi /srv/reprepro/conf/incoming</p>
<pre>
Name: incoming
IncomingDir: incoming
Allow: hardy intrepid jaunty
Cleanup: on_deny on_error
Tempdir: incomingtmp
</pre>
<p>The repository is now ready to go. So now we can setup apache. Edit /etc/apache/sites-enabled/pppa</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;">&lt;<span style="color: #000000; font-weight:bold;">virtualhost</span> *:<span style="color: #ff0000;">80</span>&gt;
    <span style="color: #00007f;">ServerName</span> packages.inodes.org
    <span style="color: #00007f;">DocumentRoot</span> /srv/reprepro
&lt;/<span style="color: #000000; font-weight:bold;">virtualhost</span>&gt;</pre></div></div>

<p>and we should also configure our sources.list to use these repositories, edit /etc/apt/sources.list</p>
<pre>
# Sources for rebuildd
deb-src http://packages.inodes.org hardy main
deb-src http://packages.inodes.org intrepid main
deb-src http://packages.inodes.org jaunty main
</pre>
<p>Next we want to setup our dput.cf to make the magic happen to get the source packages into the archive, edit ~/.dput.cf</p>
<pre>
[DEFAULT]
default_host_main = notspecified

[local]
fqdn = localhost
method = local
incoming = /srv/reprepro/incoming
allow_unsigned_uploads = 0
run_dinstall = 0
post_upload_command = reprepro -V -b /srv/reprepro processincoming incoming
</pre>
<p>So now we can do the following</p>
<pre>
apt-get source squid3
cd squid3*
dch -i # increment version number
dpkg-buildpackage -sa -S
cd ..
dput local *changes
aptitude update
apt-get source squid3
</pre>
<p>So when you run dput, first it copies the source package files to /srv/reprepro/incoming and then it gets reprepro to process it&#8217;s incoming queue. This means that the source package is now sitting in the repository.<br />
So the second apt-get source should have downloaded the source package from our local repository which is exactly what rebuildd will do before it tries to build it.</p>
<p>Next step is to setup rebuildd so that it builds the binary packages and installs them into the repository.</p>
<pre>
aptitude install rebuildd
</pre>
<p>Setup so it runs out of init.d and the releases we care about, edit /etc/default/rebuildd</p>
<pre>
START_REBUILDD=1
START_REBUILDD_HTTPD=1
DISTS="hardy intrepid jaunty"
</pre>
<p>Now when a source package is uploaded into the repository we want to kick off rebuildd to build the package. We can do this through the reprepro log hooks. You&#8217;ll notice in the conf/distributions above the following lines.</p>
<pre>
Log: logfile
  --changes /srv/reprepro/bin/build_sources
</pre>
<p>This script will be run any time a .changes file is added to the repository. Create /srv/reprepro/bin/build_sources</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
&nbsp;
<span style="color: #007800;">action</span>=<span style="color: #007800;">$1</span>
<span style="color: #007800;">release</span>=<span style="color: #007800;">$2</span>
<span style="color: #007800;">package</span>=<span style="color: #007800;">$3</span>
<span style="color: #007800;">version</span>=<span style="color: #007800;">$4</span>
<span style="color: #007800;">changes_file</span>=<span style="color: #007800;">$5</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Only care about packages being added</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$action</span>&quot;</span> <span style="color: #000000; font-weight: bold;">!</span>= <span style="color: #ff0000;">&quot;accepted&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #000000; font-weight: bold;">then</span>
	<span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">0</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Only care about source packages</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$changes_file</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-q</span> _source.changes
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$?</span> = <span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #000000; font-weight: bold;">then</span>
	<span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">0</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Kick off the job</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$package</span> <span style="color: #007800;">$version</span> 1 <span style="color: #007800;">$release</span>&quot;</span>  <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sudo</span> rebuildd-job add</pre></div></div>

<p>This script basically checks the right type of package is being added. Then it calls <strong>rebuildd-job</strong> to ask for that specific package and version to be built for that Ubuntu release.</p>
<p>Now the first thing that rebuildd does is download the source for the package. However we need to update the sources first since our server doesn&#8217;t know there are new files in the repository yet. So edit /etc/rebuildd/rebuilddrv an change</p>
<pre>
apt-get -q --download-only -t ${d} source ${p}=${v}
</pre>
<p>to</p>
<pre>
source_cmd = /srv/reprepro/bin/get_sources ${d} ${p} ${v}
</pre>
<p>and create /srv/reprepro/bin/get_sources with</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
&nbsp;
<span style="color: #007800;">d</span>=<span style="color: #007800;">$1</span>
<span style="color: #007800;">p</span>=<span style="color: #007800;">$2</span>
<span style="color: #007800;">v</span>=<span style="color: #007800;">$3</span>
&nbsp;
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">aptitude</span> update <span style="color: #000000; font-weight: bold;">&gt;/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null
<span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #660033;">-q</span> <span style="color: #660033;">--download-only</span> <span style="color: #660033;">-t</span> <span style="color: #800000;">${d}</span> <span style="color: #7a0874; font-weight: bold;">source</span> <span style="color: #800000;">${p}</span>=<span style="color: #800000;">${v}</span></pre></div></div>

<p>By this stage we have rebuildd building packages but we need to make sure they get re-injected back into the repository. We can do this with a post script. Edit /etc/rebuildd/rebuilddrc</p>
<pre>
post_build_cmd = /srv/reprepro/bin/upload_binaries ${d} ${p} ${v} ${a}
</pre>
<p>and create /srv/reprepro/bin/upload_binaries</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
&nbsp;
<span style="color: #007800;">d</span>=<span style="color: #007800;">$1</span>
<span style="color: #007800;">p</span>=<span style="color: #007800;">$2</span>
<span style="color: #007800;">v</span>=<span style="color: #007800;">$3</span>
<span style="color: #007800;">a</span>=<span style="color: #007800;">$4</span>
&nbsp;
<span style="color: #c20cb9; font-weight: bold;">su</span> <span style="color: #660033;">-l</span> <span style="color: #660033;">-c</span> <span style="color: #ff0000;">&quot;reprepro -V -b /srv/reprepro include <span style="color: #007800;">${d}</span> /var/cache/pbuilder/result/<span style="color: #007800;">${p}</span>_<span style="color: #007800;">${v}</span>_<span style="color: #007800;">${a}</span>.changes&quot;</span> johnf</pre></div></div>

<p>Now the su is in there because rebuildd needs to be able to access the GPG passphrase to sign the repository with. So rather than have a passphrase-less key we make sure that gpg-agent is running by adding the following to your .profile.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #660033;">-f</span> <span style="color: #007800;">$HOME</span><span style="color: #000000; font-weight: bold;">/</span>.gpg-agent-info <span style="color: #000000; font-weight: bold;">&amp;&amp;</span>    <span style="color: #c20cb9; font-weight: bold;">kill</span> <span style="color: #660033;">-0</span> <span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">cut</span> -d: <span style="color: #660033;">-f</span> <span style="color: #000000;">2</span> <span style="color: #007800;">$HOME</span><span style="color: #000000; font-weight: bold;">/</span>.gpg-agent-info<span style="color: #000000; font-weight: bold;">`</span> <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null; <span style="color: #000000; font-weight: bold;">then</span>
	<span style="color: #007800;">GPG_AGENT_INFO</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #007800;">$HOME</span><span style="color: #000000; font-weight: bold;">/</span>.gpg-agent-info<span style="color: #000000; font-weight: bold;">`</span>
	<span style="color: #7a0874; font-weight: bold;">export</span> GPG_AGENT_INFO
<span style="color: #000000; font-weight: bold;">else</span>
	<span style="color: #7a0874; font-weight: bold;">eval</span> <span style="color: #000000; font-weight: bold;">`</span>gpg-agent --daemon<span style="color: #000000; font-weight: bold;">`</span>
	<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$GPG_AGENT_INFO</span> <span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #007800;">$HOME</span><span style="color: #000000; font-weight: bold;">/</span>.gpg-agent-info
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #007800;">GPG_TTY</span>=<span style="color: #000000; font-weight: bold;">`</span>tty<span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #7a0874; font-weight: bold;">export</span> GPG_TTY</pre></div></div>

<p>So that&#8217;s it you now have your own personal PPA. Just in case you had fallen asleep. Here is a little script I wrote so you can auto build the source packages for each release you care about in one go.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">set</span> <span style="color: #660033;">-e</span>
&nbsp;
<span style="color: #007800;">RELEASES</span>=<span style="color: #ff0000;">&quot;hardy intrepid jaunty&quot;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-f</span> debian<span style="color: #000000; font-weight: bold;">/</span>changelog <span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #000000; font-weight: bold;">then</span>
	<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;This isn't a debian repo&quot;</span>
	<span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Check for changes</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">`</span>bzr st <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">wc</span> -l<span style="color: #000000; font-weight: bold;">`</span> <span style="color: #000000; font-weight: bold;">!</span>= <span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #000000; font-weight: bold;">then</span>
	<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;You have uncommitted changes!&quot;</span>
	<span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-d</span> ..<span style="color: #000000; font-weight: bold;">/</span>tmpbuild <span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #000000; font-weight: bold;">then</span>
	<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;The tmpbuild dir exists&quot;</span>
	<span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
bzr <span style="color: #7a0874; font-weight: bold;">export</span> ..<span style="color: #000000; font-weight: bold;">/</span>tmpbuild
<span style="color: #c20cb9; font-weight: bold;">cp</span> debian<span style="color: #000000; font-weight: bold;">/</span>changelog ..<span style="color: #000000; font-weight: bold;">/</span>tmpbuild.changelog
<span style="color: #7a0874; font-weight: bold;">cd</span> ..<span style="color: #000000; font-weight: bold;">/</span>tmpbuild
&nbsp;
<span style="color: #007800;">PACKAGE</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">head</span> <span style="color: #660033;">-1</span> debian<span style="color: #000000; font-weight: bold;">/</span>changelog <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">awk</span> <span style="color: #ff0000;">'{print $1}'</span><span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #007800;">VERSION</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">head</span> <span style="color: #660033;">-1</span> debian<span style="color: #000000; font-weight: bold;">/</span>changelog <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">awk</span> <span style="color: #ff0000;">'{print $2}'</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-r</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/^\(//;s/\)$//'</span><span style="color: #000000; font-weight: bold;">`</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">for</span> release <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #007800;">$RELEASES</span>
<span style="color: #000000; font-weight: bold;">do</span>
&nbsp;
	<span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-r</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;1s/\) [^;]+; /~<span style="color: #007800;">${release}</span>) <span style="color: #007800;">${release}</span>; /&quot;</span> ..<span style="color: #000000; font-weight: bold;">/</span>tmpbuild.changelog <span style="color: #000000; font-weight: bold;">&gt;</span> debian<span style="color: #000000; font-weight: bold;">/</span>changelog 
	<span style="color: #c20cb9; font-weight: bold;">head</span> <span style="color: #660033;">-1</span> debian<span style="color: #000000; font-weight: bold;">/</span>changelog
	dpkg-buildpackage <span style="color: #660033;">-S</span> <span style="color: #660033;">-sa</span>
	dput <span style="color: #7a0874; font-weight: bold;">local</span> ..<span style="color: #000000; font-weight: bold;">/</span><span style="color: #800000;">${PACKAGE}</span>_<span style="color: #800000;">${VERSION}</span>~<span style="color: #800000;">${release}</span>_source.changes
<span style="color: #000000; font-weight: bold;">done</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">cd</span> ..
<span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #660033;">-rf</span> tmpbuild</pre></div></div>

<p>So the above documentation is a bit of a brain dump on what I&#8217;ve been working on for the past 2 days and I&#8217;m sure I&#8217;ve left some bits out. So please give me any feedback you have in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://inodes.org/2009/09/14/building-a-private-ppa-on-ubuntu/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Linux Australia SysAdmin Day Gift</title>
		<link>http://inodes.org/2009/08/01/linux-australia-sysadmin-day-gift/</link>
		<comments>http://inodes.org/2009/08/01/linux-australia-sysadmin-day-gift/#comments</comments>
		<pubDate>Sat, 01 Aug 2009 10:19:20 +0000</pubDate>
		<dc:creator>johnf</dc:creator>
				<category><![CDATA[FOSS]]></category>
		<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[la]]></category>
		<category><![CDATA[linux australia]]></category>
		<category><![CDATA[sysadminday]]></category>
		<category><![CDATA[thinkgeek]]></category>

		<guid isPermaLink="false">http://inodes.org/blog/?p=153</guid>
		<description><![CDATA[I would like to send out a big thank you to the Linux Australia Council. As I&#8217;m sure you all know yesterday was System Administrator Appreciation Day. The Council decided to send me a ThinkGeek gift certificate in appreciation for my work as an LA Admin. After hours of searching I finally decided on the [...]]]></description>
			<content:encoded><![CDATA[<p>I would like to send out a big thank you to the <a href="http://linux.org.au/About/Council">Linux Australia Council</a>. As I&#8217;m sure you all know yesterday was <a href="http://sysadminday.com">System Administrator Appreciation Day</a>. The Council decided to send me a <a href="http://thinkgeek.com">ThinkGeek</a> gift certificate in appreciation for my work as an LA Admin.</p>
<p>After hours of searching I finally decided on the <a href="http://www.thinkgeek.com/computing/usb-gadgets/a7ea/">USB SATA Drive Dock</a> <img src='http://inodes.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p><img alt="" src="http://www.thinkgeek.com/images/products/front/a7ea_sata_dual_drive-dock.jpg" title="SATA Dual Drive Dock" class="alignnone" width="220" height="230" /></p>
<p>Again a big thank you to the LA council and to Steve Walsh for organising the gift certificate.</p>
]]></content:encoded>
			<wfw:commentRss>http://inodes.org/2009/08/01/linux-australia-sysadmin-day-gift/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Melbourne Cup Dip2</title>
		<link>http://inodes.org/2008/11/04/melbourne-cup-dip2/</link>
		<comments>http://inodes.org/2008/11/04/melbourne-cup-dip2/#comments</comments>
		<pubDate>Tue, 04 Nov 2008 07:08:11 +0000</pubDate>
		<dc:creator>johnf</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[Bulletproof]]></category>
		<category><![CDATA[cup]]></category>
		<category><![CDATA[melbounre]]></category>
		<category><![CDATA[networking]]></category>

		<guid isPermaLink="false">http://inodes.org/blog/?p=80</guid>
		<description><![CDATA[To quote Justaan: This is what we call the Melbourne Cup Network Effect It seems it really is the race that stops the nation. This is a graph of Bulletproof&#8217;s outbound web traffic for today. That&#8217;s a 37% drop in outbound traffic just after 3pm. Make sure you take note of my l33t gimp skills!]]></description>
			<content:encoded><![CDATA[<p>To quote Justaan:</p>
<blockquote><p>This is what we call the Melbourne Cup Network Effect</p></blockquote>
<p><img title="mel_cup" src="http://inodes.org/blog/wp-content/uploads/2008/11/mel_cup.png" alt="Melbourne Cup network effect" width="500" height="236" /></p>
<p>It seems it really is the race that stops the nation. This is a graph of Bulletproof&#8217;s outbound web traffic for today. That&#8217;s a 37% drop in outbound traffic just after 3pm.</p>
<p>Make sure you take note of my l33t gimp skills!</p>
]]></content:encoded>
			<wfw:commentRss>http://inodes.org/2008/11/04/melbourne-cup-dip2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hardy, exim4, SMTP-AUTH and LDAP&#8230; (or debian openssl causes pain)</title>
		<link>http://inodes.org/2008/05/15/hardy-exim4-smtp-auth-and-ldap-or-debian-openssl-causes-pain/</link>
		<comments>http://inodes.org/2008/05/15/hardy-exim4-smtp-auth-and-ldap-or-debian-openssl-causes-pain/#comments</comments>
		<pubDate>Thu, 15 May 2008 00:33:42 +0000</pubDate>
		<dc:creator>johnf</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[auth]]></category>
		<category><![CDATA[edgy]]></category>
		<category><![CDATA[exim]]></category>
		<category><![CDATA[hardy]]></category>
		<category><![CDATA[ldap]]></category>
		<category><![CDATA[smtp]]></category>

		<guid isPermaLink="false">http://inodes.org/blog/2008/05/15/hardy-exim4-smtp-auth-and-ldap-or-debian-openssl-causes-pain/</guid>
		<description><![CDATA[As most people will know yesterday caused a lot of people a lot of pain as they ran around replacing SSH keys and SSL certificates. While running around fixing up all our servers, most of them in one felll swoop thanks to puppet, I realised two of our servers were still running Edgy. I figured [...]]]></description>
			<content:encoded><![CDATA[<p>As most people will know yesterday caused a lot of people a lot of pain as they ran around replacing SSH keys and SSL certificates.</p>
<p>While running around fixing up all our servers, most of them in one felll swoop thanks to puppet, I realised two of our servers were still running Edgy. I figured it was high time I moved them to Hardy.</p>
<p>Everything went fairly smoothly with some minor hicups, except for SMTP-AUTH for exim. We use an ldap backed SMTP-AUTH and this just wouldn&#8217;t work after the upgrade. The following error was appearing in the logs.</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">ldap_search failed: -7, Bad search filter</pre></div></div>

<p>This lead to hours upon hours of google searches, staring at debug messages and even at one stage resorting to using GDB. Eventually after staring at debug messages harder it twigged when I saw the following.</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">perform_ldap_search: ldapdn URL = &quot;ldap:///ou=people,o=vquence?dn?sub?(uid=moo) &quot;</pre></div></div>

<p>Notice the space just before the closing double quote. It seems that the new openldap libraries don&#8217;t like errant spaces in your search filter.</p>
<p>Now to remember what I was doing yesterday morning before this whole derailment began.</p>
<p>Note: Before anyone comments I will completely deny that during these upgrades I did anything as silly as <strong>rm -rf `dpkg -L random-font-package`</strong>, no matter what twitter says.</p>
]]></content:encoded>
			<wfw:commentRss>http://inodes.org/2008/05/15/hardy-exim4-smtp-auth-and-ldap-or-debian-openssl-causes-pain/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hardy and password locking</title>
		<link>http://inodes.org/2008/04/29/hardy-and-password-locking/</link>
		<comments>http://inodes.org/2008/04/29/hardy-and-password-locking/#comments</comments>
		<pubDate>Tue, 29 Apr 2008 06:32:02 +0000</pubDate>
		<dc:creator>johnf</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[expiry]]></category>
		<category><![CDATA[gutsy]]></category>
		<category><![CDATA[hardy]]></category>
		<category><![CDATA[lock]]></category>
		<category><![CDATA[passwd]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://inodes.org/blog/2008/04/29/hardy-and-password-locking/</guid>
		<description><![CDATA[passwd -l root In gutsy the above would simply lock the account by placing an ! in front of the passwd in your /etc/shadow file. In hardy it now also sets the account as expired. Meaning you can&#8217;t ssh to it even if you have SSH keys in place. Time to go and rebuild my [...]]]></description>
			<content:encoded><![CDATA[
<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">passwd</span> <span style="color: #660033;">-l</span> root</pre></div></div>

<p>In gutsy the above would simply lock the account by placing an ! in front of the passwd in your /etc/shadow file. </p>
<p>In hardy it now also sets the account as expired. Meaning you can&#8217;t ssh to it even if you have SSH keys in place.</p>
<p>Time to go and rebuild my EC2 AMI. <img src='http://inodes.org/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<p></p>
<p><strong>Update:</strong> To get the old behavour back you can do the following</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">passwd -l root
usermod -e &quot;&quot; root</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://inodes.org/2008/04/29/hardy-and-password-locking/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Puppet, Facts and Certificates</title>
		<link>http://inodes.org/2008/03/13/puppet-facts-and-certificates/</link>
		<comments>http://inodes.org/2008/03/13/puppet-facts-and-certificates/#comments</comments>
		<pubDate>Thu, 13 Mar 2008 03:14:16 +0000</pubDate>
		<dc:creator>johnf</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[bugfix]]></category>
		<category><![CDATA[ec2]]></category>
		<category><![CDATA[puppet]]></category>
		<category><![CDATA[vquence]]></category>

		<guid isPermaLink="false">http://inodes.org/blog/2008/03/13/puppet-facts-and-certificates/</guid>
		<description><![CDATA[I&#8217;m currently setting up Puppet at Vquence so that, among other things, we can deploy hosts into Amazon EC2 more easily. To ensure a minimum setup time on a new server I wanted the setup to be as simple as echo &#8216;DAEMON_OPTS=&#8221;-w 120 &#8211;fqdn newserver.vquence.com &#8211;server puppetmaster.vquence.com&#8221; > /etc/default/puppet aptitude install puppet This means that [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m currently setting up <a href="http://reductivelabs.com/projects/puppet/">Puppet</a> at Vquence so that, among other things, we can deploy hosts into Amazon EC2 more easily. </p>
<p>To ensure a minimum setup time on a new server I wanted the setup to be as simple as</p>
<ul>
<li> echo &#8216;DAEMON_OPTS=&#8221;-w 120 &#8211;fqdn <strong>newserver.vquence.com</strong> &#8211;server puppetmaster.vquence.com&#8221; > /etc/default/puppet </li>
<li> aptitude install puppet </li>
</ul>
<p>This means that the puppet client will use <strong>newserver.vquence.com</strong> as the common name in the SSL certificate it creates for itself. On the puppet master the SSL cert name is then used to pick a node rather than the hostname reported by facter.</p>
<p>This means that I don&#8217;t need to worry about setting up /etc/hostname, even better /etc/hostname can be managed by puppet.</p>
<p>You can control this functionality on the puppet master by using the node_name option. From the docs</p>
<pre>
    # How the puppetmaster determines the client's identity
    # and sets the 'hostname' fact for use in the manifest, in particular
    # for determining which 'node' statement applies to the client.
    # Possible values are 'cert' (use the subject's CN in the client's
    # certificate) and 'facter' (use the hostname that the client
    # reported in its facts)
    # The default value is 'cert'.
    # node_name = cert
</pre>
<p>The problem was that the &#8216;hostname&#8217; fact wasn&#8217;t being set. It looks like there was a regression in SVN#1673 when some refactoring was performed.</p>
<p>I&#8217;ve filed bug <a href="http://reductivelabs.com/trac/puppet/ticket/1133">#1133</a> and you can clone my git <a href="http://inodes.org/~johnf/git/puppet">repository.</a></p>
<p>I haven&#8217;t included any tests in the patch as I&#8217;m not sure how to. The master.rb test already tests this functionality but doesn&#8217;t test that the facts object has actually been changed. I think a test on <strong>getconfig</strong> is probably required but I&#8217;m not sure how you would access the facts after calling it.</p>
<p><strong>Update:</strong> This patch is now in puppet as of 0.24.3.</p>
]]></content:encoded>
			<wfw:commentRss>http://inodes.org/2008/03/13/puppet-facts-and-certificates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Amazon EC2 ruby gem and large user_data</title>
		<link>http://inodes.org/2008/02/26/amazon-ec2-ruby-gem-and-large-user_data/</link>
		<comments>http://inodes.org/2008/02/26/amazon-ec2-ruby-gem-and-large-user_data/#comments</comments>
		<pubDate>Tue, 26 Feb 2008 01:05:30 +0000</pubDate>
		<dc:creator>johnf</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[ec2]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[vquence]]></category>

		<guid isPermaLink="false">http://inodes.org/blog/2008/02/26/amazon-ec2-ruby-gem-and-large-user_data/</guid>
		<description><![CDATA[When you create an instance in EC2 you can send Amazon some user data that is accessible by your instance. At Vquence we use this to send a script that gets executes at boot up. This script contains some openvpn and puppet RSA keys so its approaching about 10k in size. This works without any [...]]]></description>
			<content:encoded><![CDATA[<p>When you create an instance in EC2 you can send Amazon some user data that is accessible by your instance. At Vquence we use this to send a script that gets executes at boot up. This script contains some openvpn and puppet RSA keys so its approaching about 10k in size.</p>
<p>This works without any problems when using the java based command line tools. However I was getting the following error when using the <a href="http://amazon-ec2.rubyforge.org/">EC2 Ruby GEM</a>. </p>
<pre>
/usr/lib/ruby/1.8/net/protocol.rb:133:in `sysread': Connection reset by peer (Errno::ECONNRESET)
	from /usr/lib/ruby/1.8/net/protocol.rb:133:in `rbuf_fill'
	from /usr/lib/ruby/1.8/timeout.rb:56:in `timeout'
	from /usr/lib/ruby/1.8/timeout.rb:76:in `timeout'
	from /usr/lib/ruby/1.8/net/protocol.rb:132:in `rbuf_fill'
	from /usr/lib/ruby/1.8/net/protocol.rb:116:in `readuntil'
	from /usr/lib/ruby/1.8/net/protocol.rb:126:in `readline'
	from /usr/lib/ruby/1.8/net/http.rb:2020:in `read_status_line'
	from /usr/lib/ruby/1.8/net/http.rb:2009:in `read_new'
	 ... 6 levels...
	from ./lib/ec2helpers.rb:43:in `start_instance'
	from ./ec2-puppet:107
	from ./ec2-puppet:89:in `each_pair'
	from ./ec2-puppet:89
</pre>
<p>Doing some tcpdumping indicated that after receiving the request Amazon waits for a while and then sends a TCP RESET. Not very nice at all. My next step was to use ngrep to compare the output from the command line tools and the ruby gem. This got nowhere fast since the command line tools use the SOAP API while the ruby gem uses the Query API.</p>
<p>What I did notice however is that while the command line tools performed a POST the ruby library performed a GET. At this stage I decided to test how much data I could send. So I started trying different user data sizes. The offending amount was around 7.8k, suspiciously close to exactly 8k.</p>
<p>The <a href="http://www.ietf.org/rfc/rfc2616.txt">HTTP/1.1</a> spec doesn&#8217;t place an actual limit on the length but leaves it up to the server.<br />
<cite><br />
   The HTTP protocol does not place any a priori limit on the length of<br />
   a URI. Servers MUST be able to handle the URI of any resource they<br />
   serve, and SHOULD be able to handle URIs of unbounded length if they<br />
   provide GET-based forms that could generate such URIs. A server<br />
   SHOULD return 414 (Request-URI Too Long) status if a URI is longer<br />
   than the server can handle (see section 10.4.15).<br />
</cite></p>
<p><cite><br />
      Note: Servers ought to be cautious about depending on URI lengths<br />
      above 255 bytes, because some older client or proxy<br />
      implementations might not properly support these lengths.<br />
</cite></p>
<p>Apache for example limits this by default to 8190 bytes including the method and the protocol. You can change this using the <a href="http://httpd.apache.org/docs/2.0/mod/core.html#limitrequestline">LimitRequestLine</a> directive.</p>
<p>I created a patch to modify the EC2 Gem to use a POST instead of a GET which has no such limitations. You can find the git tree for it at http://inodes.org/~johnf/git/amazon-ec2</p>
]]></content:encoded>
			<wfw:commentRss>http://inodes.org/2008/02/26/amazon-ec2-ruby-gem-and-large-user_data/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Squid and Rails caching</title>
		<link>http://inodes.org/2008/01/15/squid-and-rails-caching/</link>
		<comments>http://inodes.org/2008/01/15/squid-and-rails-caching/#comments</comments>
		<pubDate>Tue, 15 Jan 2008 13:04:35 +0000</pubDate>
		<dc:creator>johnf</dc:creator>
				<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[squid]]></category>

		<guid isPermaLink="false">http://inodes.org/blog/2008/01/15/squid-and-rails-caching/</guid>
		<description><![CDATA[At Vquence our Rails setup looks something like this. ------------ --------- ------------ &#124; Internet &#124;---->&#124; Squid &#124;---->&#124; Mongrels &#124; ------------ --------- ------------ (Who needs Inkscape when you have ASCII art) This infrastructure is hosted in the US and up until recently squid hadn&#8217;t been doing much of anything except really sitting there. Now a few [...]]]></description>
			<content:encoded><![CDATA[<p>At Vquence our Rails setup looks something like this.</p>
<pre>
------------     ---------     ------------
| Internet |---->| Squid |---->| Mongrels |
------------     ---------     ------------
</pre>
<p>(Who needs Inkscape when you have ASCII art)</p>
<p>This infrastructure is hosted in the US and up until recently squid hadn&#8217;t been doing much of anything except really sitting there.</p>
<p>Now a few months ago when we signed a contract with an Australian customer we decided we needed to place a squid cache in Australia which would actually cache content. For two reasons, firstly the US is a long way away and the 300ms latency is really noticeable and secondly because some of our pages involving graphs have long statistical calculations which can take minutes to render. (OK its really because no one has had a chance to optimise them yet but lets pretend that&#8217;s not the case). So we changed the above setup for the Australian customers to look like the following.</p>
<pre>
------------     ------------     ------------     ------------
| Internet |---->| Squid AU |---->| Squid US |---->| Mongrels |
------------     ------------     ------------     ------------
</pre>
<p>We hand out urls like http://www.client.b2b.vquence.com/widget to Australian customers and the rails backend is smart enough to make sure all the URLs look similar (I&#8217;ll blog about how I did that another time).</p>
<p>Without much time to look into thing properly I did some really nasty things on the AU squid cache to make sure it cached the pages.</p>
<pre name="code">
refresh_pattern /client/graph  1440    0%    1440    ignore-no-cache ignore-reload
refresh_pattern /client/static 1440    0%    1440    ignore-no-cache ignore-reload
refresh_pattern /client/video  1440    0%    1440    ignore-no-cache ignore-reload
</pre>
<p>This is evil, breaks a whole heap of RFCs but it did the trick and got us out of a bind quickly.</p>
<p>A few weeks ago I moved the production site to Rails 2.0, I noticed around this time that the caching had stopped working. The client was no longer using our services as their campaign had finished so it wasn&#8217;t an urgent concern.</p>
<p>It seems that Rails 2.0 goes one step further to ensure that caches don&#8217;t cache content and instead of just sending</p>
<pre name="code">
Cache-Control: no-cache
</pre>
<p>it now sends</p>
<pre name="code">
Cache-Control: private, max-age=0, must-revalidate
</pre>
<p>I tried adding <b>ignore-private</b>, since if you&#8217;re breaking some aspects of the RFC you may as well break a couple more, but squid still refused to cache the content. After struggling with this for a bit I decided that the universe was trying to tell me I should actually do things properly.</p>
<p>So with squid set back to its defaults I went exploring how to accomplish this. Google wasn&#8217;t all that helpful at first since most Rails caching articles talk about caching to static files as most sites don&#8217;t implement reverse proxying for caching. It turns out however its fairly simple. In the appropriate actions in your controllers simply do the following.</p>
<pre name="code" class="ruby">
class VideoController < ApplicationController

    def vquence
        # Lots of code here

        expires_in 8.hours, :private => false
        render :template => "videos/vquence"
    end

end
</pre>
<p>This will send the following header and cache the page for 8 hours.</p>
<pre name="code">
Cache-Control: max-age=28800
</pre>
<p>Now everything is much faster!!</p>
]]></content:encoded>
			<wfw:commentRss>http://inodes.org/2008/01/15/squid-and-rails-caching/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
