One of the issues that every system administrator faces is that users frequently need their profile folders synced between machines. In order to fulfil that demand, we have the usual directory-service style of daemons such as Samba, NFS and OpenDirectory. However, this working scheme is not entirely a good solution, especially due to the fact that none of the mentioned services work very well cross-platofrm. For example, in a Windows intranet, you may manage to sync the user-folders across multiple machines but you will not be able to say, sync the folders to a visiting OSX client. Given these circumstances, a decentralised system is preferable where the user can download their entire profile and folders containing their data across multiple platforms. BitTorrent sync, although in beta, offers an exemplary way of cross-platform profile syncing.
The main feature is that directories are synced both ways such that any local changes will be propagated across your own BitTorrent network. This is similar to what DropBox does, with the advantage that you are working decentralised and that every machine that shares the same secret key can push and pull changes to all the other machines. Even if a machine is disconnected for a while, when the machine restores its connection, it will synchronise with the rest of the machines on the network.
In this example, we are going to sync a profile between a Linux-machine and an OSX machine both of which will share a secret key as part of the BitTorrent network.
Depending on the most suiting distribution, download the linux client from BitTorrent and unpack it with:
tar -zxpvf btsync.tar.gz
Change the permissions on the btsync
binary to root
and the group to root
and place the binary in /usr/sbin/
.
After that, we can generate a configuration file by issuing:
btsync --dump-sample-config > /etc/btsync.conf
Before editing the configuration file, let us generate a secret key that will be shared amongst all installations of BitTorrent sync:
btsync --generate-secret
This will give us a secret key such as BQOCQ8OQGABWWTOLBK4XXZZV23L9CAPKQ
.
Next step is to edit the configuration file /etc/btsync.conf
:
{ "device_name": "joe.internal", "listening_port" : 0, // 0 - randomize port "storage_path" : "/var/run/btsync", "check_for_updates" : true, "use_upnp" : true, // use UPnP for port mapping "download_limit" : 0, "upload_limit" : 0, "webui" : { // "listen" : "0.0.0.0:8888", "login" : "admin", "password" : "password" }, "shared_folders" : [ { "secret" : "BQOCQ8OQGABWWTOLBK4XXZZV23L9CAPKQ", // * required field "dir" : "/home/joe", // * required field "use_relay_server" : false, "use_tracker" : false, "use_dht" : false, "search_lan" : false, "use_sync_trash" : false, "known_hosts" : [ ] } ] }
After editing the configuration file, we set-up an init
script to start btsync
on boot. We create the a file at /etc/init.d/btsync
with the following contents:
! /bin/sh ### BEGIN INIT INFO # Provides: btsync # Required-Start: $remote_fs $syslog # Required-Stop: $remote_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Starts the BTSync daemon # Description: Starts the BTSync daemon if a configuration file is # present at /etc/btsync.conf. ### END INIT INFO # Author: Wizardry and Steamworks <office@grimore.org> # PATH should only include /usr/* if it runs after the mountnfs.sh script PATH=/sbin:/usr/sbin:/bin:/usr/bin DESC="The BitTorrent sync Daemon" USER=joe NAME=btsync DAEMON=/usr/sbin/$NAME DAEMON_ARGS="--config /etc/btsync.conf" PIDFILE=/var/run/btsync/$NAME.pid SCRIPTNAME=/etc/init.d/$NAME # Exit if the package is not installed [ -x "$DAEMON" ] || exit 0 # Read configuration variable file if it is present [ -r /etc/default/$NAME ] && . /etc/default/$NAME # Load the VERBOSE setting and other rcS variables . /lib/init/vars.sh # Define LSB log_* functions. # Depend on lsb-base (>= 3.2-14) to ensure that this file is present # and status_of_proc is working. . /lib/lsb/init-functions # # Function that starts the daemon/service # do_start() { # Return # 0 if daemon has been started # 1 if daemon was already running # 2 if daemon could not be started start-stop-daemon -c $USER --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ || return 1 start-stop-daemon -c $USER --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ $DAEMON_ARGS \ || return 2 # Add code here, if necessary, that waits for the process to be ready # to handle requests from services started subsequently which depend # on this one. As a last resort, sleep for some time. } # # Function that stops the daemon/service # do_stop() { # Return # 0 if daemon has been stopped # 1 if daemon was already stopped # 2 if daemon could not be stopped # other if a failure occurred start-stop-daemon -c $USER --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME RETVAL="$?" [ "$RETVAL" = 2 ] && return 2 # Wait for children to finish too if this is a daemon that forks # and if the daemon is only ever run from this initscript. # If the above conditions are not satisfied then add some other code # that waits for the process to drop all resources that could be # needed by services started subsequently. A last resort is to # sleep for some time. start-stop-daemon -c $USER --stop --quiet --oknodo --retry=0/30/KILL/5 --pidfile $PIDFILE --exec $DAEMON [ "$?" = 2 ] && return 2 # Many daemons don't delete their pidfiles when they exit. rm -f $PIDFILE return "$RETVAL" } # # Function that sends a SIGHUP to the daemon/service # do_reload() { # # If the daemon can reload its configuration without # restarting (for example, when it is sent a SIGHUP), # then implement that here. # start-stop-daemon -c $USER --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME return 0 } case "$1" in start) [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" do_start case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; stop) [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" do_stop case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; status) status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? ;; #reload|force-reload) # # If do_reload() is not implemented then leave this commented out # and leave 'force-reload' as an alias for 'restart'. # #log_daemon_msg "Reloading $DESC" "$NAME" #do_reload #log_end_msg $? #;; restart|force-reload) # # If the "reload" option is implemented then remove the # 'force-reload' alias # log_daemon_msg "Restarting $DESC" "$NAME" do_stop case "$?" in 0|1) do_start case "$?" in 0) log_end_msg 0 ;; 1) log_end_msg 1 ;; # Old process is still running *) log_end_msg 1 ;; # Failed to start esac ;; *) # Failed to stop log_end_msg 1 ;; esac ;; *) #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 exit 3 ;; esac :
This will allow the system to start btsync
when the system boots. One further step must be made to ensure that the btsync
working directory belongs to the user joe
:
chown -R joe:joe /var/run/btsync
To add the script to the list of scripts executed on start-up, issue:
update-rc.d btsync defaults
Now that we have BitTorrent sync set-up on the server and a shared secret (in this example, BQOCQ8OQGABWWTOLBK4XXZZV23L9CAPKQ
) we can set-up our clients to sync the /Users/joe
directory with the server by entering the shared-key. The same will apply to any computer that the user uses.
For OSX, a couple of directories are sensitive and should not be synchronised. To exclude files and directories we edit the .SyncIgnore
dot-file in the directories that is to be synced. Amongst others, a good list of directories to exclude is:
.* thumbs.db desktop.ini Thumbs.db Library Desktop Public Downloads Applications Maildir Music/iTunes mail AppData
Both Windows and OSX use the home directory of the user to store important program data. This can include licenses for software bought by the user, automated backups performed by software as well as save-game files. It is very useful to have this data replicated between machines.