The odyssey of unison on a NAS blog home

Posted Sunday, 22-Nov-2020 by Ingo Karkat

I have a Synology DS220j NAS, used mostly for file shares and as a backup host. However, it would also be great to host a central repository for the Unison file synchronizer, which I use for the configuration and tool parts of my home directory, to have a consistent environment on all of my hosts.

Okay, let's see what it takes. There are several posts on the Internet, e.g. this one from 2015, using unison 2.40, or this one from 2012, also unison 2.40.

I already know the ipkg package manager from my previous Linksys NSLU, and this post describes how to install it. Then, the build environment for Unison can be obtained via:

sudo ipkg install ocaml make gcc textutils

Unison 2.48 + Ocaml 3.12

Trying with unison-2.48.15v4 and Ocaml 3.12.0-2:

$ make UISTYLE=text NATIVE=false
ocamlc: unknown option `-unsafe-string'

A simple patch to the Makefile fixes this:

--- src/Makefile.OCaml.orig     2020-11-16 20:34:17.527454957 +0100
+++ src/Makefile.OCaml  2020-11-16 20:34:20.417497004 +0100
@@ -95,7 +95,7 @@
### Default parameters

# Generate backtrace information for exceptions
-CAMLFLAGS+=-g -unsafe-string
+CAMLFLAGS+=-g

INCLFLAGS=-I lwt -I ubase -I system
CAMLFLAGS+=$(INCLFLAGS)

I've got a binary, and it seems to work (the selftest error happens on Ubuntu 16.04 x64, too; doesn't inspire a lot of confidence in the project, but hey):

$ unison -selftest
Contacting server...
Running internal tests...
fastercheckUNSAFE 1...

Fatal error: Skipping some tests -- remove me!
$ unison
Usage: unison [options]
    or unison root1 root2 [options]
    or unison profilename [options]

For a list of options, type "unison -help".
For a tutorial on basic usage, type "unison -doc tutorial".
For other documentation, type "unison -doc topics".

Unfortunately, an actual file sync with an Ubuntu 16.04 client fails:

UNISON 2.48.3 started propagating changes at 21:37:47.30 on 20 Nov 2020
[BGN] Updating file .bashrc from //synology//volume1/homes/inkarkat/backup/Unixhome to /home/inkarkat/Unixhome
[BGN] Updating file .profile from //synology//volume1/homes/inkarkat/backup/Unixhome to /home/inkarkat/Unixhome
Unison failed: Uncaught exception Failure("input_value: bad bigarray kind")
Raised by primitive operation at unknown location 

I found a post mentioning that there was also an internal change in the OCaml libraries somewhere between OCaml versions 4.01 and 4.02.
Unfortunately, it looks like it's not straightforward to get a newer (>= 4.02) version:

$ sudo ipkg list ocaml
    ocaml - 3.12.0-2 - Objective Caml system is the main implementation of the Caml language.

Unison 2.48 + Ocaml 4.07

A different article describes cross-compilation on x64 of OCaml 4.08.1 and unison 2.51.2. That uses a Docker environment for encapsulation, but it should also work directly on the operating system.
The environment is setup via a script from the official Synology open source repository:

$ sudo pkgscripts-ng/EnvDeploy -v 6.2 -p rtd1296

Unfortunately, there again are compilation errors:

make world.opt
	"arm64.S:93: Error: bad instruction `adrp x17,caml_last_return_address'"

I finally (somehow) got Ocaml to compile, but then the produced Ocaml didn't compile Unison; there were various errors. I also tried ocaml-4.11.1.tar.gz and ocaml-4.09.1.tar.gz, and finally got ocaml-4.07.1.tar.gz to compile.

At first I didn't realize that it's compiling for x86-64, not ARM, and need to cross-compile. The Synology DiskStation Manager 3rd-Party Package Developer Guide (Appendix B: Compile Applications > Compile Open Source Projects to be precise) then explained that I need to set

CC=/usr/local/aarch64-unknown-linux-gnueabi/bin/aarch64-unknown-linux-gnueabi-gcc

Some later Makefile steps didn't seem to use the CC / LD / AR / RUNLIB environment variables, so had to prepend the whole /usr/local/aarch64-unknown-linux-gnueabi/bin to PATH.
Finally that produces a binary but it wouldn't run:

$ file unison-2.48
/home/inkarkat/tmp/B/unison-2.48: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, BuildID[sha1]=bd98e698a85e332e30f3b1206facb1848617c5c1, for GNU/Linux 3.2.0, stripped
$ file unison
/home/inkarkat/tmp/B/unison: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /opt/lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, not stripped

I'm then copying arm64.o over, then arm64.pic.o, getting closer, but in the end the linker complains. I give up there.

alternatives

A Unison question on Unix&Linux got no good answer but a comment that IPKG is abandoned, you should consider installing Entware. The ipkg Wikipedia page agrees:

ipkg is a discontinued lightweight package management system designed for embedded devices that resembles Debian's dpkg. It was used in the Unslung operating system for the Linksys NSLU2 (Optware), in OpenWrt, Openmoko, webOS, Gumstix, the iPAQ, QNAP NAS appliances and elsewhere; as of early 2017 it can still be used for the Synology NAS appliances and in the LuneOS operating system (although opkg is an increasingly common replacement). [...] Many projects which formerly used ipkg have adopted the ipkg fork opkg as the replacement.

I saw a Synology Wiki page about a Debian chroot on Synology that would allow installing *.deb packages (assuming someone has packaged Ocaml (or even Unison) for that ARM architecture. Unfortunately, a Synology forum post mentions that the Debian chroot package doesn't exist any longer (for DSM 6.2) due to stability issues. Bummer.

For QNAP (a competitor NAS, also ARM-based), someone reported success for TS-420 (Arm), QTS 4.3.3, OCaml 4.06.1, and Unison 2.51.2, so it's not a completely lost cause. I won't switch my NAS just for that, though.

Unison 2.27 + Ocaml 3.12

So, let's fall back to an older Unison version; I'd downgraded Unison to 2.27 for a long time as that was the latest version on NSLU2. Unfortunately, that leads me straight into another build error:

$ make UISTYLE=text NATIVE=false
ocamlc -o src/mkProjectInfo src/mkProjectInfo.ml
src/mkProjectInfo > src/Makefile.ProjectInfo
Fatal error: exception Scanf.Scan_failure("scanf: bad input at char number 4: ``looking for ':', found '$'''")

I found this reported as issue #103 with a simple fix:

--- src/mkProjectInfo.ml.orig   2020-11-20 22:03:07.902480634 +0100
+++ src/mkProjectInfo.ml        2020-11-20 21:46:08.268220864 +0100
@@ -42,7 +42,7 @@
(* ---------------------------------------------------------------------- *)
(* You shouldn't need to edit below. *)

-let revisionString = "$Rev$";;
+let revisionString = "$Rev: 600$";;
let revision = Scanf.sscanf revisionString "$Rev: %d " (fun x -> x);;
let pointVersion = revision - pointVersionOrigin;;
Error: The implementation /volume1/homes/inkarkat/swdev/unison/unison-2.27/src/update.ml
does not match the interface update.cmi:
Modules do not match:
[...]
Makefile.OCaml:354: recipe for target 'update.cmo' failed
make[1]: *** [update.cmo] Error 2 

This error was reported at StackOverflow and also has a trivial fix:

--- src/update.mli.orig 2020-11-20 22:03:27.952766621 +0100
+++ src/update.mli      2020-11-20 21:48:27.070118409 +0100
@@ -1,7 +1,7 @@
(* Unison file synchronizer: src/update.mli *)
(* Copyright 1999-2007 (see COPYING for details) *)

-module NameMap : Map.S with type key = Name.t
+module NameMap : MyMap.S with type key = Name.t

After that, compilation succeeds and the old version works fine (with a corresponding old client on Ubuntu). Unfortunately, the need to downgrade the Unison package to a version that was long thrown out of modern distributions (but fortunately old packages still work, even on Ubuntu 20.04) is certainly not optimal.

I'm keeping that old Unison version just on my main notebook (fortunately, it can easily be installed in parallel to the distribution's default version; this is highly needed as Unison is so choosy with regards to the proper server version), and use my NAS as a secondary backup repository only. My main repository is on a small virtual cloud server (running Ubuntu 18.04 x64, so no trouble with obtaining the Unison package there); this also has the benefit that I can do syncs from any Internet location (e.g. at work), not just within my home network.

Had I known about all of the problems beforehand, I would not have bothered at all. I couldn't imagine that it would be so difficult; I figured at least an outdated Unison package could be installed via package management.

commentary

A bit of research revealed many requests for updated Entware packages:

I know that this is a community effort of unpaid volunteers, so it's hard to complain. Most customers of the NAS vendors probably don't tinker that deeply with the system, and just use the vendor's software for the basic functions, so there's little inclination for vendors to support these efforts, neither. It's a bit of a Catch-22: As long as open source software is so difficult to install, only a few persistent nerds will manage to do it. And without widespread use, the potential base for volunteers (building packages, documenting, testing) is too small.

Ingo Karkat, 22-Nov-2020

blog comments powered by Disqus