DIY DDNS

For those of us on cable or DSL who are slightly too cheap to pay for a static IP, dynamic DNS services are really useful. My DD-WRT based router knows how to talk to dynamic DNS providers, so setting it up is really easy.

I’ve tried both DynDNS and No-IP, and while they work quite well they’re kind of annoying. They really want me to sign up for a premium service, after all that’s how they make money. As a result I need to periodically visit web pages to confirm that I’m using an address or pay a fee. It’s not a big fee, but I’m already paying someone, DreamHost to host DNS for me, and they’ve got an API

So I threw together a little script that implements the DynDNS API and modifies your own DNS zones using the DreamHost API. You can get it from here:
https://github.com/ianloic/dreamhost-ddns

The setup instructions are included in the README. Hopefully they’re pretty self-evident, but they are written from the perspective of someone who ran their own DNS servers (primary and secondary) for ten years.

Tracking WordPress using Git

Update: I don’t do this anymore.

I publish this blog through WordPress, for reasons I’ve outlined before. I run it with a custom theme and a bunch of plugins though, and I wanted a convenient way to keep my WordPress install up to date without having to reinstall everything all the time. I wanted source control for my blog install.

My first attempt involved mirroring WordPress SVN into a Git repository on github so that I had a Git version of the SVN tree (including branches, tags and every checkin separate) and seperate repository holding the changes I’d made for my web site. This eventually failed for two reasons, first the script I was using to mirror the SVN into Git had a habit of failing in bizarre ways and secondly having two repositories confused me.

Yesterday I decided to update my fairly outdated WordPress install, it had been missing security fixes for some time and was one minor version behind. Since tracking SVN hadn’t worked I tried a simpler approach, a single Git repository containing a master branch that tracks releases and an ianloic.com branch to track the state of my site.

I set up master with a fresh download of WordPress 2.5 from wordpress.com, created my ianloic.com branch and applied the differences between my site and the 2.5 SVN tag (for all it’s failures my old approach at least let me do this easily). I switched back to the master branch, deleted all the files (leaving my .git directory intact) and unpacked the new WordPress 2.6.1 tarball. I checked that in (to the master branch), tagged it 2.6.1 and then merged that into my ianloic.com branch. I pushed all that to github and then checked it out on my web server (at Dreamhost).

Normally with Git you’re tracking just the master branch, but I want both master and ianloic.com branches to be tracked so my .git/config contains:

[remote "origin"]
	url = git@github.com:ianloic/wordpress.git
	fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
	remote = origin
	merge = refs/heads/master
[branch "ianloic.com"]
	remote = origin
	merge = refs/heads/ianloic.com

Now it’s easy to track changes that I’m making to my site and update to the latest WordPress without risking losing anything. The process for updating to a new WordPress release is:

  • on my laptop check out the master branch
  • rm all the files except for .git from the directory
  • unpack the new release into the directory
  • git-add . — now git-status will indicate what has changed, been added or removed
  • git-commit to check in the new version of wordpress
  • git-tag versionnum to tag which version is currently in master
  • git-checkout ianloic.com
  • git-merge versionnum to merge the latest version into the site’s branch
  • git-push –all –tags to push all the branches and tags to github
  • on my web server, git-pull to update to the latest release

I end up with a tree that looks like this:

ianloic.com WordPress in Git

Installing Ruby Gems in your home directory

NOTE: Updated for RubyGems 1.3.7

I’ve been playing with Ruby in my cheap shared hosting provider. They don’t include everything I need so I had to install Ruby Gems in my home directory. The instructions don’t work. So here’s what I did…

First set up environment variables to tell Ruby and Gems where to find stuff:

export GEM_HOME=$HOME/lib/ruby/gems/1.8
export RUBYLIB=$HOME/lib/ruby:$HOME/lib/site_ruby/1.8

Download and unpack the Gems source (this is the version I downloaded, you should grab the latest:

wget http://rubyforge.org/frs/download.php/70696/rubygems-1.3.7.tgz
tar xzvf rubygems-1.3.7.tgz
cd rubygems-1.3.7

Run the setup.rb script with the right arguments to install into your home directory:

ruby setup.rb all --prefix=$HOME
ln -s $HOME/bin/gem1.8 $HOME/bin/gem

This will install the gem command into $HOME/bin and the Gems source into $HOME/lib/site_ruby. Gems will be installed into $HOME/lib/ruby/gems/1.8. You should add $HOME/bin to your path. If you want to install it somewhere else replace $HOME with the prefix you’d like to use.

OpenID for the mathematically challenged

The other day I got the OpenID bee in my bonnet and grabbed James Walker‘s module and installed it on my server. Actually I grabbed it from CVS, and then discovered that the CVS version is half-ported to some new Drupal 6 form API, so I ended up using the DRUPAL-5 tag.

Anyway, I use Dreamhost which I love for many many reasons (primarilly it’s really cheap and seems to work really well). Unfortunately they don’t build their PHP with BCMath or even GMP, which means my PHP can’t do the hard math that’s required for crypto. Luckily there’s a mode of OpenID that doesn’t require any work on the relaying party side. So I made a small change that allows James’ module to work in this “dumb” mode.

Index: openid.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/openid/openid.install,v
retrieving revision 1.2
diff -u -p -r1.2 openid.install
--- openid.install      25 Mar 2007 06:38:00 -0000      1.2
+++ openid.install      16 May 2007 22:59:56 -0000
@@ -2,24 +2,6 @@

/**
- * OpenID module requires bcmath
- */
-function openid_requirements($phase) {
-  if ($phase == 'runtime') {
-    $requirements['bcmath']['title'] = t('BCMath');
-    if (function_exists('bcadd')) {
-      $requirements['bcmath']['severity'] = REQUIREMENT_OK;
-      $requirements['bcmath']['value'] = t('Enabled');
-    }
-    else {
-      $requirements['bcmath']['severity'] = REQUIREMENT_ERROR;
-      $requirements['bcmath']['description'] = t('OpenID needs the bcmath extension for encryption.');
-    }
-  }
-  return $requirements;
-}
-
-/**
* Implementation of hook_install
*/
function openid_install() {
Index: openid.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/openid/openid.module,v
retrieving revision 1.2
diff -u -p -r1.2 openid.module
--- openid.module       25 Mar 2007 06:38:00 -0000      1.2
+++ openid.module       16 May 2007 22:59:56 -0000
@@ -133,10 +133,14 @@ function openid_login_form_submit($formi

$idp_endpoint = $services[0]['uri'];
$_SESSION['openid_idp_endpoint'] = $idp_endpoint;
-  $assoc_handle = openid_association($claimed_id, $idp_endpoint);
-  if (empty($assoc_handle)) {
-    drupal_set_message(t('OpenID Association failed'), 'error');
-    return;
+
+  // if we have BCMath, we should use OpenID smart mode
+  if (function_exists('bcadd')) {
+      $assoc_handle = openid_association($claimed_id, $idp_endpoint);
+      if (empty($assoc_handle)) {
+        drupal_set_message(t('OpenID Association failed'), 'error');
+        return;
+      }
}

Also, I put the patch up on Drupal.org