<?xml version="1.0" encoding="UTF-8"?>
<rss 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/" version="2.0">

<channel>
	<title>Pradador.com</title>
	
	<link>http://pradador.com</link>
	<description>Code, DIY, Music and More</description>
	<lastBuildDate>Thu, 19 Nov 2009 05:34:35 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/pradador" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="pradador" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Website Screensaver in MooTools</title>
		<link>http://pradador.com/2009/11/18/website-screensaver-in-mootools/</link>
		<comments>http://pradador.com/2009/11/18/website-screensaver-in-mootools/#comments</comments>
		<pubDate>Thu, 19 Nov 2009 05:34:35 +0000</pubDate>
		<dc:creator>pradador</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://pradador.com/?p=361</guid>
		<description><![CDATA[<p>I visited the BMW website the other day and found that they have a screensaver type of effect on their page. So it got me thinking and I decided to write my own script in MooTools which would let me fire some functions when the user goes idle and when they return. Check out the code and demo after the jump.</p>]]></description>
			<content:encoded><![CDATA[<p>To achieve screensaver like behavior, I wrote Screensaver.js. Note that the script doesn&#8217;t show or display a screensaver itself. It simply lets you attach functions to a pair of events for when the user goes idle and when they return. I&#8217;m using it on a couple of pages to start/stop a slideshow. It&#8217;s perfect for toggling type of functions which make sense to fire when the user goes idle. Or how about preloading images only when the user is idle?</p>
<p>You use it by creating a new Screensaver object and simply attaching your show/hide functions to the onActive and onIdle events it fires. For example, let&#8217;s say you have a Lightbox type of element and want to display it when the user goes idle. You would do something like this:</p>
<pre class="js">
// Lightbox pseudocode
var lightbox = new Lightbox();

// Screensaver
var moosaver = new Screensaver({
	onIdle:  lightbox.show,
	onActive: lightbox.hide,
	ttl: 15000 // 15 seconds till idle.
});
</pre>
<p>Download your own copy at the <a href="http://github.com/pradador/Screensaver.js">GitHub Repo</a> or just copy and paste the code below. The repo has a bit of documentation if you need more info.</p>
<pre class="js">(function() {
	Screensaver = new Class({
		Implements: [Options, Events],
		options: {/*
			onActive: $empty,
			onIdle: $empty,*/
			events: ['click', 'keypress', 'mousemove', 'resize', 'scroll'],
			target: window,
			ttl: 10000
		},

		initialize: function(options) {
			this.setOptions(options);
			this.enabled = false;

			var target = document.id(this.options.target);
			this.options.events.each(function(ev) {
				target.addEvent(ev, this.reset.bind(this));
			}, this);

			this.monitor();
		},

		monitor: function() {
			this.timer = this.display.delay(this.options.ttl, this);
		},

		reset: function() {
			$clear(this.timer);
			if (this.enabled) {
				this.fireEvent('active');
				this.enabled = false;
			}
			this.monitor();
		},

		display: function() {
			this.fireEvent('idle');
			this.enabled = true;
		}
	});

	Element.implement({
		screensave: function(options) {
			options.target = this;
			return new Screensaver(options)
		}
	});
})();
</pre>
]]></content:encoded>
			<wfw:commentRss>http://pradador.com/2009/11/18/website-screensaver-in-mootools/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>OpenDNS URL Resolving Bookmarklet</title>
		<link>http://pradador.com/2009/11/17/opendns-url-resolving-bookmarklet/</link>
		<comments>http://pradador.com/2009/11/17/opendns-url-resolving-bookmarklet/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 09:23:16 +0000</pubDate>
		<dc:creator>pradador</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://pradador.com/?p=352</guid>
		<description><![CDATA[<p><a href="http://opendns.com/">OpenDNS'</a> services are excellent, but their URL redirections and rewritings can sometimes get in the way of regular browsing. My one particular grievance is their URL rewriting when a URL fails to resolve. I've written a small bookmarklet which helps you reload the original URL in case this happens. Check out the code and bookmarklet after the jump.</p>]]></description>
			<content:encoded><![CDATA[<p>As much as I love <a href="http://opendns.com">OpenDNS&#8217;</a> services, I find it a bit intrusive at times when URLs fail to resolve. For instance, sometimes my connection will mess up when visiting a page and it will ultimately result in a DNS hijacking.</p>
<p>Here&#8217;s a detailed example: Let&#8217;s say I visit this Reddit URL just as my connection flakes out:</p>
<pre>http://www.reddit.com/r/programming/comments/a50gl/my_com_sci_professor_just_told_us_that_hes_never/</pre>
<p>After a min or so of not resolving, OpenDNS kicks in and attempts to help out. It will convert that url to the following in the process:</p>
<pre>http://guide.opendns.com/?url=www.reddit.com%2Fr%2Fprogramming%2Fcomments%2Fa50gl%2Fmy_com_sci_professor_just_told_us_that_hes_never%2F</pre>
<p>Now I know that URL is valid, but now there&#8217;s no easy way to get back to it since the URL is all mangled. What can we do?</p>
<p>Javascript to the rescue! We simply use a bit of string manipulation on the url to figure out the original location and use the window.location style redirect to take us there. Simply drag this <a href="javascript:(function(){window.location='http://'+decodeURIComponent(document.location.search.substring(5));})();">bookmarklet</a> to your bookmarks bar to use. Here&#8217;s the relevant javascript code:</p>
<pre class="js">(function(){
	window.location = 'http://'+decodeURIComponent(document.location.search.substring(5));
})();</pre>
]]></content:encoded>
			<wfw:commentRss>http://pradador.com/2009/11/17/opendns-url-resolving-bookmarklet/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Rackspace Cloud VS. Slicehost</title>
		<link>http://pradador.com/2009/10/28/rackspace-cloud-vs-slicehost/</link>
		<comments>http://pradador.com/2009/10/28/rackspace-cloud-vs-slicehost/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 05:22:16 +0000</pubDate>
		<dc:creator>pradador</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://pradador.com/?p=337</guid>
		<description><![CDATA[<p>Ah, the eternal question. Ever since Rackspace acquired Slicehost it seems to be on everyone's mind. In this post I explore the differences and help you make the right choice when it comes to VPS hosting.</p>]]></description>
			<content:encoded><![CDATA[<p>Ever since the Rackspace acquisition of Slicehost, I see this question pop up all the time on their forums and on the net. They live in the same data centers. They have identical server offerings. So which one&#8217;s better?
<p>Well the answer is a lot simpler than it seems. The key to it all is the variable bandwidth pricing which means that once you&#8217;ve picked your slice size, your bandwidth usage will dictate which company you should host with. There are a couple other differences which I will point out below, but for the most part the server size and bandwidth use should take the bulk of the decision process.</p>
<p>I&#8217;ve created a simple table below which gives you the bandwidth limit at which Rackspace stops being the better deal. It&#8217;s based on the prices as of October 29, 2009 where Rackspace charges $0.22/GB and Slicehost charges $0.30/GB over your allotment. Simply pick your server size on the left and compare your expected bandwidth needs with the boundary.</p>
<table cellpadding="0" cellspacing="0" border="0">
<caption>Bandwidth limit where Rackspace is optimal.</caption>
<thead>
<tr>
<th class="left-header">Slice Size</th>
<th>Bandwidth</th>
</tr>
</thead>
<tbody>
<tr>
<th class="left-header">256 MB</th>
<td class="pair">
				If using less than 41.14 GB, pick <img src="http://pradador.com/wp-content/uploads/2009/10/rc.png" alt="Rackspace Logo" title="Rackspace Logo" width="24" height="24" class="alignnone size-full wp-image-346" /> The Rackspace Cloud
			</td>
</tr>
<tr>
<th class="left-header">512 MB</th>
<td class="pair">
				If using less than 73.18 GB, pick <img src="http://pradador.com/wp-content/uploads/2009/10/rc.png" alt="Rackspace Logo" title="Rackspace Logo" width="24" height="24" class="alignnone size-full wp-image-346" /> The Rackspace Cloud
			</td>
</tr>
<tr>
<th class="left-header">1024 MB</th>
<td class="pair">
				If using less than 119.09 GB, pick <img src="http://pradador.com/wp-content/uploads/2009/10/rc.png" alt="Rackspace Logo" title="Rackspace Logo" width="24" height="24" class="alignnone size-full wp-image-346" /> The Rackspace Cloud
			</td>
</tr>
<tr>
<th class="left-header">2048 MB</th>
<td class="pair">
				If using less than 192.73 GB, pick <img src="http://pradador.com/wp-content/uploads/2009/10/rc.png" alt="Rackspace Logo" title="Rackspace Logo" width="24" height="24" class="alignnone size-full wp-image-346" /> The Rackspace Cloud
			</td>
</tr>
<tr>
<th class="left-header">4096 MB</th>
<td class="pair">
				If using less than 340.00 GB, pick <img src="http://pradador.com/wp-content/uploads/2009/10/rc.png" alt="Rackspace Logo" title="Rackspace Logo" width="24" height="24" class="alignnone size-full wp-image-346" /> The Rackspace Cloud
			</td>
</tr>
<tr>
<th class="left-header">8192 MB</th>
<td class="pair">
				If using less than 452.73 GB, pick <img src="http://pradador.com/wp-content/uploads/2009/10/rc.png" alt="Rackspace Logo" title="Rackspace Logo" width="24" height="24" class="alignnone size-full wp-image-346" /> The Rackspace Cloud
			</td>
</tr>
<tr>
<th class="left-header">15872 MB</th>
<td class="pair">
				If using less than 450.91 GB, pick <img src="http://pradador.com/wp-content/uploads/2009/10/rc.png" alt="Rackspace Logo" title="Rackspace Logo" width="24" height="24" class="alignnone size-full wp-image-346" /> The Rackspace Cloud<br />
				If using more than 6260.00 GB, pick <img src="http://pradador.com/wp-content/uploads/2009/10/rc.png" alt="Rackspace Logo" title="Rackspace Logo" width="24" height="24" class="alignnone size-full wp-image-346" /> The Rackspace Cloud
			</td>
</tr>
</tbody>
</table>
<p>As you can see, Slicehost gives you a better deal when your bandwidth needs increase. I&#8217;ve used them both, and with the tools they offer and their pricing scheme, it feels like they are there to be used as web hosts. Rackspace on the other hand doesn&#8217;t bundle bandwidth and even prices their servers by the hour which leads to faster deploy/destroy cycles and more oriented towards apps.</p>
<p>The other differences have been debated before like the extra DNS records you can use in Slicehost, but I think these are minor details when compared to the savings you can get by using Rackspace for low bandwidth operations. All that being said, you can&#8217;t go wrong with either company</p>
]]></content:encoded>
			<wfw:commentRss>http://pradador.com/2009/10/28/rackspace-cloud-vs-slicehost/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WordPress mode for Coda released</title>
		<link>http://pradador.com/2009/10/11/wordpress-mode-for-coda-released/</link>
		<comments>http://pradador.com/2009/10/11/wordpress-mode-for-coda-released/#comments</comments>
		<pubDate>Sun, 11 Oct 2009 19:51:37 +0000</pubDate>
		<dc:creator>pradador</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Coda]]></category>
		<category><![CDATA[see-mode]]></category>
		<category><![CDATA[syntax]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://pradador.com/?p=323</guid>
		<description><![CDATA[<p>I just released a WordPress syntax mode for Coda which adds the autocompletion support for WordPress functions. Read more about it after the jump or download your own copy here: <a href="/code/coda/wordpressmode/">WordPress Mode</a></p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://pradador.com/wp-content/uploads/2009/10/wordpresscoda.jpg"><img src="http://pradador.com/wp-content/uploads/2009/10/wordpresscoda-300x128.jpg" alt="WordPress + Coda" title="WordPress + Coda" width="300" height="128" class="alignnone size-medium wp-image-329 left" /></a></p>
<p>I originally used <a href="http://radiantcms.org/">Radiant CMS</a> to manage the content on my site but after I ran into a wall trying to get blog functionality to work, and more importantly since it was over-taxing my 256 MB slice, I decided to switch to WordPress.</p>
<p>Developing a site layout with WordPress on Coda turned out to be easier than I thought it would be. While the local previews might not work, it was easy enough to publish and preview changes on a test deployment while Radiant kept running. The only thing I wish I had at the time was autocompletion of WordPress functions so I decided to write a Mode for WordPress now that I had some spare time.</p>
<p>With autocompletion from my Mode and the Coda Clips from <a href="http://wpcandy.com/articles/wordpress-coda-clips-collection.html">WPCandy.com</a>, working on my site is much more streamlined. Download your own copy at <a href="/code/coda/wordpressmode/">WordPress.mode</a></p>
]]></content:encoded>
			<wfw:commentRss>http://pradador.com/2009/10/11/wordpress-mode-for-coda-released/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Roll your own Subversion server, Roll-out Part 2</title>
		<link>http://pradador.com/2009/10/09/roll-your-own-subversion-server-roll-out-part-2/</link>
		<comments>http://pradador.com/2009/10/09/roll-your-own-subversion-server-roll-out-part-2/#comments</comments>
		<pubDate>Sat, 10 Oct 2009 01:25:41 +0000</pubDate>
		<dc:creator>pradador</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://pradador.com/?p=313</guid>
		<description><![CDATA[<p>In the final part of the guide we will automate a couple of systems to get Warehouse and svnserve working together. First we will create a basic hook that will automatically syncrhonize Warehouse when we commit a changeset and finally we will make Warehouse manage our authz and passwd to easily manage access from the web client. Once that is done, our system will be fully functional.</p>]]></description>
			<content:encoded><![CDATA[<p>To take full advantage of Warehouse&#8217;s features, we now weave it into svnserve and get both systems working together. First we will make svnserve hooks that update our warehouse repositories and then we will have Warehouse create our authz and passwd files for svnserve to use.</p>
<h3 id="hooks">Hooks</h3>
<p>Svnserve has a nice system of hooks that let you execute any script you want at certain moments of a commit. Warehouse has a set of command line actions that let you synchronize the changesets so let&#8217;s make a hook which happens after a commit to synchronize the latest changes.</p>
<h4 id="post_commit_file">post-commit file</h4>
<p>Let&#8217;s create the post-commit script:</p>
<pre><code class="shell">cd ~/repositories
nano post-commit
</code></pre>
<p>Here&#8217;s the contents of the script:</p>
<pre><code class="shell">#!/bin/sh
cd /home/demo/public_html/warehouse
rake warehouse:post_commit RAILS_ENV=production REPO_PATH=$1 REVISION=$2
</code></pre>
<p>As long as the repository and the subfolder have the same name, the repo is automatically chosen by Warehouse so to make things easy and to be able to use this same post-commit file everywhere, let&#8217;s keep those names consistent.</p>
<p>Now make the script executable:</p>
<pre><code class="shell">chmod +x post-commit
</code></pre>
<h4 id="hook_your_repositories">hook your repositories</h4>
<p>Finally, we&#8217;ll make a symbolic link to the post-commit hook from each of the repos&#8217; hooks directories just like we did with the svnserve.conf files. Be sure to do this for any future repos you create.</p>
<pre><code class="shell">ln -fs /home/demo/repositories/post-commit project1/hooks
ln -fs /home/demo/repositories/post-commit project2/hooks
</code></pre>
<h4 id="test_it_out">Test it out</h4>
<p>Let&#8217;s give the automatic syncing a try. Make some changes to your local copy of the repository and make a commit. This should behave normally but now when you revisit your repo in Warehouse, it will have magically been updated with the latest changes. Neat!</p>
<h3 id="svn_access_files">SVN Access Files</h3>
<p>Let&#8217;s get Warehouse to create both our SVN access files (authz) and user/password files (passwd) automatically when changes are made from the web interface. Let&#8217;s start with the easy one&#8230;</p>
<h4 id="build_authz_configuration_file">Build authz configuration file</h4>
<p>Warehouse let&#8217;s you set per-directory access rules on every repo it manages. This allows you to fine tune access for any and all of your users easily. It will also output these rules to a file which svnserve can read and understand to limit access for commits and checkouts, etc.</p>
<p>Let&#8217;s set this up, visit the admin settings tab at http://code.example.com/admin/settings. Set the &#8220;Shell command to run when permissions are updated&#8221; to:</p>
<pre><code class="shell">rake warehouse:build_config RAILS_ENV=production CONFIG=/home/demo/repositories/authz
</code></pre>
<p>All this does is tell Warehouse to write the permissions we configure in Warehouse to the authz file in our repositories folder.</p>
<h4 id="re_enable_authz_db_in_svnserve">Re-enable authz-db in svnserve</h4>
<p>Now we must tell svnserve to actually use this authz file so hop back into the svnserve.conf file and make the change by uncommenting the authz-db line. It should now look like this:</p>
<pre><code class="shell">[general]
anon-access = none
auth-access = write
password-db = /home/demo/repositories/passwd
authz-db    = /home/demo/repositories/authz
realm       = Example Repository
</code></pre>
<p>That&#8217;s it! Now you can manage repository access right from the Warehouse GUI. Give it a try by changing a permission from the Access pane and seeing if the authz file gets updated correctly.</p>
<p>Note that the default access for new repos in Warehouse is read-only for the primary user so be sure to update that as needed.</p>
<h3 id="write_the_passwd_file">Write the passwd file</h3>
<p>Warehouse has a mechanism to write to htpassword files (appropriately called rake warehouse:build_htpasswd). These files look just like the passwd file we created in Act I except they don&#8217;t include the [users] header. The [users] header is necessary for svnserve to read the file so we must coax Warehouse to add this header. Additionally, Warehouse is configured to write passwd files in a hashed form but svnserve requires plaintext files. So let&#8217;s fix this.</p>
<h4 id="enable_plain_text_passwords">Enable Plain Text passwords</h4>
<p>Hop back into the Settings pane of the Admin page. Click on &#8220;More settings&#8230;&#8221; at the bottom left and look for the &#8220;Authentication Scheme&#8221; drop down under the Password Settings section. Choose &#8220;Plain&#8221; from the drop down and save the new settings. Now you must change your user passwords to make sure they are saved in plain text this time around.</p>
<h4 id="change_warehouse8217s_htpasswd_method">Change Warehouse&#8217;s htpasswd method</h4>
<p>Now we will actually edit the Warehouse app to get the functionality we want. This isn&#8217;t too hard, but unfortunately any updates will temporarily break the password mechanism. So be sure to change this file again if you ever update/change Warehouse. Let&#8217;s get to the right file first:</p>
<pre><code class="shell">cd ~/public_html/warehouse
cd lib/warehouse
</code></pre>
<h4 id="edit_commandrb_file">edit command.rb file</h4>
<p>Open up the command.rb file:</p>
<pre><code class="shell">nano command.rb
</code></pre>
<p>and look for the following method (line 98):</p>
<pre><code class="ruby">def write_users_to_htpasswd(users, htpasswd_path = nil)
    if htpasswd_path.nil?
        htpasswd_path = users
        users         = connection[:users]
    end

    users = users.select(:login, :crypted_password) if users.is_a?(Sequel::Dataset)
    open htpasswd_path, 'w' do |f|
        users.each do |user|
            next if user[:login].to_s == '' || user[:crypted_password].to_s == ''
            f.write("%s:%s\n" % [user[:login], user[:crypted_password]])
        end
    end
    puts "Wrote htpasswd file to '#{htpasswd_path}'"
end
</code></pre>
<p>This baby handles the writing of the htaccess file so we simply tell it to write a [users] line before cycling through each user and password. Simply add the following code:</p>
<pre><code class="ruby">f.write("[users]\n")
</code></pre>
<p>To the &#8220;open htpasswd_path&#8221; loop like this:</p>
<pre><code class="ruby">open htpasswd_path, 'w' do |f|
    f.write("[users]\n")
    users.each do |user|
        next if user[:login].to_s == '' || user[:crypted_password].to_s == ''
        f.write("%s:%s\n" % [user[:login], user[:crypted_password]])
    end
end
</code></pre>
<h4 id="save_and_restart">save and restart</h4>
<p>Now save the file and restart Warehouse.</p>
<pre><code class="shell">sudo /etc/init.d/thin restart
</code></pre>
<h4 id="test_it_out">test it out</h4>
<p>And that&#8217;s it. Let&#8217;s give it a try by running the following command:</p>
<pre><code class="shell">cd ~/public_html/warehouse
rake warehouse:build_htpasswd RAILS_ENV=production CONFIG=/home/demo/repositories/passwd
</code></pre>
<p>Now check the passwd file and ensure that it is written correctly with the [users] header and that your username and password appear:</p>
<pre><code class="shell">cat ~/repositories/passwd
...
[users]
admin:password
</code></pre>
<h4 id="all_together_now">All together now</h4>
<p>Sweet! Warehouse can now dynamically write our authz and passwd files in a format that svnserve understands. This means svnserve is &#8220;receiving&#8221; instructions from Warehouse on how to behave and is securing your repositories as needed.</p>
<p>The final step is to tell Warehouse to execute that htpasswd command when users are modified. Go back into the Settings of the Admin tab and add the command:</p>
<pre><code class="shell">rake warehouse:build_htpasswd RAILS_ENV=production CONFIG=/home/demo/repositories/passwd
</code></pre>
<p>to the &#8220;Shell command to run when someone&#8217;s password is updated.&#8221; option. From now on, when you add or update a user, the passwd file will be changed accordingly.</p>
<h3 id="finale">Finale</h3>
<p>Phew! That was some decent work up there. But it is worth it. Your Subversion slice is running smoothly with no user/repository restrictions. You have about 8 GB of usable space for your content which is more than any of the SVN hosts out there provide. And with bandwidth cheaper than ever, you shouldn&#8217;t break more than $15 a month.</p>
<p>In general, this system covers the needs of the majority of users out there, but for the rest there are a couple of tweaks that might be helpful. In future parts, I will detail how to switch from Nginx to Apache and serve SVN through mod_svn which will increase our security options. There&#8217;s also a few other Warehouse tricks that might be helpful to some users. Stay in tune!</p>
]]></content:encoded>
			<wfw:commentRss>http://pradador.com/2009/10/09/roll-your-own-subversion-server-roll-out-part-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Fixing Lightbox’s click handling issues</title>
		<link>http://pradador.com/2009/10/07/fixing-lightboxs-click-handling-issues/</link>
		<comments>http://pradador.com/2009/10/07/fixing-lightboxs-click-handling-issues/#comments</comments>
		<pubDate>Wed, 07 Oct 2009 07:16:34 +0000</pubDate>
		<dc:creator>pradador</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[MooTools]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://pradador.com/?p=129</guid>
		<description><![CDATA[<p>Browsers have mechanisms to distinguish between a left click and a right click, but there are other types of clicks like clicks with shortcut keys that often get overlooked. These tend to perform specific behaviors like opening a new tab, so they should be treated differently than a normal click. With a bit of MooTools scripting, we can check for these types of clicks and take action as needed.</p>]]></description>
			<content:encoded><![CDATA[<p>I keep seeing more and more sites implement some sort of Lightbox script to display images. Sometimes they do provide some nice eye candy &#8211; like in a picture gallery setting &#8211; but when misused they get in the way of regular browsing. They behave like modal overlays when improperly used (which is bad enough in itself), but what&#8217;s worse is that when you use shortcuts to try and open them in a new tab, they hijack the click and go into picture mode. It&#8217;s a <a href="http://en.wikipedia.org/wiki/Lightbox_(JavaScript)#Criticism">common criticism</a>.</p>
<p>The typical implementation uses standard thumbnails linked to their full-sized image file in a way that if Javascript is turned off you can still click and get to the image. This is great for accessibility, but that also means that these Lightbox-enabled images look and feel like regular links. Because of this, the expected behavior when a user command+clicks (or control+clicks in Windows) is to have the link open in a new tab. However, the browsers don&#8217;t have a special click event for these shortcut keys so when the regular click event fires, the Lightbox uses it to activate its own features.</p>
<p>This breaks default expected behavior so it should be fixed. Since there is no built-in way to detect keys held during a click event, I&#8217;ve come up with a simple MooTools script that detects if a key is held down when a user clicks on an element. We basically set flags for the modifier type keys which are set when the user presses one of the keys. Then we create a custom event that can detect if any of the modifier keys are set. Here&#8217;s the code:</p>
<pre class="js">(function() {
	var keys = new Hash({ 16: false, 18: false });  // Shift and Option/Alt keys
	if (Browser.Platform.win) { keys[17] = false; } // Control key
	if (Browser.Platform.mac) { keys[91] = false; } // Command Key

	window.addEvent('domready', function() {
		$(document.body).addEvents({
			'keydown': function(e) {
				if (keys.has(e.code)) { keys[e.code] = true; }
			},
			'keyup':   function(e) {
				if (keys.has(e.code)) { keys[e.code] = false; }
			}
		})
	});

	Element.Events.cleanclick = {
		base: 'click',
		condition: function(e) { return !keys.hasValue(true) }
	}
})();</pre>
<p>We can then use this new event instead of the regular click event to ensure our Lightbox only opens when a &#8220;clean&#8221; click is performed, i. e. a click without modifier keys held down. Here&#8217;s an example.</p>
<p>
<pre class="js">$$('a.lightbox').addEvent('cleanclick', function() {
	// openLightbox();
});</pre></p>
]]></content:encoded>
			<wfw:commentRss>http://pradador.com/2009/10/07/fixing-lightboxs-click-handling-issues/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>DarkFloor ThemeForest Theme</title>
		<link>http://pradador.com/2009/10/02/darkfloor-themeforest-theme/</link>
		<comments>http://pradador.com/2009/10/02/darkfloor-themeforest-theme/#comments</comments>
		<pubDate>Sat, 03 Oct 2009 04:05:09 +0000</pubDate>
		<dc:creator>pradador</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[ThemeForest]]></category>
		<category><![CDATA[themes]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://pradador.com/?p=95</guid>
		<description><![CDATA[<p>The design used on my site is based on the DarkFloor Theme from ThemeForest.com. A couple CSS tweaks, some MooTools scripting, and I have something that works great for me. ThemeForest is a great source of Themes too and the prices are great. Even if you don't buy anything, the inspiration you can get is worth the visit.</p>]]></description>
			<content:encoded><![CDATA[<p>The design used on my site is based on the DarkFloor Theme from ThemeForest.com. A couple CSS tweaks, some MooTools scripting, and I have something that works great for me. ThemeForest is a great source of Themes too and the prices are great. Even if you don&#8217;t buy anything, the inspiration you can get is worth the visit.</p>
<p><a href="http://themeforest.net/item/dark-floor-html-template-6-pages-7-colors/52367"><img src="http://pradador.com/wp-content/uploads/2009/10/darkfloor-397x250.jpg" alt="Darkfloor Theme" title="Darkfloor Theme" width="397" height="250" class="alignnone size-large wp-image-94" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://pradador.com/2009/10/02/darkfloor-themeforest-theme/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Roll your own Subversion server, Roll-out Part 1</title>
		<link>http://pradador.com/2009/10/01/roll-your-own-subversion-server-roll-out-part-1/</link>
		<comments>http://pradador.com/2009/10/01/roll-your-own-subversion-server-roll-out-part-1/#comments</comments>
		<pubDate>Fri, 02 Oct 2009 01:19:53 +0000</pubDate>
		<dc:creator>pradador</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[guide]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[vps]]></category>
		<category><![CDATA[warehouse]]></category>

		<guid isPermaLink="false">http://pradador.com/?p=117</guid>
		<description><![CDATA[<p>In the first part of the configuration stage, we will prepare and test svnserve to interface with Warehouse. This involves creating a svnserve.conf file with the correct settings to protect and give access to our repository. We will also initialize Warehouse app which will link it to our repositories and allow web access to our code. In the next part we will link svnserve and Warehouse together and our set up will be complete!</p>]]></description>
			<content:encoded><![CDATA[<h3 id="svnserve_configuration">svnserve configuration</h3>
<p>By default, anonymous users can only read from our repository. Since we haven&#8217;t setup a login mechanism for svnserve, we are treated as anonymous users so we can&#8217;t check in any files yet. Let&#8217;s fix this. We will create a single svnserve.conf file and make symbolic links to it from each of our repositories&#8217; conf directories. User and directory access will be set with global password-db and the authz-db files rather than by tweaking each individual svnserve.conf (nightmare!).</p>
<p>The best part of this setup, we can coax Warehouse app to maintain these files for us and we can just do access rights from their interface.</p>
<h4 id="svnserveconf_file">svnserve.conf file</h4>
<p>Let&#8217;s create the svnserve.conf file:</p>
<pre><code class="shell">cd ~/repositories
nano svnserve.conf
</code></pre>
<p>Use these settings:</p>
<pre><code class="shell">[general]
anon-access = none
auth-access = write
password-db = /home/demo/repositories/passwd
#authz-db    = /home/demo/repositories/authz
realm       = Example Repository
</code></pre>
<p>As you can see, we have disabled anonymous access with the anon-access option. You could change this if all your repos will be public but I find it better to deny first and allow on a case by case basis. For now, I commented out the authz-db file so that we don&#8217;t have to manage it manually (nightmare!). Once Warehouse is in the loop, it will take care of this file for us.</p>
<h4 id="passwd_file">passwd file</h4>
<p>Now create the passwd file:</p>
<pre><code class="shell">nano passwd
</code></pre>
<p>And add your user account. The format is one username:password entry per line. Here&#8217;s mine:</p>
<pre><code class="shell">[users]
admin:password
</code></pre>
<h4 id="authz_file">authz file</h4>
<p>Next is the authz file. We&#8217;ll create it but leave it blank for now:</p>
<pre><code class="shell">touch authz
</code></pre>
<h4 id="configure_the_repositories">Configure the repositories</h4>
<p>Finally, let&#8217;s make our repositories use the newly created svnserve.conf file by creating symbolic links as follows:</p>
<pre><code class="shell">ln -fs /home/demo/repositories/svnserve.conf project1/conf
ln -fs /home/demo/repositories/svnserve.conf project2/conf
</code></pre>
<p>Make sure they were created correctly with the following:</p>
<pre><code class="shell">ls -l project1/conf
...
total 8
-rw-rw-r-- 1 demo demo 684 Sep 25 20:34 authz
-rw-rw-r-- 1 demo demo 309 Sep 25 20:34 passwd
lrwxrwxrwx 1 demo demo  37 Sep 25 22:16 svnserve.conf -&gt; /home/demo/repositories/svnserve.conf
</code></pre>
<p>Perfect. We now have a single svnserve.conf file with which to manage repository access. Be sure to do this for any future repositories you create or they won&#8217;t follow the global rules we have set up.</p>
<h4 id="test_out_your_account">Test out your account</h4>
<p>Finally, to make sure everything is working correctly, let&#8217;s check out a copy of one of your repositories.</p>
<pre><code class="shell">svn co --username admin svn://code.example.com/project1
...
Authentication realm: &lt;svn://code.example.com:3690&gt; Example Repository
Password for 'admin':
A    project1/trunk
A    project1/trunk/project1.txt
A    project1/trunk/newfile1.txt
A    project1/branches
A    project1/tags
Checked out revision 3.
</code></pre>
<p>Good, svnserve made us authenticate so no anonymous checkouts. Now let&#8217;s create a file and try to commit it. First create the file:</p>
<pre><code class="shell">cd project1/trunk
touch commitTest.txt
svn add commitTest.txt
...
A         commitTest.txt
</code></pre>
<p>Now let&#8217;s do a commit:</p>
<pre><code class="shell">svn commit -m "authentication test commit"
...
Adding         trunk/commitTest.txt
Transmitting file data .
Committed revision 4.
</code></pre>
<p>Looks good!</p>
<h3 id="warehouse_configuration">Warehouse configuration</h3>
<p>First step is to decide if you want urls to your repos to be done with subdomains or subfolders. By default, Warehouse serves your repos from reponame.code.example.com. I personally like this, but I also like Disco music so I know to not trust my instincts. DNS can be tough for some people to edit so I&#8217;ll just use subfolders for this guide. If you like the subdomain style you can skip these steps.</p>
<h4 id="enable_subdirectories">Enable subdirectories</h4>
<p>The right way to do this is to set the USEREPOPATHS=1 environment variable, but I can&#8217;t figure out how to do this with Nginx/Thin so let&#8217;s go with plan B and edit the environment.rb file instead. If anyone can enlighten me on how to set environment variables like this, I will update the guide. Anyway, let&#8217;s enable subdirectory access. From the warehouse directory, run:</p>
<pre><code class="shell">nano config/environment.rb
</code></pre>
<p>Find the line:</p>
<pre><code class="shell">#USE_REPO_PATHS = true
</code></pre>
<p>and uncomment it:</p>
<pre><code class="shell">USE_REPO_PATHS = true
</code></pre>
<p>Now restart your Thin cluster:</p>
<pre><code class="shell">sudo /etc/init.d/thin restart
</code></pre>
<h4 id="login_to_warehouse">Login to Warehouse</h4>
<p>Re-visit your webpage (http://code.example.com/) and set up the first repo and user as follows. Note that the username and passwords you use here will later be synced up for svnserve to use. You probably want to use the same data you used when making the passwd file. Here&#8217;s my install page filled out:</p>
<p><a href="http://pradador.com/wp-content/uploads/2009/10/warehouse-install.jpg"><img src="http://pradador.com/wp-content/uploads/2009/10/warehouse-install-175x250.jpg" alt="Warehouse Install" title="Warehouse Install" width="175" height="250" class="alignnone size-large wp-image-119" /></a></p>
<p>You will now see this page where you can just tell Warehouse to syncronize the first changeset:</p>
<p><a href="http://pradador.com/wp-content/uploads/2009/10/warehouse-sync.jpg"><img src="http://pradador.com/wp-content/uploads/2009/10/warehouse-sync-264x250.jpg" alt="Warehouse Sync" title="Warehouse Sync" width="264" height="250" class="alignnone size-large wp-image-120" /></a></p>
<p>And now you will be taken to your first repo in Warehouse where you should be able to see the files we checked in earlier:</p>
<p><a href="http://pradador.com/wp-content/uploads/2009/10/warehouse-home.jpg"><img src="http://pradador.com/wp-content/uploads/2009/10/warehouse-home-339x250.jpg" alt="Warehouse Home" title="Warehouse Home" width="339" height="250" class="alignnone size-large wp-image-118" /></a></p>
<p>That&#8217;s it! Warehouse is now linked to your repository. Take some time to play around and explore. Be sure to check out the guides at <a href="http://warehouseapp.com/">Warehouseapp.com</a> to get a feel for how the system works.</p>
<h3 id="next_steps">Next Steps</h3>
<p>Subversion is officially ready to roll. It has basic authentication set up and we can now commit and check out files as needed from it. Warehouse was also initialized and it works on it&#8217;s own for now. Come back once you&#8217;re done playing around for the next article where we will configure some hooks to keep our svnserve configuration up-to-date and to automatically synchronize change-sets to Warehouse.</p>
]]></content:encoded>
			<wfw:commentRss>http://pradador.com/2009/10/01/roll-your-own-subversion-server-roll-out-part-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Roll your own Subversion server, Warehouse Setup</title>
		<link>http://pradador.com/2009/09/30/roll-your-own-subversion-server-warehouse-setup/</link>
		<comments>http://pradador.com/2009/09/30/roll-your-own-subversion-server-warehouse-setup/#comments</comments>
		<pubDate>Thu, 01 Oct 2009 01:07:30 +0000</pubDate>
		<dc:creator>pradador</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[guide]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[vps]]></category>
		<category><![CDATA[warehouse]]></category>

		<guid isPermaLink="false">http://pradador.com/?p=112</guid>
		<description><![CDATA[<p>In part three of Roll your own Subversion server, we will download and install Warehouse on our server. We will also initialize the app by creating the necessary MySQL databases and users and we will configure the Thin/Nginx servers to begin serving the app. At the end of this guide all the groundwork will be done and we will then move to configure svnserve and Warehouse to our liking.</p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://warehouseapp.com/">Warehouse</a> is a Ruby on Rails application developed by <a href="http://entp.com/">entp</a> which provides a front end to your SVN repositories. It is quite useful because it provides a much better system to manage svnserve user management and access. It also lets you show your code to other users by providing them a direct link to the code which they can view in their browser instead of having to checkout a copy via SVN. Let&#8217;s get it installed.</p>
<h4 id="create_warehouse_db">Create Warehouse DB</h4>
<p>The first step is to create the MySQL databases which will house our Warehouse install. Login to mysql and execute the following commands:</p>
<pre><code class="sql">mysql&gt; CREATE DATABASE warehouse;
Query OK, 1 row affected (0.04 sec)

mysql&gt; CREATE DATABASE warehouse_test;
Query OK, 1 row affected (0.00 sec)
</code></pre>
<h4 id="create_warehouse_user">Create Warehouse User</h4>
<p>Next we will create a MySQL user specifically for Warehouse. By limiting the user&#8217;s access we can keep our MySQL database more secure as a compromise of this username and password will only give access to the Warehouse DB. Be sure to replace <em>some_pass</em> with a password of your choice:</p>
<pre><code class="sql">mysql&gt; CREATE USER 'warehouse'@'localhost' IDENTIFIED BY 'some_pass';
Query OK, 0 rows affected (0.01 sec)

mysql&gt; GRANT ALL PRIVILEGES ON warehouse.* TO 'warehouse'@'localhost';
Query OK, 0 rows affected (0.00 sec)

mysql&gt; GRANT ALL PRIVILEGES ON warehouse_test.* TO 'warehouse'@'localhost';
Query OK, 0 rows affected (0.00 sec)
</code></pre>
<h4 id="create_the_web_root">Create the web root</h4>
<p>Now let&#8217;s create a web root in our home folder where Warehouse will live:</p>
<pre><code class="shell">mkdir /home/demo/public_html
</code></pre>
<h4 id="install_ruby_subversion_bindings">Install Ruby Subversion bindings</h4>
<p>Before Warehouse can run, we need to install the Ruby Subversion bindings which, as the name suggests, lets Ruby interact with your SVN repo. I&#8217;ve never been able to get them installed by following their guide but luckily we can just use yum to install the necessary components:</p>
<pre><code class="shell">sudo yum install subversion-ruby
</code></pre>
<p>Now fire up IRB and let&#8217;s make sure it works:</p>
<pre><code class="ruby">irb
...
irb(main):001:0&gt; require 'svn/core'
=&gt; true
</code></pre>
<h4 id="download_warehouse">Download Warehouse</h4>
<p>Our system is finally ready for Warehouse. To download it, we simply clone Warehouse via git by doing the following:</p>
<pre><code class="shell">cd /home/demo/public_html
git clone git://github.com/entp/warehouse.git
</code></pre>
<h4 id="bootstrap_warehouse">Bootstrap Warehouse</h4>
<p>Now tell Warehouse to initialize itself by running the following command and follow the instructions presented on screen. You might run into a couple of &#8220;errors&#8221; I&#8217;ve detailed below but don&#8217;t worry about them for now, they won&#8217;t stop Warehouse from running.</p>
<pre><code class="shell">cd ~/public_html/warehouse
rake warehouse:bootstrap
...

Now it's time for Step 3: Load the database schema.  All of your data will be overwritten. Are you sure you wish to continue? [y/n]
y

mkdir -p /home/demo/public_html/warehouse/log
!! No Ultraviolet gem found, defaulting to javascript syntax highlighting.  Do not be afraid.
!! Error loading plugins: Mysql::Error: Table 'warehouse.plugins' doesn't exist: SELECT * FROM `plugins`   WHERE (name IN ('photo_gallery'))
!! Make sure the database was created successfully and migrated.
...

Warehouse v1.1.6 is ready to roll.
Okay, thanks for bootstrapping!  I know I felt some chemistry here, did you?
Now, start the application with 'script/server' and visit http://mydomain.com/ to start the installation process.
</code></pre>
<p>Sweet, we are ready to roll.</p>
<h3 id="configuring_thin">Configuring Thin</h3>
<h4 id="create_configuration_file">Create configuration file</h4>
<pre><code class="shell">cd ~/public_html/warehouse
sudo thin install
...
sudo thin config -C /etc/thin/warehouse.yml -c /home/demo/public_html/warehouse/  --servers 3 -e production
</code></pre>
<h4 id="start_thin">Start Thin</h4>
<pre><code class="shell">sudo /etc/init.d/thin start
...
[start] /etc/thin/warehouse.yml ...
Starting server on 0.0.0.0:3000 ...
!! Ruby 1.8.5 is not secure please install cgi_multipart_eof_fix:
   gem install cgi_multipart_eof_fix
Starting server on 0.0.0.0:3001 ...
!! Ruby 1.8.5 is not secure please install cgi_multipart_eof_fix:
   gem install cgi_multipart_eof_fix
</code></pre>
<p>Oops, install cgimultiparteof_fix</p>
<pre><code class="shell">sudo gem install cgi_multipart_eof_fix
</code></pre>
<p>Start Thin again</p>
<pre><code class="shell">sudo /etc/init.d/thin stop
...
sudo /etc/init.d/thin start
...
[start] /etc/thin/warehouse.yml ...
Starting server on 0.0.0.0:3000 ...
** Ruby version is not up-to-date; loading cgi_multipart_eof_fix
Starting server on 0.0.0.0:3001 ...
** Ruby version is not up-to-date; loading cgi_multipart_eof_fix
</code></pre>
<h4 id="optimize_thin">Optimize Thin</h4>
<p>Let&#8217;s check our memory footprint:</p>
<p><a href="http://pradador.com/wp-content/uploads/2009/10/Thin_with_3_Servers.jpg"><img src="http://pradador.com/wp-content/uploads/2009/10/Thin_with_3_Servers-640x244.jpg" alt="Thin with three servers" title="Thin with three servers" width="640" height="244" class="alignnone size-large wp-image-114" /></a></p>
<p>Yikes! Our memory usage is close to our 256MB limit and we are starting to page in/out of the swap space. Looks like three Thin servers is too much for our 256 MB slice. Let&#8217;s fix this. Stop the Thin cluster:</p>
<pre><code class="shell">sudo /etc/init.d/thin stop
</code></pre>
<p>Edit the Thin configuration file to deploy only two servers:</p>
<pre><code class="shell">sudo nano /etc/thin/warehouse.yml
</code></pre>
<p>Change the servers option From:</p>
<pre><code class="shell inline">servers: 3
</code></pre>
<p>To:</p>
<pre><code class="shell inline">servers: 2
</code></pre>
<p>Restart the Thin cluster:</p>
<pre><code class="shell">sudo /etc/init.d/thin start
</code></pre>
<p>Note: Be sure to stop thin BEFORE changing the amount of servers or you will end up with stray servers that don&#8217;t get shut down.</p>
<p>Check memory usage again:</p>
<p><a href="http://pradador.com/wp-content/uploads/2009/10/Thin_with_2_servers.jpg"><img src="http://pradador.com/wp-content/uploads/2009/10/Thin_with_2_servers-640x242.jpg" alt="Thin with two servers" title="Thin with two servers" width="640" height="242" class="alignnone size-large wp-image-113" /></a></p>
<p>Perfect, memory usage is now under 200 MB. Now, while it seems that the swap is still in use, it is actually the remains of what got paged there from our overload. It is not currently being paged in and out of. This is OK!</p>
<h3 id="configure_nginx">Configure Nginx</h3>
<h4 id="proxy_requests_to_thin">Proxy requests to Thin</h4>
<p>Open up the virual hosts configuration file:</p>
<pre><code class="shell">sudo nano /etc/nginx/conf.d/virtual.conf
</code></pre>
<p>and change the file contents to:</p>
<pre><code class="shell">upstream domain1 {
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
    }

server {
    listen   80;
    server_name code.example.com;

    access_log /home/demo/public_html/warehouse/log/access.log;
    error_log /home/demo/public_html/warehouse/log/error.log;

    root   /home/demo/public_html/warehouse/public/;
    index  index.html;

    location / {
        proxy_set_header  X-Real-IP  $remote_addr;
        proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect false;

        if (-f $request_filename/index.html) {
            rewrite (.*) $1/index.html break;
        }

        if (-f $request_filename.html) {
            rewrite (.*) $1.html break;
        }

        if (!-f $request_filename) {
            proxy_pass http://domain1;
            break;
        }
    }
}
</code></pre>
<p>This setup proxies all non-static requests (E.g. files that don&#8217;t exist on the filesystem in the public folder) to our Thin cluster.</p>
<p>Restart Nginx to apply the changes. I&#8217;ve heard that there&#8217;s some issues with the restart command so it doesn&#8217;t hurt to just start and stop the server:</p>
<pre><code class="shell">sudo /etc/init.d/nginx stop
...
sudo /etc/init.d/nginx start
</code></pre>
<h3 id="navigate">Navigate</h3>
<p>Now cross your fingers and navigate to your server to view the Warehouse app:</p>
<pre><code class="shell">http://code.example.com/
</code></pre>
<h3 id="nice">Nice!</h3>
<p>Believe it or not, we now have our Subversion system up and running. We have svnserve listening in the background to check our code in/out while a web-facing Warehouse allows us to browse our code in our favorite Browser. Warehouse is running off a MySQL database backend and powered by a small Thin cluster in a proxy setup with Nginx. All of this on a small 256 MB slice which costs about $10 a month.</p>
<p>Alright, well let&#8217;s not get over excited. There&#8217;s still plenty of work to do. We can&#8217;t actually do much with Warehouse yet! In the next article, we will configure Warehouse to actually interface with our SVN repositories for web access and even user management and access control.</p>
]]></content:encoded>
			<wfw:commentRss>http://pradador.com/2009/09/30/roll-your-own-subversion-server-warehouse-setup/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Roll your own Subversion server, SVN Setup</title>
		<link>http://pradador.com/2009/09/28/roll-your-own-subversion-server-svn-setup/</link>
		<comments>http://pradador.com/2009/09/28/roll-your-own-subversion-server-svn-setup/#comments</comments>
		<pubDate>Mon, 28 Sep 2009 22:05:03 +0000</pubDate>
		<dc:creator>pradador</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[guide]]></category>
		<category><![CDATA[setup]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[vps]]></category>

		<guid isPermaLink="false">http://pradador.com/?p=108</guid>
		<description><![CDATA[<p>In part two of Roll your own Subversion Server, we will setup our Subversion repository and enable the svnserve daemon to begin interacting with our code. This will be the home of all your repositories to treat it well!</p>]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re not familiar with SVN, Slicehost has a great <a href="http://articles.slicehost.com/2007/9/5/introduction-to-subversion">Introduction to Subversion</a> article which will bring you up to speed on the basics. It also has a whole subsection of <a href="http://articles.slicehost.com/tags/subversion">Subversion articles</a> which I highly recommend you read before continuing.</p>
<p>I&#8217;ll continue assuming you know how to do most of the stuff detailed in those guides. Specifically, we will deploy a svnserve instance listening on the default SVN port which will serve multiple repositories (not multiple projects) from a repository container in your home folder.</p>
<h4 id="install_subversion_and_git">Install Subversion (and git!)</h4>
<p>At this point, Subversion should already be installed on your system. If it&#8217;s not, this will take care of it:</p>
<pre><code class="shell">sudo yum install subversion
</code></pre>
<p>Now while this tutorial might be about Subversion, Warehouse is hosted at GitHub and the easiest way to download it is via git so let&#8217;s install that right now too. Git lives under the EPEL repository we installed Nginx from so this simple command should do:</p>
<pre><code class="shell">sudo yum install git
</code></pre>
<h4 id="create_your_repositories">Create your repositories</h4>
<p>Let&#8217;s begin by creating the folder to hold all of our repositories. We will also create a couple of test projects to get started. I will use the multiple repository type of layout where each project has its own repository. However, if you prefer something different, I&#8217;m sure you could easily adapt my guide to it.</p>
<p>From your home folder, run the following commands:</p>
<pre><code class="shell">mkdir repositories
...
svnadmin create repositories/project1
svnadmin create repositories/project2
</code></pre>
<h4 id="create_the_recommended_subversion_layout">Create the recommended Subversion layout</h4>
<p>Now let&#8217;s create a template folder which we can use to create the standard repo layout in newly created repos:</p>
<pre><code class="shell">mkdir -p repositories/svn_default/{trunk,branches,tags}
</code></pre>
<p>Import the default layout into our test repos:</p>
<pre><code class="shell">svn import /home/demo/repositories/svn_default file:///home/demo/repositories/project1 -m "initial import"
...
svn import /home/demo/repositories/svn_default file:///home/demo/repositories/project2 -m "initial import"
</code></pre>
<h4 id="create_some_projects">Create some projects</h4>
<p>Next create some dummy projects and import them into the repositories:</p>
<pre><code class="shell">mkdir project1
touch project1/project1.txt
...
svn import /home/demo/project1 file:///home/demo/repositories/project1/trunk -m "app import"

mkdir project2
touch project2/project2.txt
...
svn import /home/demo/project2 file:///home/demo/repositories/project2/trunk -m "app import"
</code></pre>
<p>We now have two separate repositories to play with.</p>
<h4 id="clean_up">Clean up</h4>
<p>Delete the original project folders as they are no longer needed</p>
<pre><code class="shell">rm -rf project*
</code></pre>
<h3 id="initialize_svnserve">Initialize svnserve</h3>
<p>Let&#8217;s setup svnserve to serve our repositories now. Be sure to read the <a href="http://articles.slicehost.com/2007/9/5/introduction-to-svnserve">Introduction to svnserve</a> guide first and follow the instructions on opening up the firewall for svnserve access on port 3690. Now start svnserve with the following command:</p>
<pre><code class="shell">svnserve -d -r /home/demo/repositories/
</code></pre>
<h4 id="autostart_svnserve">Autostart svnserve</h4>
<p>To make svnserve start automatically, add the following to your crontab:</p>
<pre><code class="shell">crontab -e

@reboot svnserve -d -r /home/demo/repository
</code></pre>
<h4 id="test_it">Test it</h4>
<p>Let&#8217;s check out one of our test projects on our computer and verify it is working correctly. On your local computer, run:</p>
<pre><code class="shell">svn co svn://code.example.com/project1
...
A    project1/trunk
A    project1/trunk/project1.txt
A    project1/branches
A    project1/tags
Checked out revision 2.
</code></pre>
<p>Everything looks good! We have our trunk/branch/tag structure and the file we checked in earlier is in there.</p>
<h4 id="security">Security</h4>
<p>The default svnserve configuration files allow for anonymous read access and authenticated write access. This might work for you but I&#8217;d like to secure the install a bit. However, I&#8217;ll hold off on that until we finish setting up Warehouse which we will use to secure svnserve.</p>
<p>It is also important to note that svnserve stores passwords on the server in a plain-text. This is not as bad as it sounds as authentication is done using the CRAM-MD5 mechanism so the passwords are never sent in the clear. So unless someone has physical access to the server, your passwords are safe. Of course, this might not be enough security for some users so a future upgrade will be to move to an Apache HTTP svn server which allows you to store passwords in a hashed format. But for now, the standard svnserve configuration will serve us well.</p>
<h3 id="end_notes">End Notes</h3>
<p>We have now finished initializing our repository home. Even without Warehouse, your server is fully functional as a simple SVN server. In the next part we will get Warehouse installed to make managing simpler to and to provide a front-end interface for our code repositories.</p>
]]></content:encoded>
			<wfw:commentRss>http://pradador.com/2009/09/28/roll-your-own-subversion-server-svn-setup/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss><!-- Dynamic page generated in 0.194 seconds. --><!-- Cached page generated by WP-Super-Cache on 2011-06-08 00:19:09 -->

