rosswang433 downloadsSync Obsidian vault with Joplin Server — bidirectional, attachments, tags, links.
Bidirectional sync between Obsidian and a Joplin Server instance. Keeps your notes, folders, and attachments in sync across multiple devices, with optional end-to-end encryption.
joplin-file-id in its frontmatter, and a persistent change log drives conflict-free merge across multiple syncing clientsForce push / Force pull require a typed vault-name confirmation (toggleable), and a force pull that would shrink the vault far below its mapped size is blocked (wrong sync target / wiped server), before any local file is deletedForce push wipes the server (protecting info.json and E2EE master keys) then re-uploads everything; Force pull wipes local files then re-downloads everything.obsidian/, _conflicts/, templates/) via comma-separated prefixesyanqingwang/obsidian-joplin-server-syncDownload main.js, manifest.json, and styles.css from the latest release and place them in your vault at .obsidian/plugins/joplin-server-sync/.
https://joplin.example.com — without /api)| Command | Description |
|---|---|
| Sync now | Run a bidirectional sync cycle (push then pull) |
| Force push | Delete server items (keeps info.json and E2EE master keys), then upload the entire vault |
| Force pull | Delete local files (keeps the plugin config), then download the entire server |
| Test Joplin Server connection | Verify login credentials |
| Upload vault to Joplin Server | Initial upload of all notes |
| About / Status | Show mapping statistics |
| Setting | Description |
|---|---|
| Server URL | Joplin Server base URL (without /api) |
| Email / Password | Joplin Server account credentials (password stored in plugin data.json) |
| Auto sync interval | Seconds between automatic syncs. 0 = manual only (min 60) |
| Sync on startup | Run a sync when Obsidian starts |
| Confirm force push / force pull | Ask for a typed vault-name confirmation before overwriting the server or the local vault |
| Conflict strategy | Duplicate, Local wins, or Remote wins |
| Sync folders only | Sync folder structure only, no note content (useful for testing) |
| Exclude patterns | Comma-separated path prefixes to skip |
| Enable E2EE | Toggle end-to-end encryption (requires a password; loads and verifies server master keys) |
| E2EE password | Password used to encrypt/decrypt items |
| Load E2EE keys | Load master keys from the server using the E2EE password |
JED01 header, master keys, SJCL-compatible AES/KeyV1/FileV1/StringV1 item types).git clone https://github.com/yanqingwang/obsidian-joplin-server-sync
cd obsidian-joplin-server-sync
npm install
npm run dev
npm run build
Run the offline test suites (no server needed):
# reliability regressions: delete-vs-edit safety, blob-only delta pull,
# incomplete-server guard, changelog durability, three-way merge, redaction
npx esbuild test/reliability.test.ts --bundle --platform=node --format=cjs \
--alias:obsidian=./test/mock/obsidian.ts --outfile=test/reliability-out.cjs --log-level=error
node test/reliability-out.cjs
# E2EE protocol vectors
npx esbuild test/e2ee.test.ts --bundle --platform=node --format=esm --outfile=test/e2ee-out.mjs --log-level=error
node test/e2ee-out.mjs
# force push → server → force pull round-trip (in-memory mock server)
npx esbuild test/run.ts --bundle --platform=node --format=cjs \
--alias:obsidian=./test/mock/obsidian.ts --outfile=test/run-out.cjs --log-level=error
node test/run-out.cjs
The suites under test/*.test.ts that import test/mock/obsidian-real.ts drive a REAL Joplin Server (credentials read from a local vault) and are used for release verification.
When reporting an issue, please include your Obsidian version, the plugin version, a description or screenshot of the problem, and what you expected to happen.
MIT
Copyright (c) 2026 rosswang (Heart and Road Ltd)
在 Obsidian 与 Joplin Server 之间双向同步,让笔记、文件夹和附件在多台设备间保持一致,支持可选的端到端加密。
joplin-file-id,配合持久化变更日志,多客户端同步无冲突合并强制推送 / 强制拉取 需要输入库名确认(可关闭);强制拉取若会把库缩减到远小于映射规模(同步目标错误 / 服务器被清空)会被直接阻止,先于 任何本地文件被删除强制推送 清空服务器(保留 info.json 与 E2EE 主密钥)后全量上传;强制拉取 清空本地文件后全量下载.obsidian/、_conflicts/、templates/)yanqingwang/obsidian-joplin-server-sync从最新 release 下载 main.js、manifest.json、styles.css,放入库中 .obsidian/plugins/joplin-server-sync/ 目录。
https://joplin.example.com — 不带 /api)| 命令 | 说明 |
|---|---|
| 立即同步(Sync now) | 执行一轮双向同步(先推送后拉取) |
| 强制推送(Force push) | 删除服务器条目(保留 info.json 与 E2EE 主密钥),然后上传整个库 |
| 强制拉取(Force pull) | 删除本地文件(保留插件配置),然后下载整个服务器 |
| 测试 Joplin 服务器连接 | 校验登录凭证 |
| 上传库到 Joplin 服务器 | 首次上传全部笔记 |
| 关于 / 状态 | 显示映射统计 |
| 设置项 | 说明 |
|---|---|
| 服务器地址 | Joplin Server 基础 URL(不带 /api) |
| 邮箱 / 密码 | Joplin Server 账号凭证(密码保存在插件 data.json 中) |
| 自动同步间隔 | 自动同步的间隔秒数,0 = 仅手动(最小 60) |
| 启动时同步 | Obsidian 启动时执行一次同步 |
| 强制操作确认 | 覆盖服务器或本地库前要求输入库名确认 |
| 冲突策略 | 复制为冲突文件(Duplicate)、本地优先(Local wins)、远程优先(Remote wins) |
| 仅同步文件夹 | 只同步文件夹结构,不含笔记内容(适合测试) |
| 排除规则 | 逗号分隔的路径前缀,命中的路径跳过 |
| 启用 E2EE | 开关端到端加密(需要密码;加载并校验服务器主密钥) |
| E2EE 密码 | 用于加解密条目的密码 |
| 加载 E2EE 密钥 | 用 E2EE 密码从服务器加载主密钥 |
JED01 头、主密钥、SJCL 兼容的 AES/KeyV1/FileV1/StringV1 条目类型)。git clone https://github.com/yanqingwang/obsidian-joplin-server-sync
cd obsidian-joplin-server-sync
npm install
npm run dev
npm run build
运行离线测试套件(无需服务器):
# 可靠性回归:删除与编辑安全、blob-only 增量拉取、
# 服务器数据不完整保护、变更日志持久化、三方合并、日志脱敏
npx esbuild test/reliability.test.ts --bundle --platform=node --format=cjs \
--alias:obsidian=./test/mock/obsidian.ts --outfile=test/reliability-out.cjs --log-level=error
node test/reliability-out.cjs
# E2EE 协议测试向量
npx esbuild test/e2ee.test.ts --bundle --platform=node --format=esm --outfile=test/e2ee-out.mjs --log-level=error
node test/e2ee-out.mjs
# 强制推送 → 服务器 → 强制拉取 往返(内存 mock 服务器)
npx esbuild test/run.ts --bundle --platform=node --format=cjs \
--alias:obsidian=./test/mock/obsidian.ts --outfile=test/run-out.cjs --log-level=error
node test/run-out.cjs
test/*.test.ts 中引用 test/mock/obsidian-real.ts 的套件会驱动真实 Joplin Server(凭证从本地库读取),用于发版验证。
反馈时请尽量附上:Obsidian 版本、插件版本、问题描述或截图、预期结果。
MIT
Copyright (c) 2026 rosswang (Heart and Road Ltd)