Skip to content

cluion/obsync

Repository files navigation

obsync

Self-hosted file synchronization for Obsidian Vault notes.

obsync keeps your Obsidian vault in sync across multiple devices using your own server. A Go server stores files and metadata, while a Rust client watches your vault and syncs changes in real time over WebSocket.

Features

  • Real-time sync via WebSocket with automatic reconnection
  • Optional end-to-end encryption (AES-256-GCM) -- the server stores only ciphertext
  • Conflict detection with local backup files
  • File rename support coordinated between devices
  • JWT authentication with device management
  • SHA-256 hash verification for file integrity
  • Local SQLite index for offline-capable metadata
  • Configurable ignore patterns and file size limits
  • Self-hosted -- your data stays on your server
  • System service integration (launchd on macOS, systemd on Linux, Task Scheduler on Windows)
  • Docker deployment support

Quick Start

# 1. Install the client
curl -sSL https://github.com/cluion/obsync/releases/latest/download/obsync-install.sh | sh

# 2. Set up your server (or use an existing one)
docker compose -f deploy/docker-compose.yml up -d

# 3. Connect and sync
obsync init       # enter server URL, username, and vault path
obsync login      # authenticate with the server
obsync start      # start the sync daemon

Installation

Client

Binary (macOS / Linux / Windows):

Download the latest release from GitHub Releases. On Windows, obsync install registers a per-user Scheduled Task that starts the sync daemon at logon (no administrator rights required); obsync uninstall removes it.

Homebrew:

brew tap cluion/tap
brew install obsync

Install script:

curl -sSL https://github.com/cluion/obsync/releases/latest/download/obsync-install.sh | sh

From source:

git clone https://github.com/cluion/obsync.git
cd obsync
make build-client
# binary at apps/client/target/release/obsync

Server

Binary:

Download from GitHub Releases.

Docker:

docker compose -f deploy/docker-compose.yml up -d

From source:

make build-server
# binary at bin/obsync-server

Configuration

The server reads config.toml from its working directory. A full example lives at deploy/server.toml:

[server]
listen = "0.0.0.0:8080"

[storage]
backend = "disk"        # "disk" or "s3"
data_dir = "./data"
db_path = "obsync.db"
min_free_mb = 1024

[auth]
jwt_secret = ""         # leave empty to auto-generate and persist a secret

[rate_limit]
enabled = true          # throttle auth endpoints against brute-force
auth_requests_per_minute = 10
auth_burst = 5
trusted_proxies = []    # see note below if running behind a reverse proxy

Behind a reverse proxy: set trusted_proxies to your proxy's address (e.g. ["127.0.0.1/32", "::1/128"] for a local nginx). The server only reads the real client IP from X-Real-IP / X-Forwarded-For when the request arrives from a trusted proxy; otherwise those headers are ignored so clients cannot spoof them to bypass rate limiting.

S3-compatible storage can also be configured via environment variables (OBSYNC_STORAGE_BACKEND=s3, OBSYNC_S3_ENDPOINT, OBSYNC_S3_BUCKET, OBSYNC_S3_ACCESS_KEY, OBSYNC_S3_SECRET_KEY, OBSYNC_S3_REGION).

On first launch the server prompts you to create an admin account. obsync is designed for a single user syncing across multiple devices, self-hosted on your own server.

TLS and reverse proxy

Terminate TLS with a reverse proxy. A ready-to-adapt nginx config — including WebSocket upgrade handling and rate limiting for auth endpoints — is provided at deploy/nginx.conf. For containerized deploys see deploy/docker-compose.yml.

End-to-End Encryption (optional)

obsync can encrypt file contents with AES-256-GCM before they leave your device, so the server only ever stores ciphertext.

obsync e2ee setup     # fresh vault: generate a master key + print recovery phrase
obsync e2ee migrate   # existing plaintext vault: re-encrypt all files on the server
obsync e2ee status    # show E2EE state for the active vault
obsync e2ee export    # re-display the recovery phrase
obsync e2ee import    # on another device: paste the phrase to share the key

Use setup on a brand-new vault, or migrate to turn on E2EE for a vault that has already been synced in plaintext (it re-encrypts and re-uploads everything; stop obsync on your other devices first, then import the recovery phrase there).

The master key is stored in your OS keyring and never written to disk in plaintext. Write down the recovery phrase — it is the only way to decrypt your vault if you lose all devices. File paths, sizes, and timestamps remain visible to the server (needed for sync); only contents are encrypted.

Troubleshooting

obsync doctor          # run diagnostic checks (config, connectivity, auth, paths)
obsync status          # show daemon and sync status
obsync log --follow    # follow daemon logs

If sync stalls, obsync doctor is the fastest first step; it validates the server URL, credentials, vault path, and local index. See CONTRIBUTING.md to report issues, and SECURITY.md for the security policy.

Usage

obsync init                    # Interactive setup (server URL, vault path)
obsync login                   # Authenticate with the server
obsync start                   # Start sync daemon in background
obsync stop                    # Stop the sync daemon
obsync sync                    # One-time manual sync
obsync status                  # Show daemon and sync status
obsync doctor                  # Run diagnostic checks
obsync log --follow            # Follow daemon logs
obsync rename old.md new.md    # Rename a file across devices

Architecture

obsync uses a client-server model:

  • Server (Go): Stores files on disk and metadata in SQLite. Broadcasts change events to connected clients over WebSocket. Provides a REST API for file operations, authentication, and device management.
  • Client (Rust): Watches the local vault for filesystem changes. Syncs with the server via REST API and receives real-time updates over WebSocket. Maintains a local SQLite index for tracking file state and sync progress.

Building

make build          # Build both server and client
make test           # Run all tests
make lint           # Run all linters

License

This project is licensed under the terms found in the LICENSE file.

About

Self-hosted real-time file sync for Obsidian vaults — Go server, Rust client

Topics

Resources

License

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors