sotashimozono_obsidian-remo.../docs/en/server/auto-deploy.md
Souta 545bbe0862 fix(docs): correct reuse-existing-daemon claim across 5 docs + 3 troubleshooting nits
Pass-3 review caught a sustained fabrication: I'd been claiming
"the plugin always kills + redeploys the daemon on every connect,
the 'reuse existing daemon' profile flag is on the roadmap" across
5 docs. Reality (verified against plugin/src/transport/DaemonProbe.ts:49
and plugin/src/ConnectionManager.ts:87): tryReuseExistingDaemon already
runs unconditionally before deploy. It probes socket + token + handshake;
on success the deploy is skipped entirely. The "roadmap flag" framing
was pure invention — the feature ships today.

Fixes (all narrative-level, no behavior change):
- en/server/auto-deploy.md: rewrote "What happens, in order" to lead
  with the reuse probe as step 2 (the real first action after path
  resolution); removed the "planned Reuse existing daemon" claim from
  "What if I don't want auto-deploy" — answer is "you already don't,
  the reuse path runs by default".
- en/server/systemd.md: replaced the "warm spare only" caveat with
  the accurate story (systemd-managed daemon gets reused via the probe).
- en/cookbook/systemd-managed-daemon.md: rewrote the trade-off note +
  the "Connect once" paragraph. The recipe now leads with the right
  expectation (reuse skips the upload) instead of an apologetic
  "accept the redeploy".
- en/faq.md: same correction in the "does the plugin re-deploy every
  connect" answer.
- en/server/raspberry-pi.md: corrected the throwaway "kills + restarts
  on every connect" line at the bottom.

Other pass-3 findings:
- en/api/authentication.md: server.info capabilities array used the
  "fs.read*"/"fs.write*" glob notation, which the daemon never emits.
  Replaced with the actual sorted 22-entry array (matches examples.md).
- en/operations/troubleshooting.md: removed "coalesced too aggressively"
  diagnosis (no server-side coalescing exists, per proto/README.md).
  Updated plugin log path from "<plugin>/logs/*.jsonl" to actual
  console.log location. Updated "Settings → About" (no such section)
  to the real version-display location.
2026-05-10 15:47:27 +09:00

3.6 KiB

title tags
Plugin auto-deploy
server
deploy

Plugin auto-deploy

This is the default. When you connect via an RPC profile, the plugin uploads the daemon binary to the remote and starts it under your SSH user. Nothing to do upfront.

What happens, in order

  1. Resolve remote paths. Every path is absolutised against the remote's HOME — never hardcoded. Defaults:

    • Binary: ~/.obsidian-remote/server
    • Socket: ~/.obsidian-remote/server.sock
    • Token: ~/.obsidian-remote/token
    • Log: ~/.obsidian-remote/server.log
  2. Try to reuse an existing daemon (tryReuseExistingDaemon in plugin/src/transport/DaemonProbe.ts):

    • test -S <socket> — does a Unix socket exist at the expected path?
    • Read the token file via SFTP.
    • Open a Unix-socket stream + send auth(token) + server.info.
    • If all four steps succeed → skip the rest of the deploy flow and use the running daemon. Subsequent connects within ~5 minutes hit this path and finish in ~1 second.
  3. If reuse failed (no socket, bad token, version mismatch, etc.) — fall through to deploy:

    • Kill any partial prior daemon (pkill -f against suffix-form binary path — matches both relative and absolute argv).
    • Create directory: mkdir -p ~/.obsidian-remote && chmod 700 ~/.obsidian-remote.
    • Upload binary via SFTP (~5 MB, fast on LAN, ~2-3s on slow links).
    • SHA256 verify: plugin computes hash locally, runs sha256sum on remote, fails connect if they differ. Catches transport corruption and (less commonly) hostile MITM swaps.
    • Start daemon (one nohup line piping stdout/stderr into ~/.obsidian-remote/server.log, stdin closed).
    • Wait for token: the daemon writes a 32-byte token to ~/.obsidian-remote/token (mode 0600) at startup. Plugin polls (every 150 ms, default 5s deadline).
  4. Open RPC tunnel: SSH local port-forward to the Unix socket, send auth(token), then server.info for handshake.

Tuning

Per-profile overrides under ProfileTransport:

Field Default Override when
Daemon binary path ~/.obsidian-remote/server The remote HOME is on slow disk; want binary on /var/tmp/obsidian-remote/
Daemon socket path ~/.obsidian-remote/server.sock Multiple users sharing one OS account, each needing their own socket (advanced)
Daemon token path ~/.obsidian-remote/token (Almost never)

What if I do not want auto-deploy?

You don't need any opt-in flag — the reuse path (step 2 above) already attaches to a pre-existing daemon when one is healthy. The recipe is simply:

  1. Pre-stage the binary at the path the plugin expects (default ~/.obsidian-remote/server) via Docker / systemd / your own deployment.
  2. Start it with the same flags shown in ~/.obsidian-remote/server.log after one auto-deploy (--vault-root / --socket / --token-file).
  3. Connect from the plugin. The reuse probe finds the live socket + valid token and skips the binary upload entirely.

If reuse fails (token missing, version mismatch with the bundled daemon, socket stale), the plugin falls through to deploy — your pre-staged binary will be killed + replaced. To prevent that fallback you can either:

  • Keep your binary version pinned to whatever the plugin bundle was built against (so the version handshake passes), or
  • Run your daemon under a different binary path / socket path than the plugin's defaults and configure those paths in the profile (the plugin will reuse those paths if healthy and only fall back to the defaults' deploy if not).

Next: en/server/docker for sandbox / shared hosts.