Syncthing for Linux PPC

I spend way too much time trying to get software not officially support on PowerPC computers running. My latest project is Syncthing. Started in 2013 by Jakob Borg, Syncthing is promoted as an “opensource alternative to proprietary decentralized file sharing services” [1]. The biggest competitor is BitTorrent’s Sync application. The premise for both applications is the same. You pick a folder on your computer or mobile device you want to share to device or user. The application generates cryptographic identifiers that are shared and used for securing traffic. With BitTorrent Sync the identifiers are shared when you start the process of sharing a folder. For Syncthing they are shared when connecting devices together. In the end the result of secure end-to-end communication is accomplished by both applications, jus the roads are a little different.

I’ve been using BTSync for the past year as a way to keep a copy of a KeePass file synced between my computers and my Nexus 5. My KeePass file is something I don’t want to keep up on a service like Google Drive since the cloud is outside of my control. LastPass is a great service, but again, passwords are stored in the cloud and I like control.

The developers of Syncthing are doing a great job of updating the product and releasing versions for the major desktop platforms. Third-party developers have also stepped up and adapted Syncthing to run on Android and support for iOS looks to be on the roadmap [2]. One missing platform, however, is Linux on PPC. I know the market share of for PPC systems is microscopic even if you factor in IBM’s Power line of servers, some of Synology’s NAS products, and the Air Force’s PS3 cluster [3]. That is why I’m still surprised that BitTorrent released a Sync client for Linux PPC until April 2015 [4].

Enough back-story, here is how I got Syncthing running.

Step 0: Install Go

Syncthing is written in the Go programming language. For those who don’t know Go comes from few guys at Google who want something that looked like C, but is better [5]. Its popularity has exploded over the past few years and many applications are being written with it. Of course, to compile an application from source code that was written in Go, you have to have the Go build tools. That is the first problem: the developers of Go do not provide prebuilt tools for Linux PPC. Nobody seems to be building Go packages for Ubuntu yet either. Go 1.5 is the first version to support PPC but that is still listed as a feature in beta/testing. The developers focus on the major platforms like Linux 32/64-bit, Windows, and OS X.

So how does one get Go build tools for PPC? Why you build them of course. No problem, all it takes to build Go is Go… You read that right. You have to build Go using Go. It is really a chicken and egg problem. Obviously Go can’t be built by a PPC system for a PPC system, but there is hope. For 1.5 the developers of Go provide instructions for cross compiling the tools for different platforms [6]. For myself, I have a Ubuntu 14.04 amd64 virtual machine sitting around that can be used to test different software. Using it I can build go for PPC using the instructions.

  1. Download the tar.gz package of Go 1.4 to the home folder
  2. Extract the tar bundle. There should now be a folder called go
  3. Rename the folder to go1.4
  4. Use git to fetch the source repository from googlesource.com
  5. Run the bootstrap script to build Go for PPC
  6. After a few minutes a tar bundle will exist in the home folder called go-linux-ppc64-bootstrap.tbz
  7. Copy the tar bundle over to the PPC system

With the tools built and copied over, I now need to setup the bash environment to use Go.

  1. Extract the bundle to /usr/local
  2. Add the Go bin folder to the PATH variable

Woohoo. I now have Go for PPC. From here on out the process is as if you were building on an Intel box. I run Ubuntu 14.04 so all I have to do is follow the instructions.

Step 1: Build Syncthing

  1. export GOPATH=~
  2. mkdir -p ~/src/github.com/syncthing
  3. cd ~/src/github.com/syncthing
  4. git clone https://github.com/syncthing/syncthing
  5. cd syncthing go run build.go

Step 2: Install Syncthing

  1. cd ~/src/github.com/syncthing
  2. cp syncthing /opt/
  3. useradd -G sharing -m -d /home/syncthing -r -U syncthing
  4. chown -R syncthing:syncthing /opt/syncthing

Step 3: Syncthing Startup Script

I took a startup script provided by the BTSync community and modified it to work with Syncthing.
http://bernaerts.dyndns.org/linux/75-debian/290-debian-server-btsync-permanent-peer


#! /bin/sh
### BEGIN INIT INFO
# Provides: Syncthing daemon
# Required-Start: $syslog
# Required-Stop: $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Syncthing server daemon
# Description: Daemon script to run a Syncthing permanent peer
# Placed in /etc/init.d.
### END INIT INFO
# Author: Nicolas Bernaerts <nicolas.bernaerts@laposte.net>
# Version:
#  V1.0, 06/09/2013 - Creation
#  V1.1, 09/09/2013 - Use under-priviledged system user

# description variables
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="Syncthing server"
NAME="syncthing"
USER=$NAME
GROUP="sharing"
DAEMON=/opt/syncthing/bin/$NAME
DAEMON_OPTS=-gui-address=0.0.0.0:8384
PIDFILE=/var/run/$NAME.pid


# Exit if syncthing program is not installed
if [ ! -x "$DAEMON" ] ; then
  echo "Binary $DAEMON does not exist. Aborting"
  exit 0
fi

# Exit if syncthing user home directory doesn't exist
#if [ ! -d "$ROOT" ]; then
#  echo "User $USER does not exist. Aborting"
#  exit 0
#fi

# Function that starts the daemon/service
# 0 - daemon started
# 1 - daemon already running
# 2 - daemon could not be started
do_start()
{
  # If needed, start the daemon
  if [ -f "$PIDFILE" ]
  then
    echo "$NAME already running"
    RETVAL="1"
  else
    start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --chuid $USER --group $GROUP --name $NAME --exec $DAEMON -- $DAEMON_OPTS
    RETVAL="$?"
    [ "$RETVAL" = "0" ] && echo "$NAME started"
  fi

  return "$RETVAL"
}

# Function that stops the daemon/service
# 0 - daemon stopped
# 1 - daemon already stopped
# 2 - daemon could not be stopped
do_stop()
{
  # Stop the daemon
  start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
  RETVAL="$?"
  [ "$RETVAL" = "0" ] && echo "$NAME stopped"
  [ "$RETVAL" = "1" ] && echo "$NAME was not running"

  # remove pid file
  rm -f $PIDFILE

  return "$RETVAL"
}

# deal with different parameters : start, stop & status
case "$1" in
  # start service
  start)
    do_start
    ;;
  # stop service
  stop)
    do_stop
    ;;
  # restart service
  restart)
    do_stop
    do_start
    ;;
  # unknown command, display help message
  *)
    echo "Usage : $SCRIPTNAME {start|stop|restart}" >&2
    exit 3
    ;;
esac

Make startup script executable and load by default

  1. sudo chmod +x /etc/init.d/syncthing
  2. sudo update-rc.d syncthing defaults

Step 4: Update Syncthing

For the packages provided by the developers, Syncthing is updated on an almost weekly basis. My PPC build doesn’t have this luxury, but I can easily automate the process by using a shell script like this one.


service syncthing stop
export GOPATH=$HOME
export GOROOT=/usr/local/go
export PATH=$PATH:/usr/local/go/bin
cd $HOME/src/github.com/syncthing
rm -rf syncthing.old
mv syncthing syncthing.old
git clone --branch v0.11 https://github.com/syncthing/syncthing.git
cd syncthing
/usr/local/go/bin/go run build.go
rm -rf /opt/syncthing.old
cd ../
cp -r syncthing /opt/
chown -R syncthing:syncthing /opt/syncthing
service syncthing start

Conclusion

There you have it. Syncthing compiled and running on a Linux PPC server. All there is left to do is to start sharing some folders between systems.

Have fun.

[1] https://syncthing.net/
[2] http://docs.syncthing.net/users/faq.html
[3] https://en.wikipedia.org/wiki/PlayStation_3_cluster
[4] http://forum.bittorrent.com/topic/38132-powerpc-and-powerpc-qoriq-support/
[5] https://en.wikipedia.org/wiki/Go_(programming_language)
[6] http://golang.org/doc/install/source