<?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>George MacKerron: code blog &#187; System admin</title>
	<atom:link href="http://blog.mackerron.com/category/system-admin/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.mackerron.com</link>
	<description>GIS, software development, and other snippets</description>
	<lastBuildDate>Fri, 03 Feb 2012 18:35:21 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>MySQL gem for Ruby 1.9.1/1.9.2 on Snow Leopard (Mac OS X 10.6)</title>
		<link>http://blog.mackerron.com/2011/08/04/mysql-gem-snow-leopard/</link>
		<comments>http://blog.mackerron.com/2011/08/04/mysql-gem-snow-leopard/#comments</comments>
		<pubDate>Thu, 04 Aug 2011 14:47:11 +0000</pubDate>
		<dc:creator>George</dc:creator>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[System admin]]></category>

		<guid isPermaLink="false">http://blog.mackerron.com/?p=844</guid>
		<description><![CDATA[The secret to getting the MySQL gem to install and function with Ruby 1.9.1/1.9.2 on Snow Leopard is: Install MySQL using the 64-bit .DMG package installer from dev.mysql.com Install Ruby using RVM (that&#8217;s Ruby 1.9.2 or 1.9.1-p378 &#8212; at the time of writing the latest 1.9.1, p429, is buggy) Add these to lines to ~/.bash_login [...]]]></description>
			<content:encoded><![CDATA[<p><strong>The secret to getting the MySQL gem to install and function with Ruby 1.9.1/1.9.2 on Snow Leopard is:</strong></p>


<ul>
<li>Install MySQL using the 64-bit .DMG package installer from <a href="http://dev.mysql.com/downloads/mysql/">dev.mysql.com</a></li>
<li>Install Ruby using <a href="http://redmine.ruby-lang.org/issues/show/2404"><span class="caps">RVM</span></a> (that&#8217;s Ruby 1.9.2 or 1.9.1-p378 &#8212; at the time of writing the latest 1.9.1, p429, is <a href="http://redmine.ruby-lang.org/issues/show/2404">buggy</a>)</li>
<li>Add these to lines to <code>~/.bash_login</code> or <code>~/.bashrc</code>:</li>
</ul>




<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">PATH</span>=<span style="color: #ff0000;">&quot;/usr/local/mysql/bin:<span style="color: #007800;">$PATH</span>&quot;</span>
<span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">DYLD_LIBRARY_PATH</span>=<span style="color: #ff0000;">&quot;/usr/local/mysql/lib:<span style="color: #007800;">$DYLD_LIBRARY_PATH</span>&quot;</span></pre></div></div>





<ul>
<li>In a new shell (Terminal window), type <code>gem install mysql</code> as normal.</li>
</ul>



<p>I&#8217;m posting this mainly as a record for myself, having wasted a lot of time in the past trying strange incantations from comments on various other blogs posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.mackerron.com/2011/08/04/mysql-gem-snow-leopard/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blocking the weakest passwords</title>
		<link>http://blog.mackerron.com/2010/12/14/death-to-weak-passwords/</link>
		<comments>http://blog.mackerron.com/2010/12/14/death-to-weak-passwords/#comments</comments>
		<pubDate>Tue, 14 Dec 2010 12:24:04 +0000</pubDate>
		<dc:creator>George</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[System admin]]></category>
		<category><![CDATA[Web design]]></category>

		<guid isPermaLink="false">http://blog.mackerron.com/?p=429</guid>
		<description><![CDATA[The recent Gawker passwords leak once again highlights the widespread use of passwords that offer essentially no security. Some years ago, when working on a secure web app for a large organisation &#8212; let&#8217;s call them Secret Testing Ltd &#8212; I was keen that people shouldn&#8217;t choose hopelessly weak passwords. I was particularly concerned by [...]]]></description>
			<content:encoded><![CDATA[<p>The recent <a href="http://gawker.com/5712615/commenting-accounts-compromised-++-change-your-passwords">Gawker passwords leak</a> once again highlights the widespread use of passwords that offer essentially no security.</p>

<p>Some years ago, when working on a secure web app for a large organisation &#8212; let&#8217;s call them Secret Testing Ltd &#8212; I was keen that people shouldn&#8217;t choose hopelessly weak passwords. I was particularly concerned by my sysadmin colleague&#8217;s fondness for passwords of the form &#8216;p/\55w0rd&#8217; or &#8216;S3cr3t-T35t|ng&#8217;.</p>

<p><span id="more-429"></span></p>

<p>I therefore wrote some simple Ruby code to try to catch very weak passwords:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> PasswordUtils
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">look_and_sound_alikes</span><span style="color:#006600; font-weight:bold;">&#40;</span>original<span style="color:#006600; font-weight:bold;">&#41;</span>
    look_or_sound_alikes = <span style="color:#006600; font-weight:bold;">&#123;</span> \
      <span style="color:#996600;">'0'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'o'</span><span style="color:#006600; font-weight:bold;">&#93;</span> ,
      <span style="color:#996600;">'1'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'i'</span>, <span style="color:#996600;">'l'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'2'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'to'</span>, <span style="color:#996600;">'too'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'3'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'e'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'4'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'a'</span>, <span style="color:#996600;">'for'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'5'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'s'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'6'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'g'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'8'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'b'</span>, <span style="color:#996600;">'ate'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'9'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'g'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'i'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'i'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'$'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'s'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'|'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'i'</span>, <span style="color:#996600;">'l'</span>, <span style="color:#996600;">''</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'!'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'i'</span>, <span style="color:#996600;">'l'</span>, <span style="color:#996600;">''</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'@'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'g'</span>, <span style="color:#996600;">'a'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'('</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'c'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'['</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'c'</span>, <span style="color:#996600;">'e'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'{'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'e'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'&amp;'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'and'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'*'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'star'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">')'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'d'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'^'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'a'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'/'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'a'</span>, <span style="color:#996600;">'v'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'<span style="color:#000099;">\\</span>'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">''</span><span style="color:#006600; font-weight:bold;">&#93;</span>,
      <span style="color:#996600;">'&lt;'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'k'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#006600; font-weight:bold;">&#125;</span> 
    <span style="color:#008000; font-style:italic;"># the penultimate two substitutions catch /\ (A) and \/ (V), albeit without</span>
    <span style="color:#008000; font-style:italic;"># distinguishing them, and the last (in conjunction with the empty options </span>
    <span style="color:#008000; font-style:italic;"># for ! and |) catches !&lt; and |&lt; (K)</span>
    versions = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">''</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    original.<span style="color:#9900CC;">downcase</span>.<span style="color:#9900CC;">each_char</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>c<span style="color:#006600; font-weight:bold;">|</span>
      versions.<span style="color:#9900CC;">collect</span>! <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>v<span style="color:#006600; font-weight:bold;">|</span>
        alikes = look_or_sound_alikes<span style="color:#006600; font-weight:bold;">&#91;</span>c<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">||</span> <span style="color:#006600; font-weight:bold;">&#91;</span>c<span style="color:#006600; font-weight:bold;">&#93;</span>
        alikes.<span style="color:#9900CC;">collect</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>c1<span style="color:#006600; font-weight:bold;">|</span> v <span style="color:#006600; font-weight:bold;">+</span> c1 <span style="color:#006600; font-weight:bold;">&#125;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
      versions.<span style="color:#9900CC;">flatten</span>!
    <span style="color:#9966CC; font-weight:bold;">end</span>
    versions
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">obvious</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>password, custom_banned_list = <span style="color:#996600;">''</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    standard_banned_list = <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;#{RAILS_ROOT}/config/banned_password_words.txt&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    banned_words = standard_banned_list.<span style="color:#9900CC;">downcase</span>.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>\W<span style="color:#006600; font-weight:bold;">+/</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">+</span> 
      custom_banned_list.<span style="color:#9900CC;">downcase</span>.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>\W<span style="color:#006600; font-weight:bold;">+/</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">delete_if</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>w<span style="color:#006600; font-weight:bold;">|</span> w.<span style="color:#9900CC;">length</span> <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#006666;">4</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
    alike_words = <span style="color:#006600; font-weight:bold;">&#91;</span>password.<span style="color:#9900CC;">downcase</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">+</span> PasswordUtils.<span style="color:#9900CC;">look_and_sound_alikes</span><span style="color:#006600; font-weight:bold;">&#40;</span>password<span style="color:#006600; font-weight:bold;">&#41;</span>
    banned_words.<span style="color:#9900CC;">any</span>? <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>banned_word<span style="color:#006600; font-weight:bold;">|</span>
      alike_words.<span style="color:#9900CC;">any</span>? <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>alike_word<span style="color:#006600; font-weight:bold;">|</span> alike_word.<span style="color:#9966CC; font-weight:bold;">include</span>? banned_word <span style="color:#006600; font-weight:bold;">&#125;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>




<p>The first method of the class undoes some common substitutions:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&gt;</span> PasswordUtils.<span style="color:#9900CC;">look_and_sound_alikes</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'p/<span style="color:#000099;">\5</span>5w0rd'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;password&quot;</span>, <span style="color:#996600;">&quot;pvssword&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
<span style="color:#006600; font-weight:bold;">&gt;</span>  PasswordUtils.<span style="color:#9900CC;">look_and_sound_alikes</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'S3cr3t-T35t|ng'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;secret-testing&quot;</span>, <span style="color:#996600;">&quot;secret-testlng&quot;</span>, <span style="color:#996600;">&quot;secret-testng&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span></pre></div></div>




<p>And the second method uses this in conjunction with a list of banned words to check that an entered password isn&#8217;t hopelessly weak.</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&gt;</span> PasswordUtils.<span style="color:#9900CC;">obvious</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'p/<span style="color:#000099;">\5</span>5w0rd'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>
<span style="color:#006600; font-weight:bold;">&gt;</span>  PasswordUtils.<span style="color:#9900CC;">obvious</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'S3cr3t-T35t|ng'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>
<span style="color:#006600; font-weight:bold;">&gt;</span> PasswordUtils.<span style="color:#9900CC;">obvious</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'gkAsd76!o'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">false</span></pre></div></div>




<p>Obviously, you need a good banned words list &#8212; perhaps starting with some <a href="http://www.buzzfeed.com/gavon/top-25-gawker-passwords">top N passwords lists</a>, and including the name of your company, the web app, and words related to the area of business, local pubs, and so on.</p>

<p>It&#8217;s also a good idea to include custom banned words for individual users. For example:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">custom_banned_list = <span style="color:#996600;">&quot;#{first_names} #{surname} #{department} #{organisation} #{email}&quot;</span>
PasswordUtils.<span style="color:#9900CC;">password_obvious</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>password, custom_banned_list<span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>




<p>Passing these tests isn&#8217;t a sufficient condition for ruling out a weak password, but it&#8217;s arguably a necessary one, and a good start.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.mackerron.com/2010/12/14/death-to-weak-passwords/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Growling Mac backups with rsync</title>
		<link>http://blog.mackerron.com/2009/08/01/growling-backups/</link>
		<comments>http://blog.mackerron.com/2009/08/01/growling-backups/#comments</comments>
		<pubDate>Sat, 01 Aug 2009 11:40:01 +0000</pubDate>
		<dc:creator>George</dc:creator>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[System admin]]></category>

		<guid isPermaLink="false">http://blog.mackerron.com/?p=68</guid>
		<description><![CDATA[Between Time Machine and services like Dropbox, paranoid levels of backup are surprisingly painless to achieve on the Mac these days. Still, just one more copy of your data, in just one more continent, surely can&#8217;t do any harm, right? One that won&#8217;t burn down with your house, but also isn&#8217;t just wafting vaguely in [...]]]></description>
			<content:encoded><![CDATA[<p>Between <a href="http://www.apple.com/macosx/what-is-macosx/time-machine.html">Time Machine</a> and services like <a href="http://www.getdropbox.com/">Dropbox</a>, paranoid levels of backup are surprisingly painless to achieve on the Mac these days. </p>

<p>Still, just one more copy of your data, in just one more continent, surely can&#8217;t do any harm, right? One that won&#8217;t burn down with your house, but also isn&#8217;t just wafting vaguely in the Cloud at someone else&#8217;s whim. One that elevates your backup system from sensibly paranoid to borderline <span class="caps">OCD.</span> One, in this case, brought to you by rsync, find and Growl.</p>

<p><span id="more-68"></span></p>

<h3>What it does</h3>

<p>This script does the following:</p>


<ul>
<li>recursive, incremental, remote backup of the contents of folders you choose</li>
<li>safely archiving anything that changed since last time</li>
<li>and excluding things by name or folder (all this is just <code>rsync</code> so far)</li>
<li>and also excluding anything unfeasibly big (this is down to <code>find</code>)</li>
<li>all the while using Growl to keep you apprised of the situation, as exemplified below (thanks to <code>growlnotify</code>).</li>
</ul>



<p><img src="http://blog.mackerron.com/wp-content/uploads/2009/07/Picture-24.png" alt="Growling backup error screenshot" /></p>

<p>On the remote server, you end up with a file structure as below, with your current files under <em>Current</em> and any files that have moved, changed, or been deleted in a dated folder under <em>Archive</em>:</p>

<p><img src="http://blog.mackerron.com/wp-content/uploads/2009/07/Picture-26.png" alt="Backups screenshot" /></p>

<p><img src="http://blog.mackerron.com/wp-content/uploads/2009/07/Picture-25.png" alt="Backups screenshot" /></p>

<h3>What you&#8217;ll need</h3>

<p>You&#8217;ll need:</p>


<ul>
<li>a remote backup server you have <code>rsync</code> access to, with (passwordless) public key authentication set up.</li>
<li>Growl installed, obviously, and also <code>growlnotify</code> (by running <code>./install.sh</code> in the Extras folder on the Growl installation .dmg).</li>
<li>a way to schedule the script to run &#8212; iCal, <code>cron</code>, or <code>launchd</code> (for the management of which last I recommend <a href="http://tuppis.com/lingon/">Lingon</a>).</li>
</ul>



<h3>The script</h3>

<p>There&#8217;s some rather superstitious quoting. Even then, it&#8217;ll probably still bite you in case of spaces.</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: #666666; font-style: italic;"># --- Set backup parameters ---</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># What local files/folders are we backing up?</span>
<span style="color: #007800;">SRC</span>=<span style="color: #ff0000;">&quot;/Users/gjm06/Development /Users/gjm06/Documents /Users/gjm06/Sites&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># What server are we backing up to?</span>
<span style="color: #007800;">DESTSERVER</span>=<span style="color: #ff0000;">&quot;george.example.com&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># What's our user name on the server?</span>
<span style="color: #007800;">SSHUSER</span>=<span style="color: #ff0000;">&quot;george&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># What's the remote shell command for this server </span>
<span style="color: #666666; font-style: italic;"># (slight obscurity/security by avoiding port 22)</span>
<span style="color: #007800;">RSH</span>=<span style="color: #ff0000;">&quot;ssh -p 2244&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># What location on the server shall we back up to?</span>
<span style="color: #007800;">DESTPATH</span>=<span style="color: #ff0000;">&quot;/home/george/backups&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Any non-valuable stuff to exclude by name/location?</span>
<span style="color: #007800;">EXCLUDE</span>=<span style="color: #ff0000;">&quot;.DS_Store,.svn/,.Trash/,tmp/,log/,vendor/&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Exclude things that are *how* big? </span>
<span style="color: #666666; font-style: italic;"># e.g. I don't want GBs of virtual machines going over the wire</span>
<span style="color: #666666; font-style: italic;"># (NB. this is in bytes)</span>
<span style="color: #007800;">MAXFILESIZE</span>=<span style="color: #000000;">100000</span>
&nbsp;
&nbsp;
<span style="color: #666666; font-style: italic;"># --- Set Growl parameters ---</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># What will this script be called in the Growl prefpane?</span>
<span style="color: #007800;">GROWLNAME</span>=<span style="color: #ff0000;">&quot;Remote backup script&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># And what app's icon will appear in Growl notifications?</span>
<span style="color: #007800;">APPICON</span>=<span style="color: #ff0000;">&quot;Time Machine&quot;</span>
&nbsp;
&nbsp;
<span style="color: #666666; font-style: italic;"># --- Do it! ---</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">echo</span> Checking not already running 
&nbsp;
<span style="color: #007800;">PROCS</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">ps</span> <span style="color: #660033;">-A</span> <span style="color: #660033;">-o</span> <span style="color: #ff0000;">&quot;pid=,command=&quot;</span><span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #007800;">MYNAME</span>=<span style="color: #ff0000;">&quot;$0&quot;</span>
<span style="color: #007800;">MYBASENAME</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">basename</span> <span style="color: #007800;">$MYNAME</span><span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #007800;">MYPID</span>=<span style="color: #007800;">$$</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># The next line works like so:</span>
<span style="color: #666666; font-style: italic;"># * take the process list (for all users),</span>
<span style="color: #666666; font-style: italic;"># * filter *in* processes named like this script (making sure we're on word boundaries),</span>
<span style="color: #666666; font-style: italic;"># * filter *out* (-v) the one that *is* this script (by PID), and finally</span>
<span style="color: #666666; font-style: italic;"># * filter *out* the grep commands themselves.</span>
&nbsp;
<span style="color: #007800;">MERUNNING</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$PROCS</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-E</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;\b<span style="color: #007800;">$MYBASENAME</span>\b&quot;</span> \
  <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-E</span> <span style="color: #660033;">-v</span> <span style="color: #ff0000;">&quot;\b<span style="color: #007800;">$MYPID</span>\b&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-v</span> <span style="color: #c20cb9; font-weight: bold;">grep</span><span style="color: #000000; font-weight: bold;">`</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Then, if anything's left (i.e. MERUNNING isn't a zero-length string...)</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;">-z</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$MERUNNING</span>&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
  <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>growlnotify <span style="color: #660033;">--name</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$GROWLNAME</span>&quot;</span> <span style="color: #660033;">--appIcon</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$APPICON</span>&quot;</span> \
    <span style="color: #660033;">--message</span> <span style="color: #ff0000;">&quot;Another backup seems to be in progress&quot;</span> \
    <span style="color: #ff0000;">&quot;Ignoring scheduled backup&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;
&nbsp;
<span style="color: #7a0874; font-weight: bold;">echo</span> Finding large files to exclude...
&nbsp;
<span style="color: #007800;">OVERSIZELIST</span>=<span style="color: #ff0000;">&quot;/tmp/files_over_backup_limit&quot;</span>
<span style="color: #c20cb9; font-weight: bold;">find</span> <span style="color: #007800;">$SRC</span> <span style="color: #660033;">-size</span> +<span style="color: #007800;">$MAXFILESIZE</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #007800;">$OVERSIZELIST</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># If you ever want to know what's excluded -- and you should! -- just do</span>
<span style="color: #666666; font-style: italic;"># a 'cat /tmp/files_over_backup_limit' in the Terminal</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Next, 'wc -l' counts the *lines* in our oversize list, and we extract </span>
<span style="color: #666666; font-style: italic;"># just the number from the output</span>
&nbsp;
<span style="color: #007800;">NUMOVERSIZE</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">wc</span> <span style="color: #660033;">-l</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$OVERSIZELIST</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-o</span> <span style="color: #660033;">-E</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>0123456789<span style="color: #7a0874; font-weight: bold;">&#93;</span>+<span style="color: #000000; font-weight: bold;">`</span>
&nbsp;
&nbsp;
<span style="color: #7a0874; font-weight: bold;">echo</span> Rsyncing...
&nbsp;
<span style="color: #666666; font-style: italic;"># date makes up the name for our archive folders, while</span>
<span style="color: #666666; font-style: italic;"># eval is used to invoke shell expansion on the list of file names to exclude,</span>
<span style="color: #666666; font-style: italic;"># turning them into a list of --exclude= statements</span>
&nbsp;
<span style="color: #007800;">BDATE</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">date</span> <span style="color: #ff0000;">&quot;+%y_%m_%d-%H.%M.%S&quot;</span><span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #007800;">EXPEXCLUDES</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #7a0874; font-weight: bold;">eval</span> <span style="color: #ff0000;">&quot;echo --exclude={<span style="color: #007800;">$EXCLUDE</span>} &quot;</span><span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #007800;">ERRORS</span>=<span style="color: #ff0000;">&quot;/tmp/rsync_backup_errors&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># The &amp;&amp; and || operators give us a simple way to respond to zero and </span>
<span style="color: #666666; font-style: italic;"># non-zero (= error) rsync exit codes, thanks to lazy evaluation by the shell</span>
&nbsp;
rsync <span style="color: #660033;">--rsh</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$RSH</span>&quot;</span> \
  <span style="color: #660033;">--recursive</span> <span style="color: #660033;">--partial</span> <span style="color: #660033;">--delete</span> <span style="color: #660033;">--delete-excluded</span> \
  <span style="color: #660033;">--links</span> <span style="color: #660033;">--times</span> <span style="color: #660033;">--relative</span> <span style="color: #660033;">--compress</span> \
  <span style="color: #660033;">--backup</span> <span style="color: #660033;">--backup-dir</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$DESTPATH</span>/Archive/<span style="color: #007800;">$BDATE</span>/&quot;</span> \
  <span style="color: #660033;">--exclude-from</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$OVERSIZELIST</span>&quot;</span> \
  <span style="color: #007800;">$EXPEXCLUDES</span> \
  <span style="color: #007800;">$SRC</span> \
  <span style="color: #007800;">$SSHUSER</span><span style="color: #000000; font-weight: bold;">@</span><span style="color: #007800;">$DESTSERVER</span>:<span style="color: #ff0000;">&quot;<span style="color: #007800;">$DESTPATH</span>/Current/&quot;</span> \
  <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #ff0000;">&quot;<span style="color: #007800;">$ERRORS</span>&quot;</span> \
<span style="color: #000000; font-weight: bold;">&amp;&amp;</span> 
<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>growlnotify <span style="color: #660033;">--name</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$GROWLNAME</span>&quot;</span> <span style="color: #660033;">--appIcon</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$APPICON</span>&quot;</span> \
  <span style="color: #660033;">--message</span> <span style="color: #ff0000;">&quot;Backed up to <span style="color: #007800;">$DESTSERVER</span>, <span style="color: #007800;">$NUMOVERSIZE</span> oversized files excluded&quot;</span> \
  <span style="color: #ff0000;">&quot;Completed backup&quot;</span> \
<span style="color: #000000; font-weight: bold;">||</span> \
<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>growlnotify <span style="color: #660033;">--name</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$GROWLNAME</span>&quot;</span> <span style="color: #660033;">--appIcon</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$APPICON</span>&quot;</span> <span style="color: #660033;">-s</span> \
  <span style="color: #660033;">--message</span> <span style="color: #ff0000;">&quot;<span style="color: #780078;">`cat &quot;$ERRORS&quot;`</span>&quot;</span> \
  <span style="color: #ff0000;">&quot;Failed backup&quot;</span></pre></div></div>




<p>Hope it&#8217;s useful in your own paranoid backup endeavours. And, by the way, if you ever hear me say &#8220;surely a simple Bash script couldn&#8217;t take <em>that</em> long&#8221;, please don&#8217;t stop reminding me just how much I hate Bash until I change my mind.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.mackerron.com/2009/08/01/growling-backups/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iPhone + public key SSH authentication: lovely</title>
		<link>http://blog.mackerron.com/2009/05/28/iphone-public-key-ssh/</link>
		<comments>http://blog.mackerron.com/2009/05/28/iphone-public-key-ssh/#comments</comments>
		<pubDate>Thu, 28 May 2009 13:03:20 +0000</pubDate>
		<dc:creator>George</dc:creator>
				<category><![CDATA[System admin]]></category>

		<guid isPermaLink="false">http://blog.mackerron.com/?p=53</guid>
		<description><![CDATA[I&#8217;ve been unhappy for a while having the SSH daemon on my web server VPSs with password authentication enabled. Of course, it&#8217;s on a non-standard port, blocks root logins, and takes a strong-ish password&#8230; but the risk of a successful dictionary attack has still felt too non-zero for comfort. Equally, though, I&#8217;ve not wanted to [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been unhappy for a while having the <span class="caps">SSH </span>daemon on my web server <span class="caps">VPS</span>s with password authentication enabled. Of course, it&#8217;s on a non-standard port, blocks root logins, and takes a strong-ish password&#8230; but the risk of a successful dictionary attack has still felt too non-zero for comfort.</p>

<p>Equally, though, I&#8217;ve not wanted to give up the ability to log in to the servers from anywhere to fix things in an emergency, so I didn&#8217;t want to turn password authentication off and rely on public keys alone.</p>

<p>Until now, that is. I realised yesterday that, since I have iSSH on the iPhone, which does public key authentication, I <em>can</em> log into my servers from anywhere, even with password authentication turned off. Granted, doing anything serious on a tiny screen and slow connection is difficult. But all I actually need to be able to do from there is temporarily turn password authentication back on.</p>

<p>And to make this easy, I&#8217;ve put two ultra-simple scripts in ~/bin:</p>

<p><strong>pwd_login_on.sh</strong></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>
<span style="color: #c20cb9; font-weight: bold;">sudo</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/^PasswordAuthentication no$/PasswordAuthentication yes/'</span> \
  -i.previous <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>ssh<span style="color: #000000; font-weight: bold;">/</span>sshd_config
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>init.d<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">ssh</span> restart</pre></div></div>




<p><strong>pwd_login_off.sh</strong></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>
<span style="color: #c20cb9; font-weight: bold;">sudo</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/^PasswordAuthentication yes$/PasswordAuthentication no/'</span> \
  -i.previous <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>ssh<span style="color: #000000; font-weight: bold;">/</span>sshd_config
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>init.d<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">ssh</span> restart</pre></div></div>




<p>(These paths are suitable for Ubuntu 8.04).</p>

<p>Lovely.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.mackerron.com/2009/05/28/iphone-public-key-ssh/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
<!-- This Quick Cache file was built for (  blog.mackerron.com/category/system-admin/feed/ ) in 0.59454 seconds, on Feb 5th, 2012 at 3:01 am UTC. -->
<!-- This Quick Cache file will automatically expire ( and be re-built automatically ) on Feb 5th, 2012 at 4:01 am UTC -->
