<?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>domi.co.uk</title>
	<atom:link href="http://domi.co.uk/feed/" rel="self" type="application/rss+xml" />
	<link>http://domi.co.uk</link>
	<description></description>
	<lastBuildDate>Sun, 22 Apr 2012 19:26:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>video</title>
		<link>http://domi.co.uk/2012/04/21/video/</link>
		<comments>http://domi.co.uk/2012/04/21/video/#comments</comments>
		<pubDate>Sat, 21 Apr 2012 17:10:35 +0000</pubDate>
		<dc:creator>dom</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://domi.co.uk/?p=560</guid>
		<description><![CDATA[500&#215;281: 640&#215;360:]]></description>
			<content:encoded><![CDATA[<p>500&#215;281:</p>

<iframe src="http://player.vimeo.com/video/40813410?byline=0&amp;portrait=0&amp;color=d24427" width="500" height="281" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>

<p>640&#215;360:</p>

<iframe src="http://player.vimeo.com/video/40813410?color=D24427" width="640" height="360" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>
]]></content:encoded>
			<wfw:commentRss>http://domi.co.uk/2012/04/21/video/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reverse SEO</title>
		<link>http://domi.co.uk/2012/01/11/reverse-seo/</link>
		<comments>http://domi.co.uk/2012/01/11/reverse-seo/#comments</comments>
		<pubDate>Tue, 10 Jan 2012 23:25:54 +0000</pubDate>
		<dc:creator>dom</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[SEO]]></category>

		<guid isPermaLink="false">http://domi.co.uk/?p=551</guid>
		<description><![CDATA[Although it&#8217;s a truism and/or cliché to say that the first rule of SEO is to write good content, it&#8217;s probably also been said somewhere, at least once &#8211; I haven&#8217;t searched for it so I don&#8217;t know &#8211; that thinking about SEO while writing your good content makes it even better. By which I [...]]]></description>
			<content:encoded><![CDATA[<p>Although it&#8217;s a truism and/or cliché to say that the first rule of SEO is to write good content, it&#8217;s probably also been said somewhere, at least once &#8211; I haven&#8217;t <em>searched</em> for it so I don&#8217;t know &#8211; that thinking about SEO while writing your good content makes it even better. By which I mean that if you&#8217;re thinking consciously about the core meaning of the whole piece while writing every sentence, you end up staying more on topic and writing more useful content. Maybe people who actually know about writing already do this? I wouldn&#8217;t know!</p>
]]></content:encoded>
			<wfw:commentRss>http://domi.co.uk/2012/01/11/reverse-seo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Permissions setup for a Debian web host</title>
		<link>http://domi.co.uk/2012/01/09/permissions-setup-for-a-debian-web-host/</link>
		<comments>http://domi.co.uk/2012/01/09/permissions-setup-for-a-debian-web-host/#comments</comments>
		<pubDate>Mon, 09 Jan 2012 17:57:43 +0000</pubDate>
		<dc:creator>dom</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[chgrp]]></category>
		<category><![CDATA[chmod]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[permissions]]></category>
		<category><![CDATA[web development]]></category>

		<guid isPermaLink="false">http://domi.co.uk/?p=545</guid>
		<description><![CDATA[This is another of those &#8220;note-to-self&#8221; posts, where I detail how I&#8217;m setting something up so that I can refer back to it, or so I can point someone else to it. As if often the case, some of this may be Debian-specific&#8230; There are different ways of approaching the task of setting the permissions [...]]]></description>
			<content:encoded><![CDATA[<blockquote>
  <p>This is another of those &#8220;note-to-self&#8221; posts, where I detail how I&#8217;m setting something up so that I can refer back to it, or so I can point someone else to it. As if often the case, some of this may be Debian-specific&#8230;</p>
</blockquote>

<p>There are different ways of approaching the task of setting the permissions for web directories, depending on how many users have access to the server, how many sites are sharing the server, and lots of other concerns. I tend to be in a situation where anyone who has shell access to the server is at a level trusted with web content, so that simplifies the process somewhat. I&#8217;ll look at different levels of dealing with this questions, in increasing levels of security.</p>

<h2>Simplest approach: use the <code>www-data</code> group</h2>

<p>This is the default group that Debian has for web daemons. If you add everyone who can log in to this group, you can then use this group for all web directories that the notional &#8220;web team&#8221; needs to access, and make them &#8220;group writable&#8221;. <strong>Be aware that this configuration also allows the Apache daemon itself to write to the web directories, which is an obvious potential security issue, so you need to be sure that the web applications in there don&#8217;t/won&#8217;t allow that.</strong></p>

<p>You can either specify the group when creating the user:</p>

<pre><code>adduser --ingroup www-data USER
</code></pre>

<p>or add an existing user to the group:</p>

<pre><code>adduser USER www-data
</code></pre>

<h2>Almost as simple as simplest approach: create a <code>webdev</code> group</h2>

<p>This is also a very simple approach, which won&#8217;t allow Apache to write to the web directories, unless you specifically allow it. (This would usually be for cache directories, image upload and so on.)</p>

<p>&#8220;webdev&#8221; is just an arbitrary name, it can be anything you like as long as it doesn&#8217;t exist. First create your new group, then add the user(s) to it:</p>

<pre><code>addgroup webdev
adduser USER webdev
</code></pre>

<p>It goes without saying (or should do) that for the above to work, you also need to allow the right group access to the web directories you need. A simple example of this, making a few assumptions of your directory layout, would be:</p>

<pre><code>chgrp -R webdev /www/www.example.com/htdocs
chmod -R g+w /www/www.example.com/htdocs
</code></pre>

<p>So what did we just do?</p>

<p>First, we recursively (<code>-R</code>) changed the group to be <code>webdev</code> for the <code>htdocs</code> directory. Then, we (also recursively) allowed the group write-access (<code>g+w</code>) on <code>htdocs</code>. Which means: from now on, anyone in the <code>webdev</code> group can create and edit files in <code>htdocs</code> and any of its subdirectories. Note that these lines will stop any previously configured group-access from working (if it&#8217;s a different group from <code>webdev</code>). However, if we have a directory with write-access for everyone (AKA &#8220;<code>chmod 777</code>&#8220;) as is sometimes the case with cache directories, for example, they won&#8217;t be affected.</p>

<p>So, how can we make this more granular?</p>

<h2>Multi-layered approach: create per-site groups</h2>

<p>If we wanted to have some directories writable by all our web team, and others by certain people in certain sub-teams, we can create multiple groups.</p>

<p>Take, for example, two subdomain sites on example.com: foo.example.com and bar.example.com. Of course, these could be different domains, I&#8217;m just sticking with example.com for the, er, examples. We want to deny editing access to the teams working on these two sites to each other&#8217;s site. A solution is to create two groups: <code>webdev-foo</code> and <code>webdev-bar</code>, maybe.</p>

<pre><code>addgroup webdev-foo
addgroup webdev-bar
adduser fooguy webdev-foo
adduser foogal webdev-foo
adduser barboy webdev-bar
chgrp -R webdev-foo /www/foo.example.com/htdocs
chgrp -R webdev-bar /www/bar.example.com/htdocs
chmod -R g+w /www/foo.example.com/htdocs /www/bar.example.com/htdocs
</code></pre>

<p>This takes care of giving write-access for their sites to <code>fooguy</code>, <code>foogal</code> and <code>barboy</code>. Neither <code>fooguy</code> nor <code>foogal</code> will be able to write to the bar.example.com site&#8217;s directory, and <code>barboy</code> won&#8217;t be able to edit foo.example.com. If we want to allow all three of them to edit or create inside the main site, we just add them to the <code>webdev</code> group, assuming we&#8217;ve already set the permissions for its root directory and children to be <code>g+w</code>.</p>

<pre><code>adduser fooguy webdev
adduser foogal webdev
adduser barboy webdev
</code></pre>

<h2>Checking permissions</h2>

<p>If we pop over and have a look at these directories, what should be see?</p>

<pre><code>cd /www
ls -l *example.com
</code></pre>

<p>The output should be something like:</p>

<pre><code>bar.example.com:
total 4
drwxrwxr-x 2 root webdev-bar 4096 2012-01-09 18:49 htdocs

foo.example.com:
total 4
drwxrwxr-x 2 root webdev-foo 4096 2012-01-09 18:49 htdocs

www.example.com:
total 4
drwxrwxr-x 2 root webdev 4096 2012-01-09 18:50 htdocs
</code></pre>

<p>What does that mean? What we&#8217;re seeing here is that in all cases, the permissions are set as <code>drwxrwxr-x</code>, which means:</p>

<ol>
<li>It&#8217;s a directory</li>
<li>User permissions are <code>rwx</code> &#8211; Read/Write/eXecute</li>
<li>Group permissions are also <code>rwx</code></li>
<li>Other (&#8220;world&#8221;) permissions are <code>r-x</code> &#8211; Read/eXecute</li>
</ol>

<p>We can also see that each of the <code>htdocs</code> entries has <code>root</code> as its owner, and the respective group we set before as its group. If we&#8217;ve already got a super simple site in these &#8211; just an index and an image directory &#8211; and list inside of htdocs, we should see:</p>

<pre><code>bar.example.com/htdocs:
total 4
drwxrwxr-x 2 root webdev-bar 4096 2012-01-09 19:01 img
-rw-rw-r-- 1 root webdev-bar    0 2012-01-09 18:59 index.html

foo.example.com/htdocs:
total 4
drwxrwxr-x 2 root webdev-foo 4096 2012-01-09 19:01 img
-rw-rw-r-- 1 root webdev-foo    0 2012-01-09 18:59 index.html

www.example.com/htdocs:
total 4
drwxrwxr-x 2 root webdev 4096 2012-01-09 19:01 img
-rw-rw-r-- 1 root webdev    0 2012-01-09 18:59 index.html
</code></pre>

<p>This tells use that the index and the directory are both editable by the right groups as well. (Files are <code>-rw-rw-r--</code>, meaning user and group read/write and world read-only.)</p>

<p><em>To clarify: &#8220;execute&#8221;, when applied to directories, means the ability to change into it or open it. Applied to a file, the execute-bit is a potential hazard, if the file has any code in there, but that&#8217;s another story for another day.</em></p>

<h2>More granularity: ACL</h2>

<p>The approach detailed above is usually enough for most web situations, but if more control is required, we move into ACL territory (Access Control Lists). This is something that has to be made available at the filesystem level, and isn&#8217;t usually available on normal web hosts. As such, it&#8217;s a bit out of the scope of this post.</p>
]]></content:encoded>
			<wfw:commentRss>http://domi.co.uk/2012/01/09/permissions-setup-for-a-debian-web-host/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MacBook DVD swap-out</title>
		<link>http://domi.co.uk/2011/11/25/macbook-dvd-swap-out/</link>
		<comments>http://domi.co.uk/2011/11/25/macbook-dvd-swap-out/#comments</comments>
		<pubDate>Fri, 25 Nov 2011 12:29:28 +0000</pubDate>
		<dc:creator>dom</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[disk]]></category>
		<category><![CDATA[dvd]]></category>
		<category><![CDATA[hardware]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[macbook]]></category>
		<category><![CDATA[ssd]]></category>

		<guid isPermaLink="false">http://domi.co.uk/?p=531</guid>
		<description><![CDATA[When I got my SSD installed in my MacBook, I swapped out the (defective) DVD for a caddy from Mac:Upgrades to house the original boot drive. This was completely unrecognised, but I didn&#8217;t have time to worry about it, so put the old boot disk in an external FW400 case and used the data from [...]]]></description>
			<content:encoded><![CDATA[<p>When I got my <a href="http://domi.co.uk/2011/11/11/solid-state-stress-reliever/">SSD installed in my MacBook</a>, I swapped out the (defective) DVD for a <a href="http://www.macupgrades.co.uk/store/product_info.php?products_id=704">caddy from Mac:Upgrades</a> to house the original boot drive. This was completely unrecognised, but I didn&#8217;t have time to worry about it, so put the old boot disk in an external FW400 case and used the data from there. I assumed there must be something wrong with the ATA interface on my MacBook&#8217;s motherboard, which could explain the DVD not working.</p>

<p>Long story short, I popped open the MacBook and another almost identical one with working DVD and tried all the combinations of disks I could. The odd result of this is that the original boot disk was the only one that didn&#8217;t work in the caddy &#8211; every other drive I tried worked. Very odd. Anyway, I just put a different drive in the caddy and used its external case for my rebellious original boot disk. I can&#8217;t think of an explanation for that set of circumstances&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://domi.co.uk/2011/11/25/macbook-dvd-swap-out/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unlocking T-Mobile Wireless Pointer (UK)</title>
		<link>http://domi.co.uk/2011/11/23/unlocking-t-mobile-wireless-pointer-uk/</link>
		<comments>http://domi.co.uk/2011/11/23/unlocking-t-mobile-wireless-pointer-uk/#comments</comments>
		<pubDate>Wed, 23 Nov 2011 14:44:42 +0000</pubDate>
		<dc:creator>dom</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[3g]]></category>
		<category><![CDATA[access point]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[mobile router]]></category>
		<category><![CDATA[t-mobile]]></category>
		<category><![CDATA[wifi]]></category>

		<guid isPermaLink="false">http://domi.co.uk/?p=529</guid>
		<description><![CDATA[While I was in the UK, I bought a T-Mobile Wireless Pointer (which is quite a daft name for their Huawei E583C). The nicest thing about this, I think is the display that actually lets you know what&#8217;s going on without deciphering blinking LEDs of various colours. You can see signal strength, 3G confirmation, how [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.t-mobile.co.uk/eshop/content/redesign-img/mbb-landing/usb_wireless_pointer.jpg" alt="" title="" /></p>

<p>While I was in the UK, I bought a <a href="http://www.t-mobile.co.uk/shop/mobile-broadband/wireless-pointer/">T-Mobile Wireless Pointer</a> (which is quite a daft name for their Huawei E583C). The nicest thing about this, I think is the display that actually lets you know what&#8217;s going on without deciphering blinking LEDs of various colours. You can see signal strength, 3G confirmation, how many devices are connected by Wifi, how many SMSs are unread, connection status, battery level and which network you&#8217;re connected to just as easily as on your phone (on a cute little OLED display, a bit like the small screen on a clamshell.)</p>

<p>That was another good purchase &#8211; I&#8217;m on a roll! Anyway, getting back to Barcelona, obviously I need to unlock it and make it work with my Vodafone unlimited data plan.</p>

<p>I ended up using <a href="http://www.dc-unlocker.com/">DC Unlocker</a> which seems to Just Work. (Although: Windows required… &lt;sigh>)</p>

<p>Vodafone Spain&#8217;s access info is, as googled in various places, as follows:</p>

<ul>
<li>APN: ac.vodafone.es</li>
<li>User: vodafone</li>
<li>Pass: vodafone</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://domi.co.uk/2011/11/23/unlocking-t-mobile-wireless-pointer-uk/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Solid State Stress Reliever</title>
		<link>http://domi.co.uk/2011/11/11/solid-state-stress-reliever/</link>
		<comments>http://domi.co.uk/2011/11/11/solid-state-stress-reliever/#comments</comments>
		<pubDate>Fri, 11 Nov 2011 15:30:58 +0000</pubDate>
		<dc:creator>dom</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[crucial]]></category>
		<category><![CDATA[crucial m4]]></category>
		<category><![CDATA[m4]]></category>
		<category><![CDATA[macbook]]></category>
		<category><![CDATA[ssd]]></category>

		<guid isPermaLink="false">http://domi.co.uk/?p=512</guid>
		<description><![CDATA[I&#8217;d read a few blog posts here and there about how swapping your old MacBook&#8217;s hard drive for an SSD made amazing improvements, so I decided to give that a go. My 2006 MacBook is definitely creaking, but I don&#8217;t work mobile that much, and I can usually use the iPad for whatever I need [...]]]></description>
			<content:encoded><![CDATA[<iframe class="amazoniframe" src="http://rcm-uk.amazon.co.uk/e/cm?lt1=_blank&#038;bc1=FFFFFF&#038;IS2=1&#038;bg1=FFFFFF&#038;fc1=000000&#038;lc1=0000FF&#038;t=domi-21&#038;o=2&#038;p=8&#038;l=as4&#038;m=amazon&#038;f=ifr&#038;ref=ss_til&#038;asins=B004W2JKZI" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>

<p>I&#8217;d read a few blog posts here and there about how swapping your old MacBook&#8217;s hard drive for an SSD made amazing improvements, so I decided to give that a go. My 2006 MacBook is definitely creaking, but I don&#8217;t work mobile that much, and I can usually use the iPad for whatever I need to really get done before I get back to HQ. (Which is to say, I haven&#8217;t quite found sufficient excuse to buy a new MacBook, Air, Pro, or otherwise…)</p>

<p>So, I got a Crucial M4 from Amazon. On swapping that in for the (already upgraded) hard drive the improvement was way past my expectations. Instant app startup is something you don&#8217;t want to lose once you have it! My iMac&#8217;s main (or usually, <em>only</em>) bottleneck is the hard drive. Now my BlackBook is starting apps seemingly faster than that, even though there&#8217;s a difference of four times the memory, and four times the cores (if you allow hyper-threading into the equation).</p>

<p>I need to have a word with my local Apple specialists about changing my iMac HD for an SSD&#8230;</p>

<p>Nice one, Crucial, and SSDs in general!</p>
]]></content:encoded>
			<wfw:commentRss>http://domi.co.uk/2011/11/11/solid-state-stress-reliever/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A web development workflow</title>
		<link>http://domi.co.uk/2011/11/09/web-development-workflow/</link>
		<comments>http://domi.co.uk/2011/11/09/web-development-workflow/#comments</comments>
		<pubDate>Wed, 09 Nov 2011 15:17:44 +0000</pubDate>
		<dc:creator>dom</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[amazon web services]]></category>
		<category><![CDATA[aws]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[editor]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[remote project]]></category>
		<category><![CDATA[rsync]]></category>
		<category><![CDATA[text editor]]></category>
		<category><![CDATA[textmate]]></category>
		<category><![CDATA[version control]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[workflow]]></category>

		<guid isPermaLink="false">http://domi.co.uk/?p=452</guid>
		<description><![CDATA[[Update: added illustration of overview.] I originally called this post &#8220;My web development workflow&#8221; but although it is my workflow, the idea of the article was as a suggestion for one possible methodology for the kind of development with which I&#8217;m usually involved. Others I&#8217;ve worked with, both in the past and on an ongoing [...]]]></description>
			<content:encoded><![CDATA[<p>[Update: added illustration of overview.]</p>

<p>I originally called this post &#8220;My web development workflow&#8221; but although it is <em>my</em> workflow, the idea of the article was as a suggestion for one possible methodology for the kind of development with which I&#8217;m usually involved. Others I&#8217;ve worked with, both in the past and on an ongoing basis, have found this method to be both flexible and fast. Once the concepts are taken onboard, it&#8217;s also very easy to understand. Another key advantage is that it&#8217;s designed to allow work to be carried out from multiple workstations &#8211; I&#8217;m using the word &#8220;workstation&#8221; very loosely here, including mobile devices &#8211; because the working copy of the files is at a remote location. The amount of times I&#8217;ve saved somebody else&#8217;s skin thanks to that…</p>

<p>The whole shebang depends on certain tools of course. Some of the core elements of the setup are ubiquitous and <em>de facto</em> standards, such as Git, <code>rsync</code>, <code>ssh</code>, <code>ppk</code>, and any flavour of Unix-like OS. That brings me to the less ubiquitous elements, although within the scope of web development, they are not that far from standard. These components include TextMate, from <a href="http://macromates.com/">MacroMates</a> which also means that OS X is a required element. If you&#8217;re not based on OS X, you&#8217;ll need to replace TextMate with a suitable editing environment. If you&#8217;re using Windows, don&#8217;t. Life&#8217;s too short, really. I&#8217;ll come onto how TextMate integrates into the workflow later on.</p>

<p>Here&#8217;s a step-by-step rundown of the process to set this workflow up:</p>

<ol>
<li><a href="#centralrepo">create a central <em>bare</em> git repository</a></li>
<li><a href="#placeholder">create placeholder project file(s) in a work directory on the dev server</a></li>
<li><a href="#gitinit">initialise the working dir as a git project, configure it, and push the placeholder files to the central repo</a></li>
<li><a href="#rsync">synchronise the remote work directory to a local directory</a></li>
<li><a href="#mate">open the local work directory in TextMate</a></li>
<li><a href="#rp1">configure Remote Project for TextMate with the remote working directory</a></li>
<li><a href="#symlink">symlink the web root of the remote working dir to a web-visible location</a></li>
<li><a href="#rp2">use Remote Project in TextMate to keep your local version in sync with your remote version-controlled copy</a></li>
<li>start hacking&#8230;</li>
</ol>

<p>Seems like a lot of hassle? Well, it&#8217;s all done in seconds after the first time, and the benefits far outweigh the setup steps. Let&#8217;s go through each step in more detail.</p>

<p>Here&#8217;s an illustration of the overview:</p>

<p><img src="http://domi.co.uk/files/2011/12/A-web-development-workflow-011.png" alt="A web development workflow 01" border="0" width="750" height="189" /></p>

<p>The &#8220;mobile device(s)&#8221; block can be any platform that can run <code>ssh</code> &#8211; your laptop, your tablet, your phone, somebody else&#8217;s gear, whatever. As long as you can run <code>ssh</code> and you know how to use a good text editor (make that <code>vim</code>!) you can edit your working copy from anywhere and commit/push your changes.</p>

<h2 id="centralrepo">Create a central <em>bare</em> git repository</h2>

<p>This is an easy one to get us started. Let&#8217;s call our project &#8220;devflow&#8221; so we have a handle for it. Create a central directory &#8211; I use <code>/opt/git/devflow.git/</code> &#8211; then go in there and initialise it:</p>

<pre><code>cd /opt/git/devflow.git/
git init --bare
</code></pre>

<p>Additionally, and predictably if you&#8217;ve ever done anything like this before, the permissions need to allow your development team read/write access to the repo. One option is create a group &#8211; I always thought &#8220;gits&#8221; had a ring to it &#8211; and set up the perms:</p>

<pre><code>chmod -R g+w /opt/git/devflow.git
chgrp -R gits /opt/git/devflow.git
</code></pre>

<p>Now any user in the gits group can write to that repo. If you have to add a user to a group it&#8217;s as simple as</p>

<pre><code>adduser {username} {groupname}
</code></pre>

<h2 id="placeholder">Create placeholder project files</h2>

<p>Also simple, I usually use <code>~/jobs/devflow</code> as the working directory on the dev server. Sometimes to get the ball rolling I just create a single <code>readme.markdown</code> file.</p>

<h2 id="gitinit">Initialise your working copy as a git repo</h2>

<p>Inside your working copy on the dev server, initialise a new git repository:</p>

<pre><code>git init
</code></pre>

<p>If you haven&#8217;t configured git yet, start by telling it a little about yourself:</p>

<pre><code>git config --global user.name "A. N. Other"
git config --global user.email "another@example.com"
</code></pre>

<p>Once you&#8217;ve done that, you need to tell the local git repo where the central repo is &#8211; the &#8220;origin&#8221;:</p>

<pre><code>git remote add origin another@devserver:/opt/git/devflow.git
</code></pre>

<p>Apart from the URL of the remote origin, we need to tell git what branch to use and where to find it:</p>

<pre><code>git config --add branch.master.remote origin
git config --add branch.master.merge refs/heads/master
</code></pre>

<p>If at this point, you have a look at the config with <code>cat</code> you&#8217;ll see the results of the configuration we&#8217;ve just done:</p>

<pre><code>cat .git/config
…
[remote "origin"]
    url = another@devserver:/opt/git/devflow.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
    remote = origin
    merge = refs/heads/master
</code></pre>

<p>We can see that the <code>git config</code> commands have written the items to the configuration file. It&#8217;s possible to edit this file directly as well &#8211; whatever you prefer. Another way to view the state of the configuration is to use git&#8217;s own config command:</p>

<pre><code>git config -l
</code></pre>

<p>This lists the configuration in a compact version of the config file:</p>

<pre><code>remote.origin.url=another@devserver:/opt/git/devflow.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master
</code></pre>

<h2 id="rsync">Synchronise local with remote</h2>

<p>In your terminal &#8211; I use iTerm, but OS X Terminal is fine &#8211; change to a working directory. Once again, for this I use <code>~/Jobs/DevFlow</code> or similar. Once you <code>cd</code> into there, just use <code>rsync</code>:</p>

<pre><code>rsync -Chavuz another@devserver:~/jobs/devflow .
</code></pre>

<p>which will bring your project, such as it is, to your local machine. The switches to rsync are to ignore version control systems directories &#8211; we don&#8217;t want any git files getting local. That will likely create issues for us. The other switches are to get human feedback, use archive mode, be verbose, look for updates, and compress the files <em>en route</em>.</p>

<p>Note: this assumes you&#8217;ve set up key-based authentication on the dev server. If you haven&#8217;t step into my office&#8230;</p>

<h3>Setting up PPK</h3>

<p>On your local machine &#8211; let&#8217;s just drop the pretence and call it &#8220;Mac&#8221; from now on! &#8211; run this command:</p>

<pre><code>ssh-keygen
</code></pre>

<p>Then answer with Enter (i.e. blank) to all the questions. This will create  a <code>.ssh</code> directory in your home. The key files (see what I did there?) in there are</p>

<pre><code>id_rsa
id_rsa.pub
</code></pre>

<p>Which as you can guess is the public key, and by elimination, the private key. The public key you can share around however you like &#8211; the worst thing that can happen is that someone will give you a login on their machine. In our case, we&#8217;re interested in the contents of <code>id_rsa.pub</code>. The contents of that file will be added to another file, on the remote dev server. On the dev server, the simplest thing is to do the same thing: <code>ssh-keygen</code>. (You don&#8217;t need to create a key on the server, but a side-effect of doing this is that the <code>~/.ssh</code> directory is created for you in the right place with the right permissions. Once you have the <code>~/.ssh/</code> dir, you can add a file:</p>

<pre><code>touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
cat {contents of local id_rsa.pub} &gt;&gt; ~/.ssh/authorized_keys
</code></pre>

<p>What does a public key look like? Something like:</p>

<pre><code>ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDFmDZzW5XHKjsV2Fo624wXOPxmLkLSKiFkoTgOIqqlu
A3eD1tBpEGvhXYfVab9MJt08w/WdNo828GDUK3bWL74tLKiKyOY+yGwaqLQlqbKti0sFHTHyN/U76aen2
3hKy9ChMc2rFXFiM73fgQQveB1vZkmMezf6xRYcm2uJFiP76aen23hKy9ChMc2rFXFiM73fgQQveB1vZk
mMezf6xiryOCYiFSHvXZBVdToOg0OtDDO6sH1L8li664CDN8KOX1UebOw2DwHIFXNqvIjZQG3+DN8KOX1
UebOw2DwHIFXNqvIjZQG37IvuAlYAR9UPT4FV9mexCxGBJ6xURmHHYRGJwqUYzJKrjqyUIpY8wlHZjqvk
doqeJlBoUrLGNiT+A/gC4kN5haj65pJDvhOU4J0ctD6b dom@macbookhair
</code></pre>

<p>So once the version of you that lives on the dev server has your public key it can check it on its list of <code>authorized_keys</code> to see whether to let you in.</p>

<p>You should never send the private key to anyone over any transport. And you don&#8217;t have to type a password! This is most important for scripted access, like the type that Remote Project is doing for you behind the scenes in TextMate.</p>

<h2 id="mate">Open your project in TextMate</h2>

<blockquote>
  <p>I would recommend installing the TextMate <a href="http://ciaranwal.sh/2008/08/05/textmate-plug-in-projectplus">ProjectPlus</a> plug-in which brings us some nice additional project-handling features. See the above link for full details.</p>
</blockquote>

<p>Once you install the <code>mate</code> shell command, this is just a question of</p>

<pre><code>cd ~/Jobs/DevFlow/
mate devflow
</code></pre>

<p>This will open the whole directory as a project in TextMate.</p>

<h2 id="rp1">Set up Remote Project</h2>

<p>The TextMate bundle Remote Project is really a wrapper for <code>rsync</code>, allowing you to get from remote, put to remote and compare local and remote copies of your project.</p>

<p>[This section may have to change because of Remote Project's seeming lack of availability.]</p>

<p>The configuration of Remote Project is handled by an environment variable: <code>TM_REMOTE_PROJECT</code>. This is set at the project level. Configure it to the location of the remote working copy: <code>another@devserver:~/jobs/devflow</code>.</p>

<p><img src="http://domi.co.uk/files/2011/11/TM_REMOTE_PROJECT1.png" alt="TM_REMOTE_PROJECT.png" border="0" width="596" height="307" /></p>

<p>This is a good point to save the TM project (⌃⌘S). I usually save it in the same directory as the root dir of the working copy. In this case, that would be <code>~/Jobs/DevFlow/</code>.</p>

<p>Remote Project, as I have it configured, ignores the <code>.git</code> directory on your remote working copy, so you never get into a muddle with two competing copies of that. It also means that wherever you are you can work with the repo as long as you have access to ssh.</p>

<h2 id="symlink">Symlink to a web-visible location</h2>

<p>Back on the dev server now, we create a virtual host for our project. This is normally a subdomain, possibly a sub-subdomain, like devflow.work.domi.co.uk. This means you can configure the DNS with a wildcard record, so when a client gives you something to work on urgently out of the blue, it&#8217;s ready.</p>

<p>If you have your vhosts set up to live somewhere like <code>/var/www/work.domi.co.uk/htdocs/</code> you can quickly symlink from there to <code>~/jobs/devflow</code> and you can see your changes as soon as Remote Project uploads them.</p>

<pre><code>cd /var/www/work.domi.co.uk/htdocs/
ln -s /home/another/jobs/devflow
</code></pre>

<p>An example snippet from an Apache Virtual Hosts configuration might be:</p>

<pre><code>&lt;VirtualHost *:80&gt;
    ServerName devflow.work.domi.co.uk
    DocumentRoot /var/www/work.domi.co.uk/htdocs/devflow
&lt;/VirtualHost&gt;
</code></pre>

<h2 id="rp2">Start syncing local and remote copies of the project</h2>

<p>The Remote Project bundle has three main functions:</p>

<ul>
<li>Upload Project Changes</li>
<li>Get Remote Project</li>
<li>Compare to Remote Project</li>
</ul>

<p>They do what they sound like they will do. Inside the bundle, the commands are fairly normal <code>rsync</code> statements. The first thing to try is the compare function &#8211; right now, there should be no difference between the local and remote. Edit the <code>readme.markdown</code> we created, then run the comparison again. Now we should see that the local copy is newer.</p>

<p><img src="http://domi.co.uk/files/2011/11/TM-RP-Compare.png" alt="TM-RP-Compare.png" border="0" width="600" height="435" /></p>

<p>The fast way to use Remote Project is with its default shortcut: ⌃⌘P then 1 for upload, 2 for download and 3 for compare.</p>

<p><img src="http://domi.co.uk/files/2011/11/Remote_Project_menu.png" alt="Remote_Project_menu.png" border="0" width="254" height="122" /></p>

<p>The confirmation of the sync is just a small tooltip next to the text cursor in the editor:</p>

<p><img src="http://domi.co.uk/files/2011/11/RM_tooltip.png" alt="RM_tooltip.png" border="0" width="216" height="41" /></p>

<h3>My customised Remote Project commands:</h3>

<h4>Upload (excerpt)</h4>

<pre><code>rsync -auCz --exclude 'phpdoc' --exclude '.git' --exclude "cache" 
--exclude "logs" --exclude ".DS_Store" --exclude "Thumbs.db" 
--exclude ".*.swp" --exclude "stats" --include ".gitignore" 
--include ".htaccess" "$TM_PROJECT_DIRECTORY/" "$ESCAPED_REMOTE"
</code></pre>

<h4>Download (excerpt)</h4>

<pre><code>rsync --delete -auCz --exclude '.git' --exclude "cache" 
--exclude "logs" --exclude ".DS_Store" --exclude "Thumbs.db" 
--exclude ".*.swp" --exclude "stats" --include ".gitignore" 
--include ".htaccess" "$ESCAPED_REMOTE/" "$TM_PROJECT_DIRECTORY"
</code></pre>

<p>Obviously, in the bundle these commands are one-liners.</p>

<p>You&#8217;ll notice something important in the Download excerpt: that <code>rsync</code> has its <code>--delete</code> option set. This will remove any files from your local directory that aren&#8217;t present in the remote. That keeps things tidy, but it can also remove new files you&#8217;ve just created locally that you haven&#8217;t yet uploaded, so beware of that.</p>

<p>Other elements to those command lines are:</p>

<ul>
<li>we don&#8217;t upload &#8220;phpdoc&#8221;, because it&#8217;s generated automatically on the remote</li>
<li>we exclude some standard things that aren&#8217;t part of the project: cache, logs, preview file, stats, <code>vi</code> swap files</li>
<li>we make sure .gitignore and .htaccess are included &#8211; they&#8217;re part of the project, but sometimes default <code>rsync</code> configuration has them excluded</li>
<li>the <code>-C</code> switch to <code>rsync</code> is to ignore source control directories (&#8220;C&#8221; for &#8220;CVS&#8221;) and in current versions that includes git, but not all versions of <code>rsync</code> know about git, so we explicity <code>--exclude</code> it as well.</li>
</ul>

<h2>Conclusion</h2>

<p>Now you&#8217;ve got to this point, you can work locally, with the advantages that brings &#8211; being able to view files in Finder, save directly and so on &#8211; and handle the versioning remotely in a shell, as it should be! And while you&#8217;re working, everything is visible at a development URL that is as close as possible to how the production site will be, because it&#8217;s at the root of an Apache Virtual Host, with as much of the configuration exactly the same as the final destination for the project&#8217;s hosting.</p>
]]></content:encoded>
			<wfw:commentRss>http://domi.co.uk/2011/11/09/web-development-workflow/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>App Store not updating apps?</title>
		<link>http://domi.co.uk/2011/11/05/app-store-not-updating-apps/</link>
		<comments>http://domi.co.uk/2011/11/05/app-store-not-updating-apps/#comments</comments>
		<pubDate>Sat, 05 Nov 2011 10:37:25 +0000</pubDate>
		<dc:creator>dom</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[app store]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[mac app store]]></category>
		<category><![CDATA[os x]]></category>
		<category><![CDATA[osx]]></category>
		<category><![CDATA[updates]]></category>

		<guid isPermaLink="false">http://domi.co.uk/?p=448</guid>
		<description><![CDATA[Mac App Store not updating your apps with &#8220;Please login to the account you purchased with&#8221; type errors? The simplest fix seems to be to just delete the app from your Applications folder. Refresh the Purchased page on the Mac App Store and now instead of Update, its button says &#8220;Install&#8221; (well, on mine it [...]]]></description>
			<content:encoded><![CDATA[<p>Mac App Store not updating your apps with &#8220;Please login to the account you purchased with&#8221; type errors? The simplest fix seems to be to just delete the app from your Applications folder. Refresh the Purchased page on the Mac App Store and now instead of Update, its button says &#8220;Install&#8221; (well, on mine it says &#8220;Instalar&#8221;, so whatever language you&#8217;re in.)</p>

<p>Seems to work consistently for me&#8230;</p>

<p>[Update: title changed to reflect how a human speaks...]</p>
]]></content:encoded>
			<wfw:commentRss>http://domi.co.uk/2011/11/05/app-store-not-updating-apps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Drop the BOM</title>
		<link>http://domi.co.uk/2011/11/03/drop-the-bom/</link>
		<comments>http://domi.co.uk/2011/11/03/drop-the-bom/#comments</comments>
		<pubDate>Thu, 03 Nov 2011 14:01:57 +0000</pubDate>
		<dc:creator>dom</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[bom]]></category>
		<category><![CDATA[editor]]></category>
		<category><![CDATA[nano]]></category>
		<category><![CDATA[unix]]></category>
		<category><![CDATA[vim]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://domi.co.uk/?p=446</guid>
		<description><![CDATA[[Update 2011-12-20-120457: see end of post] I sometimes get issues with files that come in from another source, that have the BOM &#8211; usually from some other web developer who&#8217;s using Windows. It&#8217;s not a massive issue, but often introduces space that you can&#8217;t see except in the browser where it can break some designs. [...]]]></description>
			<content:encoded><![CDATA[<p>[Update 2011-12-20-120457: see end of post]</p>

<p>I sometimes get issues with files that come in from another source, that have the <a href="http://en.wikipedia.org/wiki/Byte_order_mark">BOM</a> &#8211; usually from some other web developer who&#8217;s using Windows.</p>

<p>It&#8217;s not a massive issue, but often introduces space that you can&#8217;t see except in the browser where it can break some designs.</p>

<p>One problem is that <a href="http://www.vim.org/">vim</a> and most (all?) graphical editors don&#8217;t show it to you so you can remove it, so you usually have to shove it through perl or something. Another method that&#8217;s extremely easy to use is to edit the file in <a href="http://www.nano-editor.org/">nano</a>. I&#8217;m not a massive fan of nano, but what it gives you in this case is the ability to see the BOM as what looks like a single space at the start of the file, so you can delete it very easily. Handy.</p>

<p>Update:</p>

<p>There&#8217;s an even easier way, just in vim; not sure what from version this became available.</p>

<p>Check to see if you have a BOM:</p>

<pre><code>:set bomb?
</code></pre>

<p>Get rid of it:</p>

<pre><code>:set nobomb
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://domi.co.uk/2011/11/03/drop-the-bom/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Something I always forget when setting up the post-receive hook for a new git repo</title>
		<link>http://domi.co.uk/2011/10/29/something-i-always-forget-when-setting-up-the-post-receive-hook-for-a-new-git-repo/</link>
		<comments>http://domi.co.uk/2011/10/29/something-i-always-forget-when-setting-up-the-post-receive-hook-for-a-new-git-repo/#comments</comments>
		<pubDate>Fri, 28 Oct 2011 22:55:35 +0000</pubDate>
		<dc:creator>dom</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[repo]]></category>
		<category><![CDATA[version control]]></category>

		<guid isPermaLink="false">http://domi.co.uk/?p=434</guid>
		<description><![CDATA[Catchy title for a blog post, huh? Anyway, something I always (or almost always) forget to do every time when I set up a new git repo and set up the hook to send everyone an email on each git push is to edit description so the first email always starts &#8220;UNNAMED PROJECT&#8221; which drives [...]]]></description>
			<content:encoded><![CDATA[<p>Catchy title for a blog post, huh?</p>

<p>Anyway, something I always (or almost always) forget to do every time when I set up a new git repo and set up the hook to send everyone an email on each <code>git push</code> is to edit <code>description</code> so the first email always starts &#8220;UNNAMED PROJECT&#8221; which drives me mad!</p>

<p>The full list of steps for setting this up I take are:</p>

<pre><code>cd {git dir}/hooks
mv post-receive post-receive.bak
ln -s /usr/share/doc/git-core/contrib/hooks/post-receive-email post-receive
vi config # edit the config to give the hook an email address (see below)
vi description # *that* step - edit this to have your project name
</code></pre>

<p>The config should have something like this in it:</p>

<pre><code>[hooks]
mailinglist = bunch-o-gits@example.com
emailprefix = "[URA git] "
</code></pre>

<p>which will send it to a list you need to set up and give you something by which to filter the emails.</p>

<p>Later, gits!</p>

<p>[Update: that line linking to the post-receive-email script might be a bit Debian-specific, not sure…]</p>
]]></content:encoded>
			<wfw:commentRss>http://domi.co.uk/2011/10/29/something-i-always-forget-when-setting-up-the-post-receive-hook-for-a-new-git-repo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

