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.