sotashimozono_obsidian-remo.../docs/en/tutorial.md
Souta 07435647d3 fix(docs): correct review-pass findings on PR #294
Critical:
- api/examples.md + api/overview.md: framing protocol was wrong. Daemon
  uses LSP-style `Content-Length: <N>\r\n\r\n<body>` framing
  (server/internal/rpc/frame.go), NOT 4-byte big-endian length prefix.
  The shell smoke-test as written would have failed with "missing
  Content-Length". Both files now show the correct framing + the
  16 MiB max-message cap. Worst self-fabrication of this PR — the
  examples.md preamble explicitly claimed wire-accuracy from
  proto/types.go while echoing this pre-existing bug.
- 4 broken cross-folder relative links from the architecture/contributing
  migration: perf.md → testing-strategy.md, shadow-vault.md →
  plugin-compatibility.md (×2), testing-strategy.md → shadow-vault.md.
  All now use the correct `../<folder>/<file>.md` paths.

Important:
- api/examples.md server.info capabilities array: actual response is
  alphabetically sorted (sort.Strings) and includes EVERY registered
  method — auth + server.info + 20 fs.* methods = 22 entries. The doc
  showed a hand-curated 20-entry list in registration order.
- plugin-compatibility.md: 5 GitHub issue links used `../../issues/NNN`
  which resolved to repo-root when the file lived at docs/, but now
  resolves to docs/issues/ (404). Switched to absolute github.com URLs.

Advisory:
- "RPC daemon" UI label inaccuracy in 3 docs (raspberry-pi-vault,
  tutorial, quickstart) — actual ProfileForm.ts shows
  "Daemon (deploys helper on connect)" / "SFTP (direct)" labels.
- Fake `tailscale status` output line (no `alias:` row exists);
  replaced with realistic format + an `tailscale ip -4` example.
2026-05-10 15:18:20 +09:00

6.8 KiB
Raw Blame History

title tags
Tutorial — zero to a working vault
tutorial
getting-started

Tutorial — zero to a working vault

A long-form walkthrough that takes you from "I just heard about this plugin" to "I'm editing notes on a remote server and trust the setup". About 20 minutes if you already have a server with SSH access; closer to an hour if you also need to set up the server.

This synthesises en/getting-started/install, en/getting-started/quickstart, en/getting-started/first-connect, and en/security/cosign-verify. If you only want one of those, jump there directly.

What we're going to build

graph LR
  L[Your laptop] -.SSH.- R[Remote host]
  L --- O[Obsidian]
  O --- P[Plugin]
  P --- SV[Local shadow vault]
  R --- D[Daemon]
  D --- V[Real vault files]
  P -.RPC over SSH tunnel.- D
  SV -.synced via daemon.- V

By the end:

  • A signed daemon binary running on a remote host you control
  • An Obsidian window editing files that physically live on that remote
  • The trust chain (host key, daemon binary signature) explicitly verified

Step 1 — Install Obsidian + the plugin

If you don't have Obsidian: install it from obsidian.md. Open it once and create or open any vault — Obsidian needs a vault loaded for the plugin to install into.

Install the plugin via one of:

  • Stable (Community Plugins store): Settings → Community plugins → Browse → search Remote SSH. Awaiting the store team's review at time of writing — see en/getting-started/install.
  • Beta (BRAT): install BRAT, paste sotashimozono/obsidian-remote-ssh with --beta.

Enable it. You'll see a "Remote SSH" entry in Settings.

Step 2 — Pick (or set up) a remote host

You need an SSH-reachable Linux or macOS host with:

  • Your public SSH key in ~/.ssh/authorized_keys
  • A directory to use as a vault (can be empty)

Got one already? Skip ahead.

If not:

  • Cheapest: a Raspberry Pi 4 + microSD on your home network — see en/cookbook/raspberry-pi-vault.
  • Cloud VPS: any $5/month tier from Hetzner / DigitalOcean / OVH works fine; see en/cookbook/share-via-tailscale for a sane way to reach it without exposing port 22 to the public internet.
  • Sandbox just to try: clone the repo and run cd deploy/docker && docker compose up -d --build; see en/server/docker.

If ssh user@host works from a normal terminal, you're ready.

The plugin auto-uploads its bundled daemon binary on first connect. If you'd like to know what's getting uploaded, verify it with cosign first.

Find the bundled binary at <your-vault>/.obsidian/plugins/remote-ssh/server-bin/obsidian-remote-server-linux-<arch> after enabling the plugin. Match it against the signed manifest from the latest release:

gh release download 1.0.43 --repo sotashimozono/obsidian-remote-ssh \
  --pattern 'daemon-manifest.json*'

cosign verify-blob \
  --bundle daemon-manifest.json.bundle \
  --certificate-identity-regexp \
    'https://github.com/sotashimozono/obsidian-remote-ssh/.github/workflows/release.yml@.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  daemon-manifest.json
# → Verified OK

sha256sum '<vault>/.obsidian/plugins/remote-ssh/server-bin/obsidian-remote-server-linux-amd64'
grep linux-amd64 daemon-manifest.json
# Hashes should match.

For the full background on what cosign is checking, see en/security/cosign-verify.

Step 4 — Add a profile

In Obsidian: Settings → Remote SSH → Add profile.

Field Value
Profile name My host
Host 192.168.1.50 (or your hostname / Tailscale name)
Port 22
Username your remote user
Authentication SSH agent (preferred) or Private key + path
Remote vault path /home/<you>/notes (must exist)
Mode Daemon (deploys helper on connect)

Save.

Step 5 — Connect for the first time

Command palette → Remote SSH: Connect → pick your profile.

What happens, in order:

  1. Host-key trust dialog appears with the remote's fingerprint. Compare with the value from a different channel (a console session on the remote, your provider's web console, your previous ssh session's output) — see en/security/host-keys for what each button does. Click Trust & remember when satisfied.

  2. Plugin uploads the daemon to ~/.obsidian-remote/server and verifies the SHA256 round-trip.

  3. Plugin starts the daemon under your remote user. The daemon writes a 32-byte token to ~/.obsidian-remote/token (mode 0600).

  4. A new Obsidian window opens showing the contents of your remote vault.

First connect: ~58 seconds (binary upload). Subsequent connects: ~1 second.

Step 6 — Verify it's actually editing the remote

In the new window, create a file tutorial-test.md with some content. Save (Ctrl-S / ⌘S).

In a separate terminal:

ssh user@host 'cat ~/notes/tutorial-test.md'
# → your content

The file is on the remote. There's no local copy outside the shadow-vault cache (which lives at ~/.obsidian-remote/vaults/<profile-id>/ on your laptop and is automatically managed).

Step 7 — Edit from the other side

While the Obsidian window is open, on the remote:

ssh user@host 'echo "edit from terminal" >> ~/notes/tutorial-test.md'

Within ~500 ms, Obsidian's view should reflect the new line. That's the daemon's fs.watch subscription pushing the change through the SSH tunnel.

Step 8 — Disconnect cleanly

Command palette → Remote SSH: Disconnect, or just close the shadow-vault window.

The daemon stays running on the remote for ~5 minutes (configurable) so a quick reconnect skips the binary upload + token re-read.

What's next

You're done with the basic setup. Common next steps:

If something didn't work: en/operations/troubleshooting is the first place to look.