Synchronizing directories using Unison Print

  • unison, synchronization, ssh, high availability
  • 82

Unison synchronises files and directories in both directions between two servers. It is used to keep a standby copy of a site or shop up to date, or to maintain a second server ready to take over.

Unlike a one-way copy, Unison detects changes on both sides and reconciles them — which is what makes it suitable for keeping two live servers aligned, and also what makes conflicts possible when the same file changes in both places.

Synchronisation is not a backup. It propagates changes, including deletions and damage — a file deleted or encrypted on one server is deleted or encrypted on the other at the next run. Keep real backups as well: see Backups and snapshots for CloudVM virtual servers.

1. Set up SSH key access

Unison connects over SSH, and an unattended job cannot type a password, so key authentication is required.

On the server that will initiate synchronisation:

ssh-keygen -t ed25519

Press Enter to accept the default path (~/.ssh/id_ed25519). Leave the passphrase empty only for an automated job — a key with a passphrase cannot be used unattended. If you leave it empty, the key file itself is the credential: keep its permissions at 600 and do not copy it around.

Then copy the public key to the second server:

ssh-copy-id [email protected]

Confirm it works before going further:

ssh [email protected]

This must connect without asking for a password. If it asks, nothing further will work.

2. Install Unison on both servers

Debian and Ubuntu:

apt install unison

AlmaLinux, Rocky Linux and other RHEL-based systems:

dnf install unison

Install the same version on both sides. Unison refuses to run when the versions differ, and this is the most common reason a setup that looks correct does nothing.

3. Create a profile

Unison reads profiles from ~/.unison/. Create ~/.unison/default.prf:

root = /var/www/example.com
root = ssh://[email protected]//var/www/example.com

# what not to synchronise
ignore = Path cache
ignore = Name *.log
ignore = Name .git

# behaviour for automated runs
batch = true
auto = true
times = true
prefer = newer

# where to log
log = true
logfile = /var/log/unison.log

The important settings:

  • root — the two directories to keep in step. Note the double slash in the remote path.
  • ignore — paths and names to leave alone. Caches, logs and version-control directories should not be synchronised: they change constantly and produce conflicts for no benefit.
  • batch and auto — required for unattended runs; without them Unison waits for answers nobody is there to give.
  • prefer = newer — how to resolve a conflict. Consider carefully: with two servers both writing, "newer wins" can silently discard the other change.

4. Test by hand first

unison -testserver
unison

The first command checks only that the connection and versions are compatible. Then run a real synchronisation with a few test files and confirm that they appear on the other side and that nothing unexpected was touched.

5. Schedule it

Add a cron entry, for example every fifteen minutes:

*/15 * * * * /usr/bin/unison default >> /var/log/unison-cron.log 2>&1

Do not run it every minute: a run that has not finished when the next starts leads to overlapping jobs and lock files. See Cron style schedules in KeyHelp for the schedule syntax.

What to watch afterwards

  • Check the log. A synchronisation job that has been failing quietly is discovered when you need the second server, which is the worst possible moment.
  • Watch for conflicts. Unison reports files it could not reconcile; ignoring those reports defeats the point of the setup.
  • Databases are not covered. Copying database files while the database is running produces an unusable copy. Use replication or scheduled dumps for the database — see Для чего нужна репликация Master-Slave.

See the Unison project page for the full option reference. If you would like help designing a synchronisation setup for your project, describe it in a ticket.


Was this answer helpful?

« Back