3.8 KiB
Obsidian Sync
Obsidian Sync is a self-hosted, end-to-end encrypted vault sync system for Obsidian across Windows, Linux, and Android. It consists of an Obsidian plugin, a sync server, and shared protocol and crypto packages inside a TypeScript monorepo.
Features
- End-to-end encrypted text note and binary attachment sync
- Automatic text merge with conflict markers when both sides change
- Binary conflict copies when attachments diverge
- Durable server state stored on disk
- Structured JSON-line diagnostics and client sync log upload
- Recovery bundle export and import for onboarding new devices
- Device listing and revocation
- Vault key rotation with recovery-bundle refresh
- Paged pull and batched push behavior so interrupted sync runs can resume safely
Repository Layout
apps/obsidian-plugin: Obsidian plugin entry point, settings UI, and sync orchestrationapps/sync-server: Express server for encrypted revision exchange and device managementpackages/sync-protocol: Shared request and response schemaspackages/sync-engine: Shared crypto, hashing, and merge helpersdocs: Architecture and deployment notestests: Focused contract and store-level integration tests
Requirements
- Node.js 22 or newer
- npm 10 or newer
Install
npm install
Build
npm run build
Test
npm test
Run The Server
npm run dev:server
The default server URL is http://localhost:8787.
Run The Server In Docker
Build and start the server with Docker Compose:
docker compose up --build sync-server
Or build the image directly:
docker build -f apps/sync-server/Dockerfile -t obsidian-sync-server .
docker run --rm -p 8787:8787 -v obsidian-sync-data:/app/data obsidian-sync-server
The Docker image persists server state in /app/data, which is backed by the obsidian-sync-data volume in compose.yaml.
Build The Obsidian Plugin
The plugin build now emits a bundled main.js directly in apps/obsidian-plugin, beside manifest.json, which is the layout Obsidian expects for local plugins.
After running npm run build, use these files from apps/obsidian-plugin in your vault plugin folder:
manifest.jsonmain.js
First-Time Setup
- Start the sync server.
- Load the plugin into an Obsidian vault.
- Set the server URL, vault ID, and device name in the plugin settings.
- Run a manual sync to register the first device and generate the initial vault key.
- Export a recovery bundle from the settings tab and store it securely.
Add Another Device
- Install the plugin on the second device.
- Open the plugin settings and paste the recovery bundle into the import field.
- Run a manual sync to register that device and pull the encrypted vault contents.
Rotate The Vault Key
- Open the plugin settings and use
Rotate key. - Wait for the client to re-encrypt and upload the current vault contents.
- Export the fresh recovery bundle.
- Import that new bundle on every other device before the next sync.
Revoke A Device
Use the plugin settings device list to revoke a device that should no longer have access. A revoked device can no longer authenticate to the server.
Server Data
data/sync-state.json: durable revision, device, tombstone, and key-status statedata/logs/server.jsonl: structured server and client-sync diagnostics
When running under Docker, these same files are stored under /app/data inside the container.
Current Limitations
- The server storage backend is file-based rather than SQLite or PostgreSQL.
- Sync validation is focused on shared libraries and the server store; there is not yet a full Obsidian plugin integration harness.
- Device onboarding is driven by a copy-and-paste recovery bundle instead of a richer pairing flow.
Documentation
docs/architecture.mddocs/deployment.mdPlan.md