The vault is on an always-on host, your laptop edits it, and now the cluster and your AI agents want it too. The naive answer — clone it everywhere — quietly recreates the exact ⚠️ split-brain we’ve fought all series: multiple writable copies, each drifting. This post gives everyone access without a second authority.
One editing client, many readers. The machine you edit from gets a direct read-write mount; everything else — cluster services, agents, other machines — reaches the vault through a read-only forced-command SSH interface that can only status, read, and search, and reports the commit on every read.
Replace the stand-ins with your own: 10.0.0.76 → your vault host’s IP; vaultreader → the account you create for readers; the ssh-ed25519 AAAA… key → your own generated public key; /wiki-data/git → your repo path; the commit 64dc195 is just an example.
The access topology
The laptop writes; everyone else reads. Because the readers cannot write, none of them can become a competing authority — the split-brain is structurally impossible, not merely discouraged.
Building the read-only reader
An SSH command= restriction (authorized_keys forced command) pins a key to exactly one program. Connect with that key and you get the reader, never a shell.
The reader accepts a small verb set — status, read <path>, search <query> — and always prints the current commit. It refuses anything else.
#!/bin/bash
# Invoked via SSH forced command. $SSH_ORIGINAL_COMMAND holds the request.
set -euo pipefail
VAULT=/wiki-data/git
COMMIT=$(git -C "$VAULT" rev-parse HEAD)
read -r verb arg <<< "$SSH_ORIGINAL_COMMAND"
case "$verb" in
status) echo "commit $COMMIT" ;;
read) echo "commit $COMMIT"; git -C "$VAULT" show "HEAD:$arg" ;;
search) echo "commit $COMMIT"; git -C "$VAULT" grep -n "$arg" -- '*.md' ;;
*) echo "denied: read-only reader (status|read|search)"; exit 1 ;;
esac
command="/usr/local/bin/vault-reader",no-pty,no-port-forwarding,no-agent-forwarding,no-X11-forwarding ssh-ed25519 AAAA... vault-reader-key
Now that key can only run the reader. A cluster agent using it can read and search the vault — and learns the commit on every call — but cannot write, cannot get a shell, cannot forward anything. That’s least privilege (NIST’s term) made concrete: each consumer gets exactly the access its job requires and nothing more.
ssh -i ~/.ssh/vault-reader vaultreader@10.0.0.76 "status"
# → commit 64dc195
ssh -i ~/.ssh/vault-reader vaultreader@10.0.0.76 "read runbooks/example.md"
# → commit 64dc195 (then the file contents)
The reader prints the commit first on purpose. A consumer (like an agent’s begin step) compares it to the expected HEAD and stops if they differ. A read interface that hides its revision turns a stale cache into invisible misinformation.
The full reader, key restrictions, and a consumer wrapper are in the paired playbook: Canonical Vault Restricted Reader.
The swap-in box
Git natively: a bare repo with read-only deploy keys gives readers a clone they can pull but not push — pair it with a commit-reporting wrapper. HTTP: a read-only API in front of the repo (returning content plus the commit header) is the same idea over a different transport. The rule: exactly one writable path to the authority; every other consumer is read-only and reveals its revision.
What you have now
Every machine and agent can read current vault state, and not one of them can fork it — the split-brain failure mode is closed off by construction. The readers above return raw pages; the next post gives them semantic search that still knows its own version: local RAG that knows its own version.
Related posts:
- Make Your AI Agents Read the Docs First, Every Time — the agents that consume this read-only reader
- Semantic Search for Your Notes, Running Locally — semantic search built as another read-only consumer
- Why Auto-Syncing Your Notes Repo Will Corrupt It — the single writable path this preserves
- Tailscale Subnet Router: Remote Access to Your Entire Homelab — the network layer readers reach the vault over
- Already Made a Mess of Your Notes? Here’s the Fix — fixing split-brain once it has already happened
Comments
Comments are powered by GitHub Discussions — sign in with a GitHub account to join the conversation.