OpenFileSync

Table of Contents
An open-source bidirectional file sync tool built on top of rclone bisync. Designed for users who have remote storage (Hetzner Storage Box, any SFTP endpoint) and want Dropbox/Mega-like sync without vendor lock-in.
Why #
Cloud sync services like Mega.nz or Dropbox work great but lock you into their ecosystem. Meanwhile, cheap SFTP storage (like Hetzner Storage Boxes at 3.20 EUR/month for 1TB) has no sync client — just rsync or manual transfers.
OpenFileSync bridges that gap: plug in any SFTP backend and get automatic bidirectional sync between your devices.
Quick Setup #
First computer #
curl -fsSL https://get.openfilesync.runatyr.dev/ | bash
ofs init
The wizard asks for: SFTP host, port, username, auth (password or SSH key), and which local folders to sync. It shows a dry-run preview before syncing, then optionally installs a systemd timer for automatic sync every 30 min.
Verify it’s working:
ofs log
Extra computer #
Install the same way, then run ofs init and choose option 2 (browse remote). Only paths already synced by another machine will be listed — select them and sync begins. See Multi-device Setup for path planning requirements.
Features #
- Bidirectional sync via rclone bisync over SFTP
- Path mappings — same remote layout, different local paths per device
- Smart filters — built-in presets for Node.js, Go, Python, Terraform, Ansible, VSCodium, Vim (excludes
node_modules,.git, build dirs, caches, etc.) - Conflict resolution — newest file wins, losing version saved as
.conflictfile - Systemd integration — scheduled sync via timer, no cron needed
- Self-updating — run
ofs updateto pull the latest version
How It Works #
Each sync mapping pairs a local path with a remote path. The same remote paths can map to different local paths on each machine:
# ~/.config/openfilesync/mappings
Documents = /home/alice/Documents # Device A
Documents = /home/bob/Documents # Device B — same remote, different local
Syncs run with safe defaults: --resilient, --recover, --max-delete 10%, --conflict-resolve newer.
Usage #
ofs sync # Run sync once
ofs sync --dry-run # Preview changes
ofs sync --force # Allow bulk deletes (bypass safety limit)
ofs status # Check sync health
ofs conflicts # List conflict files
ofs log # Tail sync log
ofs update # Update to latest version
Multi-device Setup #
Plan your sync paths before setting up the first machine. rclone bisync places an access verification file (RCLONE_TEST) at each sync root. If two machines sync overlapping paths — one syncing projects/ and another syncing projects/work/ — bisync detects a mismatch and aborts. Use the exact same remote paths across all machines.
# Good — both machines sync the same root
Machine 1: projects/ <-> ~/projects
Machine 2: projects/ <-> ~/projects
# Bad — overlapping roots, bisync will fail
Machine 1: projects/ <-> ~/projects
Machine 2: projects/work/ <-> ~/work
On the second machine, install and run ofs init, then choose option 2 (browse remote). Only paths already configured on another machine will be shown. Both password and SSH key auth are supported — use the same credentials as the first machine.
Troubleshooting #
- “Another sync is running” — stale lock from a crashed run. Remove it:
rm ~/.local/share/openfilesync/lock - “Access test failed: RCLONE_TEST” — sync path on this machine doesn’t match another machine’s mapping (e.g. syncing a parent dir when another machine syncs a subdir). Re-run
ofs initusing option 2 to pick the correct paths. - Check configured auth/remote —
rclone config show openfilesync - Sync seems stuck or erroring —
ofs logto see what’s happening. For persistent bisync state issues:ofs sync --resync - List all commands —
ofs help
Limitations & Behaviors #
- Full file listing on every sync — rclone bisync lists and compares every file on both sides each run. There is no local change tracking. With large directories (100k+ files) over SFTP, a single sync can take 10-30 minutes even if nothing changed. This is an inherent limitation of rclone bisync. Good filters are critical to keep file counts low.
- Deletes propagate both ways — deleting a file locally will delete it on the remote (and vice versa). A safety limit aborts if too many files would be deleted in a single run. Use
ofs sync --forceto override. - Empty directories are cleaned up — after each sync, empty directories are removed on both local and remote sides. Filtered paths are excluded from local cleanup (
.git,node_modules,.gradle,.cache,.cxx,CMakeFiles,.idea,ios/Pods). Any tool that needs empty dirs should recreate them. - Resync merges both sides — when a
--resyncruns (first sync, filter changes, or error recovery), rclone treats both sides as equally valid and merges them. Files that exist on one side but not the other are copied, not deleted. If you previously synced with another tool, this may restore old files that were intentionally deleted. Delete them again and run a normal sync to propagate.
Links #
- GitHub
- Install:
curl -fsSL https://get.openfilesync.runatyr.dev/ | bash