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.
Install #
curl -fsSL https://get.openfilesync.runatyr.dev/ | bash
This installs rclone (if missing), inotify-tools, and the ofs binary.
Then run the setup wizard:
ofs init
The wizard will ask you:
- SFTP host, port, username, and auth method (password or SSH key)
- Which local folders to sync (enter paths one by one, or paste multiple at once)
- Confirm a dry-run preview, then run the initial sync
- Optionally install a systemd timer for automatic sync every 30 min
Config is saved to ~/.config/openfilesync/. Remote paths mirror your local structure by default (e.g. ~/Documents → Documents on the remote).
Features #
- Bidirectional sync via rclone bisync over SFTP
- Simple setup — answer 4 questions, syncing in minutes
- 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 - Self-managed logging — plain log file, auto-trimmed to 15 days
- Systemd integration — scheduled sync via timer, no cron needed
- Self-updating — run
ofs updateto pull the latest version
How It Works #
OpenFileSync wraps rclone bisync with a configuration layer. Each sync mapping defines a local path and its corresponding remote path:
# ~/.config/openfilesync/mappings
# Device A
Documents = /home/user1/important1/Documents
Projects = /home/user1/important1/projects
# Device B (same remote paths, different local paths)
Documents = /home/user1/Documents
Projects = /home/user1/projects
On each sync run, the tool iterates over mappings, applies combined ecosystem filters, and runs rclone bisync 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
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