LiveSync 專用資料庫(系統資料庫 single_node 模式會自動建立)

需求背景

需要一套跨所有裝置(macOS、Windows、Linux、iOS)的 Obsidian vault 同步方案。

最終同步架構:

全裝置 ←— LiveSync (HTTPS) —→ CouchDB (Lima VM)
                          Caddy (HTTPS 反向代理)
                          Tailscale 內網 (WireGuard 加密)
iCloud 同步不可行

原本計畫 iOS 走 iCloud、電腦端走 LiveSync,Mac mini 作為中樞橋接兩邊。但實測發現 LiveSync 插件是全域同步的,無法在單一裝置上關閉——只要 vault 啟用了 LiveSync,所有開啟該 vault 的裝置都會參與同步。因此無法讓 iOS 只走 iCloud 而不走 LiveSync,必須統一用 LiveSync 同步所有裝置。

這也意味著 HTTPS 是必要的,因為 Obsidian mobile 強制要求加密連線。已透過 Caddy + Tailscale HTTPS 憑證解決。


環境概覽

項目規格
主機macOS (你的主機)
虛擬化Lima VM (default), Ubuntu 25.10, x86_64
容器工具nerdctl v2.2.1 + nerdctl compose(非 Docker)
VM 資源4 CPU / 4GB RAM / 100GB Disk
內網Tailscale (你的 tailnet)
反向代理Caddy 2 (alpine),提供 Tailscale HTTPS 終止

部署架構

macOS (你的主機)
  └─ Lima VM (default, Ubuntu 25.10 x86_64)
       └─ nerdctl compose
            ├─ Caddy 2 (alpine) — :443 TLS 終止,host network mode
            │    └─ Tailscale HTTPS 憑證 (Let's Encrypt)
            │    └─ reverse_proxy → 127.0.0.1:5984
            └─ CouchDB 3.5.1 — :5984
       └─ Lima port forward: 0.0.0.0:443, 0.0.0.0:5984

部署流程

1. 建立目錄

Lima VM 內 macOS 掛載 /Users/your-name唯讀(virtiofs ro),所有可寫資料必須放在 Linux 本地路徑:

limactl shell default -- bash -c "mkdir -p /home/your-user/couchdb/etc /home/your-user/couchdb/data"
limactl shell default -- bash -c "mkdir -p /home/your-user/caddy/certs /home/your-user/caddy/data /home/your-user/caddy/config"
踩坑:Lima 的 HOME 目錄

~/ 在 Lima shell 中解析到 /Users/your-name(macOS 掛載),是唯讀的。必須明確使用 /home/your-user/ 路徑。

2. CouchDB docker-compose.yml

路徑:/home/your-user/couchdb/docker-compose.yml

services:
  couchdb:
    image: docker.io/library/couchdb:3
    restart: unless-stopped
    ports:
      - "5984:5984"
    environment:
      - COUCHDB_USER=`你的帳號`
      - COUCHDB_PASSWORD=`你的密碼`
    volumes:
      - ./data:/opt/couchdb/data
      - ./etc:/opt/couchdb/etc/local.d

3. CouchDB 設定檔

路徑:/home/your-user/couchdb/etc/local.ini

[couchdb]
single_node=true
max_document_size = 50000000
uuid = your-generated-couchdb-uuid

[chttpd]
require_valid_user = true
max_http_request_size = 4294967296
enable_cors = true
bind_address = 0.0.0.0

[chttpd_auth]
require_valid_user = true

[httpd]
WWW-Authenticate = Basic realm="couchdb"
bind_address = 0.0.0.0
enable_cors = true

[cors]
origins = app://obsidian.md,capacitor://localhost,http://localhost
credentials = true
headers = accept, authorization, content-type, origin, referer
methods = GET, PUT, POST, HEAD, DELETE
max_age = 3600
[admins] 區塊

CouchDB 啟動後會自動在 local.ini 寫入 [admins] 區塊,將明文密碼轉為 PBKDF2 hash。這是正常行為,不需要手動修改。

設定重點:

  • single_node=true:單節點模式,不需要叢集
  • max_document_size = 50000000:50MB,LiveSync 附件同步需要
  • max_http_request_size = 4294967296:4GB
  • CORS 開啟:LiveSync 從 Obsidian App 直連 CouchDB 需要

4. 啟動 CouchDB

limactl shell default -- bash -c "cd /home/your-user/couchdb && nerdctl compose up -d"

5. 建立資料庫

curl -X PUT 'http://`你的帳號`:`你的密碼`@127.0.0.1:5984/your-sync-db'
密碼含特殊字元

密碼中的 / 在 URL 裡要編碼為 %2F

踩坑:資料庫名稱限制

LiveSync 插件的 DB name 欄位不支援 -_ 符號。原本取名 my-sync-dbmy_sync_db 都失敗,最終用 yoursyncdb


Caddy 反向代理(HTTPS)

為什麼需要反向代理?

  • Obsidian mobile(iOS/Android)的 LiveSync 強制要求 HTTPS
  • LiveSync 插件無法在個別裝置關閉,iOS 也必須用 LiveSync,所以 HTTPS 是必要的
  • CouchDB 本身不支援 HTTPS
  • Caddy 作為 Lima VM 的統一反向代理,未來新增服務(Vaultwarden 等)只要改 Caddyfile

Tailscale HTTPS 憑證

Tailscale 內建 Let’s Encrypt 憑證簽發,不需要自簽憑證:

# 在 macOS 上產生憑證
tailscale cert node.example.ts.net

# 複製到 Lima VM
limactl copy node.example.ts.net.crt default:/home/your-user/caddy/certs/
limactl copy node.example.ts.net.key default:/home/your-user/caddy/certs/
憑證有效期

Tailscale 憑證約 90 天有效,需定期重新執行 tailscale cert 並複製到 Lima VM。

Caddy docker-compose.yml

路徑:/home/your-user/caddy/docker-compose.yml

services:
  caddy:
    image: docker.io/library/caddy:2-alpine
    restart: unless-stopped
    network_mode: host
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./certs:/etc/caddy/certs:ro
      - ./data:/data
      - ./config:/config
為什麼用 network_mode: host?

Caddy 和 CouchDB 在不同的 compose 專案裡。用 host network 讓 Caddy 直接使用 VM 的網路堆疊,可以透過 127.0.0.1:5984 連到 CouchDB,未來加任何服務都能直接連到。

Caddyfile

路徑:/home/your-user/caddy/Caddyfile

{
	auto_https off
}

node.example.ts.net:443 {
	tls /etc/caddy/certs/node.example.ts.net.crt /etc/caddy/certs/node.example.ts.net.key

	handle_path /couchdb/* {
		reverse_proxy 127.0.0.1:5984
	}
}

設定說明:

  • auto_https off:關閉 Caddy 自動 HTTPS,因為我們手動管理 Tailscale 憑證
  • handle_path /couchdb/*:將 /couchdb/ 路徑的請求反向代理到 CouchDB,並自動去除 /couchdb 前綴
  • 未來新增服務,在此檔案加新的 handle_path 區塊即可

啟動 Caddy

limactl shell default -- bash -c "cd /home/your-user/caddy && nerdctl compose up -d"

擴充範例(未來加 Vaultwarden)

node.example.ts.net:443 {
	tls /etc/caddy/certs/node.example.ts.net.crt /etc/caddy/certs/node.example.ts.net.key

	handle_path /couchdb/* {
		reverse_proxy 127.0.0.1:5984
	}

	handle_path /vaultwarden/* {
		reverse_proxy 127.0.0.1:8080
	}
}

Lima Port Forward 設定

~/.lima/default/lima.yaml(約第 507 行):

portForwards:
- guestPort: 443
  hostIP: "0.0.0.0"
- guestPort: 5984
  hostIP: "0.0.0.0"

修改後需重啟 Lima VM(容器設定了 restart: unless-stopped,重啟後會自動恢復):

limactl stop default && limactl start default

驗證:log 中看到以下兩行即成功:

  • Forwarding TCP from [::]:443 to 0.0.0.0:443
  • Forwarding TCP from [::]:5984 to 0.0.0.0:5984

LiveSync 插件設定

安裝

Obsidian → Settings → Community plugins → Browse → 搜尋 “Self-hosted LiveSync” → Install → Enable

初始設定流程

  1. 選擇 Minimal setup(不是 Use a Setup URI)
  2. 填入連線資訊:
    • URI: https://node.example.ts.net/couchdb(全裝置通用,含 mobile)
    • http://localhost:5984(本機直連,僅限同一台電腦)
    • Database: yoursyncdb
    • Username: 你的帳號
    • Password: 你的密碼
  3. E2EE不啟用(見下方說明)
  4. Internal API:啟用(效能較好)
  5. 同步模式:啟用 LiveSync(即時 P2P 雙向同步)

多裝置設定

  • 主力機(第一台):Rebuild Everything → 選「I am setting up a new server for the first time / I want to reset my existing server」
  • 其他裝置:等主力機同步完 → Rebuild Everything → 選「My remote server is already set up. I want to join this device」
  • 其他裝置的 vault 內容跟主力機差不多 → 選「The files in this Vault are almost identical to the server’s」

初次同步

  • 首次會把整個 vault 推送到 CouchDB(1000+ 筆記、20000+ chunks)
  • 出現 “Do you want to send all chunks before replication?” → 選 Yes
  • 資源消耗:CPU 167%、RAM 125MB、網路進 55.8MB(同步完成後降至 CPU 6%、RAM 115MB)
踩坑:Fetch Remote Configuration Failed

首次設定時會報 “Could not fetch configuration from remote”,這是正常的。因為新資料庫裡還沒有任何設定檔。直接跳過繼續。

踩坑:Broken files detected

同步過程中偵測到壞檔案會阻止同步。先選 “Check it later” 讓整體同步跑完,之後回來處理壞檔案即可恢復正常。


E2EE 的教訓

不建議啟用 E2EE

曾經啟用 E2EE(含 Obfuscate Properties),結果遇到嚴重問題:

  1. 多裝置解密失敗:第三台裝置即使 passphrase 完全一致,仍報 “Decryption with HKDF failed on Path”
  2. 特定檔案加解密出錯:大檔、含特殊字元的檔名、二進位附件容易觸發
  3. 關閉 E2EE 需要全部重來:清空資料庫、所有裝置重新同步

結論: 走 Tailscale 內網已有 WireGuard 加密,傳輸安全性足夠,不需要再疊一層 E2EE。關閉 E2EE 後同步速度明顯提升,也更穩定。

清空資料庫重建流程(關閉 E2EE 時用到)

# 刪除並重建
curl -X DELETE 'http://`你的帳號`:`你的密碼`@127.0.0.1:5984/yoursyncdb'
curl -X PUT 'http://`你的帳號`:`你的密碼`@127.0.0.1:5984/yoursyncdb'

# 清除廢棄資料庫
curl -X DELETE 'http://`你的帳號`:`你的密碼`@127.0.0.1:5984/my-sync-db'
curl -X DELETE 'http://`你的帳號`:`你的密碼`@127.0.0.1:5984/my_sync_db'

# 驗證
curl 'http://`你的帳號`:`你的密碼`@127.0.0.1:5984/_all_dbs'
# 預期:["_replicator","_users","yoursyncdb"]

然後主力機 reset server,其他裝置 join。


同步架構決策

為什麼不用 Cloudflare / Linode?

Tailscale 內網 + Caddy HTTPS 已經能讓所有裝置(含 mobile)互通,走內網延遲低、免費、憑證自動簽發。不需要公網部署。

為什麼 HTTPS 是必要的?

原本以為電腦端用 HTTP、iOS 走 iCloud 就好,不需要 HTTPS。但因為 LiveSync 插件無法在個別裝置關閉,iOS 也必須用 LiveSync 同步,而 Obsidian mobile 強制要求 HTTPS,所以 HTTPS 變成必要設定。

iCloud 方案已放棄

iCloud + LiveSync 不能共存

原本計畫讓 Mac mini 同時走 iCloud 和 LiveSync,iOS 單獨走 iCloud。但 LiveSync 是 vault 層級的插件,無法在個別裝置上單獨關閉同步。一旦 vault 啟用 LiveSync,所有裝置都必須參與。因此 iCloud 同步已完全放棄,全部改走 LiveSync + Tailscale HTTPS。

所有裝置都必須裝 LiveSync

LiveSync 是同步型插件,vault 內啟用後所有開啟該 vault 的裝置都會同步。包括 iOS 也必須安裝並設定 LiveSync,連線到 HTTPS endpoint https://node.example.ts.net/couchdb

LiveSync 也支援 S3?

是的,可用 AWS S3、MinIO、Cloudflare R2 等替代 CouchDB。但目前用 CouchDB 走 Tailscale 內網免費且快速,沒有必要換。


nerdctl vs Docker

Lima VM 使用 nerdctl(containerd 前端),非 Docker。個人用途完全足夠:

  • 功能與 Docker 幾乎一致,compose 也支援
  • 免費、無授權限制(Docker Desktop 商業用要付費)
  • CouchDB 這類標準 image 跑起來沒有任何差異
  • 資源消耗極低:閒置時 CPU < 6%、RAM 約 115MB
nerdctl stats 注意事項

nerdctl stats --no-stream 在 Lima VM 中偶爾會卡住不退出,累積殭屍進程吃 CPU。如果 load average 異常飆高,用 ps aux | grep 'nerdctl stats' 檢查並 kill。


連線資訊

LiveSync 插件填入(全裝置通用)

項目
URIhttps://node.example.ts.net/couchdb
Databaseyoursyncdb
Usernameadmin
Password你的密碼
iOS / mobile 裝置

必須先開啟 Tailscale VPN 才能連到 node.example.ts.net

服務位置

項目
CouchDB 位置Lima VM /home/your-user/couchdb/
Caddy 位置Lima VM /home/your-user/caddy/
CouchDB 版本3.5.1
HTTPS URIhttps://node.example.ts.net/couchdb
HTTP URI(本機直連)http://localhost:5984http://100.115.83.44:5984

檔案結構總覽

/home/your-user/
├── couchdb/
│   ├── docker-compose.yml
│   ├── data/                 # CouchDB 資料
│   └── etc/
│       └── local.ini         # CouchDB 設定
├── caddy/
│   ├── docker-compose.yml    # network_mode: host
│   ├── Caddyfile             # 反向代理設定
│   ├── certs/                # Tailscale TLS 憑證
│   │   ├── node.example.ts.net.crt
│   │   └── node.example.ts.net.key
│   ├── data/
│   └── config/
├── nginx-proxy-manager/      # 舊,未使用
└── zoraxy/                   # 舊,未使用

待處理

  • 多裝置同步鏈路完整測試(全裝置透過 LiveSync HTTPS 同步)
  • Tailscale HTTPS 憑證自動更新機制(目前手動,90 天到期)

MCP 設定備忘

此次也處理了 Claude Code 的 MCP 設定:

  • 移除 Todoist MCPclaude mcp remove todoist(從 ~/.claude.json 移除)
  • 新增 Obsidian MCP (stdio)claude mcp add --transport stdio obsidian -- node /Users/your-name/mcp-obsidian/dist/index.js --stdio
  • MCP server 定義要放在 ~/.claude.json(按 project 路徑分區),不是 ~/.claude/settings.json
  • settings.json 只放權限、effort level 等設定,不放 MCP server
  • Vault 路徑:已從 iCloud 改為 /Users/your-name/Obsidian Vault/個人筆記庫(設定檔:~/.obsidian-mcp.json