Keep a directory in step with a master copy.
App::FileSync keeps a directory on each client in step with one master copy on the server. Clients never talk to each other: each pushes its changes to the master and pulls everyone else's from it, so a change made on one client reaches the others on their next run.
- version 0.002.0
- Perl 5.14+
- GPL-2.0
- no daemon
Any number of clients can share a repo this way, and a separate machine can hold a replica of the master. Every run is a short-lived CLI process suitable for cron or the Windows Task Scheduler: there is no daemon, no database and no web interface.
laptop ──┐
desktop ──┼── push / pull ──▶ master on the server
tablet ──┘ │
└──▶ replica (optional, pull-only)
Why it is built this way
-
No daemon to supervise
Every run is a short-lived process. Cron or the Task Scheduler starts it, it finishes, and nothing is left listening.
-
Only changes move
A size-and-mtime cache decides what to send. Data frames are deflated when that helps, and files of at least 64 KiB go as rsync-style block deltas when the other side holds an older copy.
-
Conflicts are kept
The newer mtime wins; the loser is preserved beside it as
report.conflict-laptop-1-20261022T101500Z.txt, never silently discarded. -
Deletions are recoverable
Removed files go to a per-repo trash, kept for 30 days by default.
filesync restoreputs a path back, or lists every version. -
Snapshots for replicas
A replica can take a daily snapshot of its tree, by hard link or by copy, and roll back to a date. Fourteen are kept by default.
-
Boring to operate
JSON configuration and run logs you can read with
cat, people-readable messages from a catalogue, and distinct exit codes for cron.
A repo in six commands
Two machines are involved: the server, which holds the master, and each client, which holds a copy. Install App::FileSync on both. The example keeps the master in the server account's home directory, so nothing runs as root.
# on the server, once
filesync-admin --root ~/filesync repo create documents
# on the server, once: filesync-server needs the same --root
cat > ~/bin/filesync-server-home <<'EOF'
#!/bin/sh
exec /usr/local/bin/filesync-server --root "$HOME/filesync" "$@"
EOF
chmod +x ~/bin/filesync-server-home
# on each client, once
filesync init --repo documents --root /home/foo/Documents \
--server foo@srv --server-command /home/foo/bin/filesync-server-home
# on each client, whenever you like
filesync sync --repo documents --dry-run
filesync sync --repo documents
The client reports its host name as its id; there is nothing else to name. An id is not a login, and it does not divide the repo: every client of a repo syncs the whole tree.
Where to go next
-
Quick start
Server and client setup, the first sync, cron, Windows, and a backup-and-restore drill.
-
Commands
Every option of
filesync,filesync-adminandfilesync-server, and what each exit code means. -
Settings
Process-wide settings, the client's repo list, the server's per-repo policy, and where each value came from.
-
How it works
The session, the line-delimited JSON protocol, deltas, conflicts, locking and the layout on disk.