I've been contemplating improving my backup strategies lately.
Last year, I signed up with Backblaze to back up my MacBook to the cloud. There are a few players in this arena, another is Carbonite.
But off-site backup is only one leg of the backup stool. The wisest course for backup is a 3, 2, 1 strategy. That is to have three copies of your data, on two media (i.e. at least one of the copies should be on a different medium than the others), and one of the three should be offsite.
I consider on-line backup (a la Backblaze) to be a different medium, where rather than the medium just being a hard disk it's the whole off-line backup company's infrastructure.
Offline/offsite backup is really targeted for disaster recovery, if the building housing my on-site backups was destroyed by fire, or some other calamity, along with those backups I could recover the data from backblaze, but it would take a while to get it, either by downloading or getting them to ship me an external hard disk.
And for certain important data, I also use DropBox which can not only save data to the cloud, but sync that data between multiple machines. To make sure I've got a copy of the contents of this blog, I have a cron job on the Linux server where it runs which does a sql dump of the database to a dropbox folder, along with any new files (images, documents, etc) used by the blog. This runs in the wee-dark hours, and every morning, my MacBook informs me that DropBox has copied that data down to my MacBook.
But I've been feeling a gnawing need for better on-site backup, with faster access for either full recovery, or to get back a mistakenly deleted, or corrupted file.
One requirement is that the backups be done automatically. I've got too many other things on my mind than to remember to backup frequently, that's what I have computers for. Also I want the backups of my Macbook to work anywhere it can access the LAN. I tend to use my MBP in various areas of the house, upstairs in my office, where it's next to the server, and can be jacked into the same ethernet switch as the server, but also in the family room and even the bedroom, where it's connected by wi-fi.
TimeMachine
I've been wanting to use Apple's TimeMachine for a while, but haven't had the necessary hardware. I'd been thinking about buying a TimeCapsule, but I've been just a little leery since several of my friends have had their TimeCapsules die within a year.
I did a bit of research, and came up with the idea of looking at using my Linux server to hold a TimeMachine backup. The box has several available drive bays, and I could get a 2TB WD SATA drive for $120. With the cable and tax it came to just around $150.
But first I wanted to make sure that it would really work.
Existing How-Tos
I asked my friend Google about TimeMachine and Ubuntu and the first hit was a detailed how-to on kremaliscious.. Unfortunately that how-to is about two years old. Fortunately it still pretty much applies, but things have been simplified a bit.
That how-to, which was last updated when the latest Ubuntu was 8.04, "Hardy Heron" and the latest OS X was still 10.5.x, "Leopard", describes building a custom debian package for netatalk to add support for ssh connections. Netatalk is an open source implementation of Apple's AppleTalk Protocol Suite. I also encountered a much more succinct article by my old OTI friend Andrew "Roo" Low, which did the same.
For context, I'm running Ubuntu 10.04, "Lucid Lynx", on the Linux box, and OS X 10.6.4, "Snow Leopard" on the MBP.
A comment near the end of a long string of comments in that first article indicated that a custom netatalk package was no longer necessary, since the standard debian/ubuntu netatalk package now has ssh support. But following the rest of the instructions got me to the state where my Mac could see the shared volumes on the server, but when I tried to connect to them, I couldn't authenticate.
Figuring that I really did have to build a custom netatalk package, I followe Roo's article and built one. But it ended up in the same place.
It turned out that the crucial bit was a change to the configuration of netatalk's afp configuration.
The article gives the following configuration line in /etc/netatalk/afpd.conf
- - transall -uamlist uams_randnum.so,uams_dhx.so -nosavepassword -advertise_ssh
But with the current netatalk this needs to be changed to:
- - transall -uamlist uams_randnum.so,uams_dhx2.so -nosavepassword -advertise_ssh
This is actually mentioned in comment 330 (of 670!) but I missed it.
After making that change, I could connect to the shares. So I removed my custom netatalk package and installed the standard one, and it still works.
Avahi setup
Netatalk is one half of what's needed to have a Linux box participate in an Apple friendly network. The other half is Avahi which is an open source implementation of the Zeroconf standard or what Apple calls Bonjour. Bonjour/Zeroconf is how Macs find services on the local network.
Most current linux distributions include Avahi, as does Ubuntu 10.04, so it was just a matter of configuring it. The instructions in the kremaliscious article are fine. However, while I was at it, I also configured Avahi to publish a VNC server which allows me to easily start a graphic login to the server from the Mac finder. Bonjour uses the service type rfb (remote frame buffer) for the VNC server. To get this working I followed this article. I combined the configuration of both the afpd and rfb services into a single configuration file in /etc/avahi/services/multi.service
Here's that file:
<?xml version="1.0" standalone='no'?><!--*-nxml-*--> <!DOCTYPE service-group SYSTEM "avahi-service.dtd"> <service-group> <name replace-wildcards="yes">%h</name> <service> <type>_rfb._tcp</type> <port>5901</port> </service> <service> <type>_afpovertcp._tcp</type> <port>548</port> </service> <service> <type>_device-info._tcp</type> <port>0</port> <txt-record>model=Xserve</txt-record> </service> </service-group>
File Server Setup
First I configured netatalk to give me a test 'drive' by publishing a directory in my own home directory on the linux box. Once I'd proved to myself that TimeMachine could in fact connect to this, it was time to buy that drive and hook it up.
I make it a standard procedure to install disks on Linux under control of LVM. Here's a pretty good and succinct guide on getting started with LVM on Ubuntu.
So I installed the drive, and set it up as an LVM Physical Volume called FileServer, I then added a couple of logical volumes to the group:
sudo lvdisplay --- Logical volume --- LV Name /dev/FileServer/TimeMachine VG Name FileServer LV UUID VIdN7y-0gDa-1Azr-0oYB-MRj3-Woxt-Utyef8 LV Write Access read/write LV Status available # open 1 LV Size 1.50 TiB Current LE 393216 Segments 1 Allocation inherit Read ahead sectors auto - currently set to 256 Block device 251:3 --- Logical volume --- LV Name /dev/FileServer/MunimulaClone VG Name FileServer LV UUID Y36agh-Tgnk-1dcf-34tw-AJLm-1Mc2-jcqsuk LV Write Access read/write LV Status available # open 0 LV Size 320.00 GiB Current LE 81920 Segments 1 Allocation inherit Read ahead sectors auto - currently set to 256 Block device 251:4
I gave TimeMachine 1.5 terabytes to play with, and reserved enough to hold a snapshot of my laptop drive in MunimulaClone. Munimula is the name I gave my MacBook pro, inspired by it's construction and a childhood memory. I then installed an ext3 filesystem in both of these logical volumes.
I set up /etc/fstab to mount these in to mount points in the /var directory
/dev/FileServer/TimeMachine /var/TimeMachine ext3 /dev/FileServer/MunimulaClone /var/MunimulaClone ext3
Following Roo's suggestion I created an empty file “/var/TimeMachine/.com.apple.timemachine.supported” with the touch command, and on the Mac I executed the command:
defaults write com.apple.systempreferences TMShowUnsupportedNetworkVolumes 1
Then I added the following two lines at the end of /etc/netatalk/AppleVolumes.default to publish the two network volumes:
/var/TimeMachine TimeMachine allow:rick cnidscheme:cdb options:usedots,upriv /var/MunimulaClone MunimulaClone allow:rick cnidscheme:cdb options:usedots,upriv
I did run into the problem encountered by others of TimeMachine giving an error that it couldn't create the backup disk image, but IIRC this only happened once, it created a file called munimula.tmp.sparsebundle, and removing the .tmp from the file name seemed to allow TimeMachine to proceed.
Results
With the MBP connected via an ethernet cable through a switch to the linux box, the first backup (about 290GB) took around 11-12 hours. It had just finished when I checked this morning. The second 'hourly' backup took just a few minutes. I then disconnected the hard-wired connection and brought the laptop downstairs.
It didn't seem to automatically start a new backup cycle over wifi when it should have, but getting it started by holding the mouse down over the TimeMachine icon in the dock until the menu appeared and then selecting "Back up now" got things kicked off, and it's been taking hourly backups wirelessly all day so far. The hourly backups take a bit longer, may 10-15 minutes. I'm not sure if that's because of lower bandwidth over wifi, or just because I've been using the laptop, and there's more delta data than there was first thing in the morning.
So far I'm pretty happy with the setup, I'll update this article should any surprises occur, good or bad.
Today was the day to upgrade the server running this blog to Ubuntu 9.10 "Karmic Koala".
Late in the upgrade, during the process of installing and configuring the Debian packages, the upgrade hung. I had just tried to stop bind9 and given an series of error messages indicating that rndc was unable to communicate with bind9.
After waiting a while I hit control-c and was warned that this might leave the system in an inconsistent state, but I figured I had little to lose, so I clicked ok. The upgrade continued, but didn't reboot, saying that there had been a problem
I tried to start bind9 manually, both with rndc start, and /etc/init.d/bind9 start but only got bad news.
So I then tried to start it while tailing the syslog, and noticed that I was getting an error about a failure to open /etc/ssl/openssl.cnf for read. This was strange since the permissions on that file allowed reading by anyone.
A little googling eventually revealed that I was running afoul of AppArmor, something I hadn't encountered before. It turns out that Ubuntu doesn't automatically include an AppArmor profile for bind9, not sure why.
The solution seems to have been to manually install the apparmor-profile package with apt-get.
After verifying that I could manually start bind9 and talk to it with rndc, I rebooted, and as they say "so far so good."
Yesterday, I wrote about the crash project to resurrect this blog after a hardware failure. I'm now running it on an upgraded version of Typo (5.2 instead of 4.1), using Passenger on Ubuntu 8.10 (instead of a cobbled up stack of Apache, Pen, and Mongrel::Cluster on Ubuntu Dapper), and deployed from my MacBook using Capistrano with git as the source repository. I've been wanting to do a lot of this for a while, but never seemed to have the time. The crash gave me the motivation, and the necessity.
This article is to let me capture what I can remember while it's still fairly fresh in my memory, and hopefully provide help to others with similar goals.
Installing Passenger on Ubuntu 8.10
A bit of help from my friend google, led me to this how-to which I followed. I'm not entirely happy with the approach, since it installs Ruby using the debian package, and I generally prefer to install it from source. I also thought that it installed Rubygems from a package, but looking at it now it seems to have installed it from source, but installed in in /usr/bin which may not be the wisest place on a debian system, it really should be in /usr/local/bin or somewhere else that dpkg/apt-get doesn't muck with. I might need to straighten that out.
I had to hack his scripts a bit as well. They assume that the current directory is on the path, which is something I don't like to do, so I went through and added './' where necessary.
Finally, his script for upgrading to enterprise Ruby for improved performance didn't work, so that's a job for later.
I posted a few comments on the article about this, but as of now they are waiting for moderation.
Typo Upgrade
For those who haven't used it typo comes a a gem which provides a typo command, you use it to either install typo
typo install typo_dir
Either installs the latest version of typo, which is really just a rails app, in typo_dir, or upgrade an existng version.
One of the first things the upgrade does is to backup the database to a yml file. For a blog like mine with a lot of content, this took forever. As I sat there waiting, it occurred to me that I already had a mysql backup, which I'd already used to recreate the database, so I killed the upgrade and hacked the rails-app-installer gem (which typo uses) to skip the backup.
The next hurdle was a gem version problem. I got to the point where the upgrade script was trying to migrate the database, but Rake was failing
Migrating Typo's database to newest release rake aborted! RubyGem version error: actionpack(1.13.3 not = 1.13.6)
This was particularly strange since Typo 5.2 runs on Rails 2.2. Somebody was loading the wrong version of rails, and then complaining about the wrong version of actionpack. And the 1.13.6 version of the actionpack gem doesn't seem to be around anymore, probably left behind when Rails moved to github.
So I asked on the typo mailing list, and my former co-worker Ben Burdick gave me the solution:
sudo gem install datanoise-actionwebservice --source http://gems.github.com
This got me up to the point where I could run the blog on the MacBook. I used the very nice Passenger pane, you just drag the folder containing your rails project into the pane, and restart, and your app is running! Since I wanted to urls to match up. I told passenger pane to use a url of talklikeaduck.denhaven2.com instead of something.local, and put an entry into /etc/hosts to point that name to local host.
Once I was there, it was a matter of recreating the articles which had been lost since the last backup. Mark Imbriacco emailed me what he had cached for each article in his RSS reader. It turned out to be a pretty simple job of cutting and pasting, and telling Typo to publish the articles on their original dates which could be determined by the permalink urls. I didn't worry about the exact time.
I then did a mysqldump of the database, shipped it over to the server with scp, and recreated the database on the server.
Capistrano Deployment
Now the task was setting up Capistrano and having it get the code from git. For the time being I set up a git repository in my home directory on the server, and pushed the code to it from the MacBook over ssh.
The next step was to allow the apache user (which is www-data on debian based systems) to access the repo. This was a matter of generating a public/private key pair in the www-data users home directory, adding the public key part in the .ssh/authorized_keys file in MY home directory, and a
sudo su - www-data ssh rick@localhost # answer yes to the prompt to add the host being connected to exit
I then upgraded my capistrano gem and capified my typo project. Then I edited the config/deploy.rb based on a couple of blog posts and some trial and error.
set :application, "talklikeaduck" set :repository, "ssh://rick@aaa.bbb.ccc.ddd/home/rick/git/tlad.git" set :scm, :git set :branch, "master" set :deploy_via, :remote_cache set :user, "www-data" set :runner, "www-data" set :deploy_to, "/var/www/rails/#{application}" role :app, "aaa.bbb.ccc.ddd" role :web, "aaa.bbb.ccc.ddd" role :db, "aaa.bbb.ccc.ddd", :primary => true namespace :deploy do desc "Restarting mod_rails with restart.txt" task :restart, :roles => :app, :except => { :no_release => true } do run "touch #{current_path}/tmp/restart.txt" end [:start, :stop].each do |t| desc "#{t} task is a no-op with mod_rails" task t, :roles => :app do ; end end end desc "Link in the production database.yml" task :after_update_code do run "ln -nfs #{deploy_to}/#{shared_dir}/config/database.yml #{release_path}/config/database.yml" end
Note that I've replaced the lan address of the server with aaa.bbb.ccc.ddd, it probably wouldn't be a security exposure to show the real address behind the nat, but paranoia is paranoia. Normally I'd use a local dns server name, but I haven't gotten around to setting that back up.
Getting this working was a matter of trying cap deploy:check until I ironed out permissions issues, usually by sshing into the server creating files using sudo, then chowning them to www-data.www-data, since www-data doesn't have sudo privileges.
Then I worked on getting cap deploy:cold to work. More sshing, mkdiring, and chowning to set up the current, releases and shared subdirectories. I'd scratched my head a bit about what to do with config/database.yml which I'd gitignored as usual. Ben pointed me to a blog article which added a post setup task to upload it to the shared directory, but it turned out to be easier to just do it via scp and ssh.
If I recall correctly, the next hurdle was familiar, cap:deploy cold was failing for the same reasons as on the Mac, the gem version problem killing Rake. The solution here was to rake gems:push, git a
rake gems:unpack git add vendor/gems git commit git push origin cap deploy:cold
Now I ran into a problem because I'd missed a bit of code in the deploy.rb from the article I was using a model. It was this piece:
[:start, :stop].each do |t| desc "#{t} task is a no-op with mod_rails" task t, :roles => :app do ; end end
Without this capistrano was trying to get the www-data user to sudo to run script/spinner. Before I noticed the omission I was considering writing scripts to stop the server by disabling the virtual host, and reloading apache, and starting in in a similar manner, and giving www-data limited sudo privileges to run those scripts. It turns out that this is unnecessary using Passenger, so it was just a matter of overriding the default capistrano tasks to do nothing.
So now there was joy in Mudville. The cap deploy:cold worked. At this point I created a vhost configuration in /etc/apache2/sites-available, used a2ensite to enable it, and reloaded apache. Now to check it out.
One Last Wafer Thin Mint
Back on the MacBook, I edited /etc/hosts to now point to the servers lan address. I still wasn't ready to expose port 80 of the server to the internets.
I cranked up my browser and reloaded the url. Everything was working! But being the suspicious type, I wanted to make sure. Tailing the log on the server showed no acivity, hmmmm?
I pinged talklikeaduck.denhaven2.com on the MacBook, and it was pinging 127.0.0.1. I knew that I'd changed /etc/hosts. Ben told me over ichat to try dscacheutil -flushcache, which seemed to have no effect. So I rebooted the MacBook, and it was still resolving talklikeaduck.denhaven2.com to localhost.
At that point I tried:
$ dscacheutil -q host 127.0.0.1
Which produced:
name: talklikeaduck.denhaven2.com ip_address: 127.0.0.1 name: localhost ip_address: 127.0.0.1 name: talklikeaduck.denhaven2.com ip_address: aaa.bbb.ccc.ddd
So there were two cache entries, and the local host one was winning.
I finally got a clue when I grepped /etc for references to talklikeaduck, and found one in /etc/hosts, but also one in /etc/apache2/sites-available/tlad which was the vhost configuration generated by Passenger pane. When I removed the blog project directory from the Passenger pane, and hit restart, then did the dscacheutil -flushcache, the name was now resolving to the server.
Now I was hitting the server, and I did a little more prodding to make sure things were working, including writing my resurrection announcement.
Now I was finally ready to unblock port 80 on the router.
Hopefully someone will find something useful in this post, at least I've captured the lessons I learned from the exercise.

I live in the fastest growing corner of one of the fastest growing counties in the US.
Lately that has seemed to come with more than my share of power interruptions.
This blog is hosted on a ‘server’ in my home office, which also hosts several other things, some for internal use, and
others, like talklikeaduck are public facing. Besides this blog I have a
wikimedia based site on the technical history of
Project Mercury, a personal interest of mine.
One of my frustrations of late has been the fact that the blog doesn’t suffer those power interruptions well.
For deployment, I’m using a combination of Apache 2.0, with pen for load balancing, and mongrel_cluster. That last has
been the main source of that minor annoyance. The version of mongrel_cluster I’ve been using doesn’t properly deal with
stale pid files, so that when the system reboots after a power outage, the blog doesn’t come back without manual
intervention.
My frustration level finally rose to the point where I started to look for a solution.
Stable vs. Backwater
The sharp eyed might notice that I’m using Apache 2.0 instead of the later versions which support
mod_proxy_load_balancer. The reason is that the server is running Ubuntu Dapper which doesn’t have the latest Apache, and
since I have so much other stuff running, I haven’t wanted to attack that problem. Don’t ask me about my php4 to php5
platform migration plans, either. Wikimedia moved on to PHP5 some time back, and I’ve stopped moving with it.
I’m running Dapper since that’s the latest Ubuntu LTS release.
It’s the usual dilemma of wanting a stable server vs. being left behind.
For things like Ruby, where I’ve got the time and interest to spend, I’ve gone to installing from source rather than
debian packages. This allows me to keep up, and gets around things like the issues between the views of the debian
maintainers and the rubygems folks about how software should be installed.
Searching For Religion
A few weeks ago, I started
hearing about god, a new ruby server monitoring framework.
So I installed god, only to find that it wouldn’t install in Ubuntu Dapper. I asked about this on the ruby-talk forum,
and the developers seemed to agree with me that it might be nice if, as a server oriented offering, god supported Dapper.
So I’ve been waiting for god to come to Dapper, but with after another power outage this morning, I decided to look at
alternatives
God is inspiring, but who inspired god?
God is actually patterned after another non-ruby offering called monit.
Monit has been around awhile, has been packaged for debian, and even is available in packaged form for dapper.
It’s also showed up recently in several
of the rss feeds I monitor.
I think it’s fair to say that monit:god :: make:rake.
Monit and Mongrel_Cluster
So this morning I installed monit, and started to configure it.
While in the midst of doing this I started wondering how best to configure it to monitor a mongrel cluster. Monit
is a daemon which periodically examines things like pid files and sees if the processes which they reference are still
running. It can be configured to automatically restart services when they die, restart them under certain load conditions,
etc.
The problem is that mongrel_cluster is really responsible for multiple processes, and I was scratching my head over
how to map this to monit for a few seconds before resorting to google. I noticed that, as I predicted,
others had been
there or in
similar places
before.
Aha! There’s a new Mongrel_cluster
While perusing the words of wisdom from the pioneers, I noticed that those who had setup monit to monitor clusters of
mongrels were mentioning the need for
version 1.0.1
So, as directed I did a
sudo gem install mongrel_cluster --source http://mongrel.rubyforge.org/releases/
But when I tried it out, with
mongrel_rails cluster::status
mongrel_rails couldn’t find the
cluster::status command.
At this point I couldn’t restart my blog, so I uninstalled the 1.0.1 version of mongrel_cluster, tried to start it again
and, relieved when it did start, looked for a solution.
My first thought was to see if maybe there was an even later version of mongrel_cluster. Doing a gem list —remote,
showed that there as a 1.0.2 in the normal source. So I installed that, and, same problem.
Then, with a little help from google, I uninstalled the earlier version of mongrel_cluster, and lo and behold, the new
cluster commands worked.
Permissions problem
But then I ran into another problem. Starting the blog was thowing an exception because of a permissions problem.
I use an init script to start mongrel_rails, and mongrel_rails runs as a particular user. The mongrel_cluster init file looks
for existing pid files, and it uses a sequence which changes to the working directory specified in the mongrel cluster
configuration, looks for the file, then changes back to the old working directory. But the user running it didn’t have
permission to my home directory which was I started, so it failed when on that change back.
The solution was to change myinit script to change to the rails root of my typo installation before invoking mongrel_rails. Problem solved.
Still waiting for god(ot)
So what of monit?
Now that I’ve got the new version of mongrel_rails, which properly handles stale pid-files, I’m less motivated to setup
monit. I do like the monitoring functions it provides, so I might still pursue it, but on a less urgent priority.
On the other hand I just might wait for god to bless Dapper, or for the next
Ubuntu LTS release, whichever comes first.




