SyncVault

approved

by talon

同步你的笔记库到自托管 CouchDB 服务器,支持端到端加密,双向实时更新,全中文界面。参考 Self-hosted LiveSync(MIT)重写,数据完全由你掌控。 - This plugin has not been manually reviewed by Obsidian staff.

3 downloadsUpdated 2d agoMIT

SyncVault

English | 中文

SyncVault is a self-hosted, end-to-end encrypted, real-time two-way sync plugin for Obsidian, backed by your own CouchDB server. It is a fully localized (Chinese UI) rewrite inspired by the design of Self-hosted LiveSync (MIT License).

Your note contents and file names are encrypted (AES-256-GCM, key derived via PBKDF2) before they leave your device, so your server operator can only see ciphertext. Works on desktop and mobile.

⚠️ Before using SyncVault, disable other sync methods for the same vault — Obsidian Sync, iCloud, Nutstore, etc. — to avoid conflicts and data corruption. Back up your vault first.


Features

FeatureDescription
Real-time two-way syncContinuous CouchDB replication; changes sync on save, reconnects automatically after disconnects
End-to-end encryptionAES-256-GCM; key derived from your passphrase with PBKDF2 (310,000 iterations); file content and file names are encrypted before leaving your device — the server only sees ciphertext
Conflict handlingMarkdown conflicts auto-merge (if one side is a superset, it merges directly; otherwise conflict markers merge both versions without losing content); other files keep the local version and save the remote one as a "(冲突 …)" copy
Localized Chinese UIServer, encryption, sync, conflict and maintenance settings fully explained in Chinese
Multi-deviceFill in the same server + database name + passphrase on every device and they stay in sync
Safety netsPeriodic full sync, startup scan, ignore rules, oversized-file skipping

Installation

  1. Copy this directory (syncvault, containing main.js, manifest.json, styles.css, versions.json) into: YourVault/.obsidian/plugins/syncvault/
  2. Open Obsidian → Settings → Community plugins → enable SyncVault.
  3. Complete the three-step setup on the plugin settings page (see below).

Quick start

1. Prepare the server (CouchDB — skip if already deployed)

You have already deployed your sync server. Two things to confirm:

  • Enable CORS (otherwise the Obsidian client cannot talk to the server). In CouchDB's local.ini / default.ini:
[couchdb]
; if you need to sync files larger than 5MB, raise the single-doc limit (default 8MB)
;max_document_size = 134217728

[chttpd]
; allow cross-origin
require_valid_user = false

[cors]
origins = *
credentials = true
methods = GET, PUT, POST, HEAD, DELETE
headers = accept, authorization, content-type, origin, referer, x-csrf-token

Then restart CouchDB.

  • HTTPS is strongly recommended (reverse proxy such as Nginx/Caddy with a certificate) to protect the transport link. Even without HTTPS, end-to-end encryption guarantees the server cannot read your notes.

2. First device

  1. Open plugin settings → "① 服务器设置":
    • Server address: http://your-server:5984 or https://sync.example.com
    • Username / password: your CouchDB account
    • Database name: anything, e.g. obsidian-vault (must be the same on all devices)
  2. Click 测试连接 (Test connection) — the database is created automatically if it does not exist.
  3. Under "② 端到端加密", enable encryption and set / generate a passphrase.
  4. Click 启动同步 (Start sync), then 全量上传到服务器 (Full upload) to push your vault to the server.

3. Other devices

  1. Install the plugin and fill in the same server, account, database name and passphrase.
  2. Test connection → start sync → click 从服务器全量下载 (Full download) to pull everything.
  3. Real-time two-way sync runs from then on.

If you do not want the new device to overwrite local files wholesale, start live sync first and run "立即同步" (Sync now) only for individual files.

End-to-end encryption details

  • Algorithm: AES-256-GCM (authenticated, detects tampering).
  • Key derivation: PBKDF2-SHA256, 310,000 iterations; the salt is derived deterministically from the database name, so the same database + same passphrase derives the same key on every device — no key exchange files needed.
  • Scope: file content + file path (the whole document body is encrypted); the server only sees metadata such as content hashes, sizes and mtimes.
  • The key stays in the local plugin config (data.json) and is never uploaded; keep your vault and passphrase safe.
  • ⚠️ Losing the passphrase means the data can never be decrypted again; ⚠️ after changing the passphrase or database name, you must first "重置本地数据库" (Reset local database) under the old config and re-upload, otherwise old data cannot be decrypted (the plugin detects the key fingerprint and blocks the wrong sync).

Conflict handling

  • When the same file is modified on two devices:
    • Markdown: if one side is a superset of the other (line-based), the merge result is taken automatically; otherwise both versions are merged into the original file with <<<<<<< 本地版本 / ======= / >>>>>>> 远端版本 markers so nothing is lost and you can review manually.
    • Other files: the local version is kept and the remote version is saved as original-name(冲突 timestamp).ext.
  • You can disable auto-merge under "④ 冲突处理" (always save a conflict copy instead).

Commands

CommandPurpose
启动同步 / 停止同步 (Start/Stop sync)Manually control the sync engine
立即同步 (Sync now)One manual two-way sync
全量上传到服务器 (Full upload)First-device initialization
从服务器全量下载 (Full download)Second-device initialization
重置本地同步数据库 (Reset local sync database)Clear the local sync cache (does not affect the server or your notes)

The refresh icon in the left ribbon = sync now; the status bar at the bottom shows sync status and up/download counters.

Settings reference

SettingDefaultDescription
实时同步 (Live sync)OnContinuous replication with auto-reconnect
保存后自动同步 (Sync on save)OnSync immediately after Ctrl+S
定时完整同步 (Periodic full sync)10 minFallback full sync; 0 disables
启动时扫描 (Startup scan)OnPicks up external changes made while the plugin was off
最大同步文件大小 (Max file size)5 MBLarger files are skipped (raise max_document_size on the server to relax)
忽略规则 (Ignore regex)emptyMatching paths are not synced, e.g. ^附件/
同步配置目录 (Sync config dir)OffSync settings/themes/snippets (excluding the plugin's own data.json)

FAQ

Connection fails / keeps retrying?

  1. Click "测试连接" first and read the error: 401/403 means wrong credentials; 404 means a wrong address; cannot connect → check the port and firewall.
  2. If "测试连接" succeeds but replication keeps failing, CORS is usually not configured — enable CORS in CouchDB as above and restart.

Need to sync files larger than 5MB?

Raise the plugin's "最大同步文件大小" and increase max_document_size in CouchDB (e.g. 134217728 = 128MB), then restart.

Sync reports "凭据不一致" after toggling encryption / changing the passphrase?

First "重置本地数据库" (Reset local database), then re-run "全量上传" or "全量下载". Note: data uploaded with a new passphrase cannot be decrypted by devices using the old one.

Will my notes ever appear in plaintext on the server?

No, when end-to-end encryption is on — ciphertext is only decrypted on your devices. The passphrase never leaves your machine.

Compatible with official Obsidian Sync?

No, and they should not be used together. Keep only one sync solution.

Development

npm install        # install dependencies
npm run dev        # watch build (development)
npm run build      # production build → main.js
npm run typecheck  # type check
node build-test.mjs && node .test-build/unit.test.cjs        # unit tests
node build-test.mjs && node .test-build/integration.test.cjs # replication integration tests

Project structure

syncvault/
├── manifest.json      # plugin manifest (id/name/version)
├── main.js            # build output (the file Obsidian loads)
├── styles.css         # styles
├── versions.json      # version compatibility
├── src/
│   ├── main.ts        # plugin entry: commands, status bar, vault events
│   ├── syncEngine.ts  # sync engine: PouchDB + CouchDB live replication, echo suppression, conflict handling
│   ├── crypto.ts      # end-to-end encryption (AES-256-GCM + PBKDF2)
│   ├── conflict.ts    # conflict sweep (_conflicts multi-revision handling)
│   ├── merge.ts       # Markdown line-level merge (pure functions)
│   ├── settings.ts    # localized Chinese settings UI
│   ├── types.ts       # types and default config
│   └── utils.ts       # utilities
└── test/              # unit + integration tests

License

MIT. Inspired by Self-hosted LiveSync (MIT).

For plugin developers

Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.