Skip to content

Instantly share code, notes, and snippets.

@jftuga
Last active June 22, 2024 01:14
Show Gist options
  • Save jftuga/0265e5403d56373662b9513d8816e392 to your computer and use it in GitHub Desktop.
Save jftuga/0265e5403d56373662b9513d8816e392 to your computer and use it in GitHub Desktop.
Unison Configuration

Cross Platform Unison Setup: One Way, Immutable File Mirroring

  • Server: desktop - a windows PC
  • Client: macbook
  • Unison: version 2.53.5

Concept

I need to run KeePassXC on both my Windows desktop and MacBook. I consider the desktop to be the source of truth. If I want to update an entry, then I will modify KeePassXC only on my Windows box. I am restricting myself to this self-imposed limitation, because I don't trust two-way file synchronization. The is my own unfounded, unreasonable mind-set as I don't want to have to deal with file synchronization conflicts. By using the -force option, this effectively changes unison from a synchronizer into a mirroring utility. Consider this to be immutable mirroring.

Since Windows 10 now has a built in SSH server, I can run ssh-keygen on both systems to configure an authorized_keys file on both systems to allow for password-less, key-only SSH access to each system. You probably only need to allow the Macbook to authenticate to the Windows system without a password.
I have not tested this as I use ssh from my Windows system to connect to my Macbook via a key file and therefore need both ways.

In order to allow the macbook to log into the windows desktop without using a password, I appended the contents of the macbook's ~/.ssh/id_rsa.pub file onto the windows desktop file: ~/.ssh/authorized_keys. Note: On the macbook, this file might also be named: ~/.ssh/id_ed25519.pub.

Once that is done, I can use a MacOS LaunchAgent to launch my unison shell script at User Login. This also has the advantage that the script will automatically relaunch if the unison binary crashes and/or stops.

Files on MacBook

  • ~/.ssh/config - defines the Windows server address
  • ~/Library/LaunchAgents/local.john.unison.plist - the LaunchAgent definition file
  • ~/bin/unison_to_desktop.sh - a simple wrapper with all of the necessary unison command line options
  • ~/bin/unison - a sym link to /opt/homebrew/bin/unison
  • ~/bin/unison-fsmonitor - built from https://github.com/benesch/unison-fsmonitor
  • /tmp/local.unison.out
  • /tmp/local.unison.err
    • STDOUT and STDERR streams of the unison binary

Directory Locations

  • macbook: ${HOME}/unison
  • windows desktop: $env:USERPROFILE\unison
  • These locations can be changed by modifying the unison_to_desktop.sh script, which resides on the macbook.

Behavior

  • Any files residing in the unison folder on the authoritative Windows server can not be modified by the Macbook.
  • Any files residing in the unison folder on the Windows server are copied to the Macbook.
  • If you try to add a new file in the Macbook unison folder, it will be immediately deleted.
  • If you try to modify an existing file in the Macbook unison folder, the changes will not be saved.
  • On the MacBook, these KeePassXC settings are disabled:
    • Remember database key files and security dongles
    • Automatically save after every change
    • Automatically save when locking database
    • Automatically save non-data changes when locking database
  • On the MacBook, these KeePassXC settings are enabled:
    • Automatically reload the database when modified externally
      • If KeePassXC is simultaneously opened on both systems and a change is made on the Windows side, this change will immediately get synced to KeePassXC running on the MacBook.
  • On the macbook, both /tmp/local.unison.out and /tmp/local.unison.err will be deleted upon a system reboot.

Limitations

  • Using this setup will only allow synchronization to occur while the two systems are on the same LAN.
    • This could be overcome by editing the ~/.ssh/config file and then allowing external SSH access to the Windows server, but I don't want to do this.
    • I'm OK with having to wait until both systems are on the same LAN before a file sync can occur.
Host desktop
HostName 192.168.1.105
User john
Port 22
# Compression yes
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>local.john.unison</string>
<key>Program</key>
<string>/Users/john/bin/unison_to_desktop.sh</string>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardErrorPath</key>
<string>/tmp/local.unison.err</string>
<key>StandardOutPath</key>
<string>/tmp/local.unison.out</string>
</dict>
</plist>
#!/bin/zsh
exec ${HOME}/bin/unison -repeat watch -batch -silent -force ssh://desktop/unison ${HOME}/unison ssh://desktop/unison
# you may need to include something like this: -servercmd /Users/jftuga/bin/unison
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment