Unison dependency hell

UnisonI would really like to rid myself of Dropbox, but all the alternatives I’ve tried are too bloated, beta- or alpha-quality stage, too complicated to set up, or just plain don’t do what Dropbox does (minus the sharing stuff, which I don’t care about). I don’t want btsync, it’s closed-source. Seafile is too complicated, and makes dubious security claims. Owncloud is a cool project, but their file sync is slow, error prone, and has other limitations. There are some good services, but they don’t run on all the platforms I need, including Mac OSX, Linux x86 (32 and 64-bit), Linux ARMv6 (my Raspberry Pi B) and Android. I ran Syncthing for a while, but the continuous memory usage is pretty steep for the Pi, and I’ve experienced random silent file truncation in my shared directories with it. So I needed something else.

Enter Unison. I know I said I wanted it to be simple – bear with me for a moment. Until recently, I thought you needed to run Unison continuously and get some arcane config files set up perfectly in order to use it. This is not the case! As it happens, if you want to set up a star topology and just initiate Unison from some transient “points” of the star, all you really need is a system with some storage space to which you can SSH and run Unison to be the center of the star. I’ve got that, and I’m comfortable with the command line and scripting, so that helps a lot too.

The Unison documentation indicates you need the first two parts of the Unison version (e.g., 2.48) to match on each host in order for them to communicate. In a star topology, that means all the hosts need roughly the same version number. Here’s where I ran into trouble. Even after getting a Mac, amd64 Linux netbook and my Pi all onto 2.40.x, I kept getting the following error: Uncaught exception Failure("input_value: bad bigarray kind"). The Googs hinted that the problem may lie in the version of OCaml that was used to build Unison. OCaml? Don’t get me wrong, I liked learning ML in my Programming Languages course at University, but I haven’t used it since. I feel the need to use some salty language at this point, because clearly we are in bullshit territory.

There is really only one good reason for MacPorts, Homebrew, Fink, the *BSD ports system and all Linux distro repositories to offer a packaged version of Unison, and that is if you happen to want to run Unison in a completely homogeneous environment. Otherwise it won’t work. Save yourself the PITA. Seriously, just give up. I knew I wasn’t going to find some rainbow-farting unicorn version of Unison that was going to work between any two of my systems, especially since the version of OCaml that’s used to build it makes a difference. The only reason I spent any time looking for such a majestic unicorn is that compiling stuff on my Pi is a bit, er, pokey. But it seems I had no other choice.

The Mac is the most straightforward build, incredibly. I had a Homebrew version of Unison that I removed. Then I asked Homebrew for OCaml and got the latest stable release, 4.02.3 as of this writing. Then I downloaded the source tarball from the Unison site (2.48.3) and built with make UISTYLE=text NATIVE=true STATIC=false. I first tried STATIC=true here, but that was just silly, because nobody would ever want a statically-built binary, and also because you just can’t do that on a Mac. I copied the built binary to $HOME/bin/unison so as not to trespass on Homebrew’s territory in /usr/local.

On the Linux netbook, Ubuntu wasn’t offering the version of OCaml I needed, so I installed the opam package and used the install instructions for getting the latest version of OCaml. Then I compiled the source of Unison, but used the STATIC=true option this time. Then I again copied the binary to my home directory.

The Pi is where I had the most difficulty. There are only old OCaml versions offered in Raspbian, and there’s no opam package. This is where the binary installer came in handy. Running this to get opam, telling opam to download and use 4.02.3 with the switch command, and finally compiling the Unison source again takes a long time.

Other tips:

  • Make sure to set $UNISONLOCALHOSTNAME on all the “points” of your star, so that if their IP changes, they don’t trigger a new archive index.
  • I wrote scripts on each point host that does a few checks, then runs The batch option is good for trying to do the right thing automatically and without asking any questions after the first successful synchronization.

If you care to avoid the suck detailed herein, I’m providing binaries (with NO warranty, of course).


Unison dependency hell is original content from devolve.