Files
JARVISandClaude Opus 5.5 fc2ad85e19 obsidian_headless: grant the service user on shared folders too (WDWL-22)
Content multica creates in inbox/ is owned multica:multica, so obsync fell
into "other" (---) and Sync could neither read nor upload Wong's
submissions. Found after the real Sync sign-in on spaceship-earth; the
earlier verify only tested the obsync -> multica direction.

Shared folders now carry user:obsync:rwx as an access and a default entry
alongside the shared user's, and verify tests the multica -> obsync
direction (read + rewrite, as merge needs). Second run changed=0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 21:28:52 -05:00
..

obsidian_headless

Runs Obsidian's official headless Sync client (obsidian-headless, command ob, open beta) as a dedicated unprivileged user under a systemd unit. It lays out the vault folder so that other local users reach only the folders granted to them.

Written for spaceship-earth (WDWL-22). Wong's daemon user (multica) may read and write inbox/ and nothing else. everpure/ and wip/ are obsync only. Entry point: playbooks/provision-wong-host.yml.

What it does

  1. Creates the system user obsync, with a 0700 home in /var/lib/obsync. That home holds the Obsidian account token and per-vault sync state.

  2. Installs the pinned obsidian-headless into that user's npm prefix and links ob into /usr/local/bin. Node.js is not installed here. The role asserts that the runtime multica_agent_host installs is present and is at least version 22.

  3. Lays out the vault folder and its permissions:

    Path Mode ACL
    /srv/obsidian/ 0710 obsync user:multica:--x
    /srv/obsidian/vault/ 0710 obsync user:multica:--x, so multica can traverse but not list
    vault/everpure/, vault/wip/ 0700 obsync none
    vault/inbox/ 0770 obsync user:multica:rwx and user:obsync:rwx, each also as a default entry

    On a directory with an ACL, the mode's group bits are the ACL mask. A chmod 0700 would therefore void every named entry, which is why the shared paths use 0710 and 0770. The owning group is obsync's private group, so those bits grant nobody anything.

  4. Installs obsidian-sync.service (User=obsync, UMask=0077, sandboxed) and enables it. It is started only once a vault has been set up. Condition*= lines keep it inert until then, including across reboots.

  5. Verifies the isolation as the users themselves:

    • multica writes, reads and deletes in inbox/.
    • A folder and file created by obsync under umask 0077 (the way Sync creates them) stay readable and writable by multica.
    • What multica creates stays readable and writable by obsync. Those files are owned multica:multica, so without the named user:obsync default entry Sync could not read them and would never upload them.
    • multica is refused both listing the vault root and listing or writing everpure/ and wip/.

Do modes and ACLs survive Sync?

Obsidian Sync carries no Unix modes or ACLs. Files are created locally by obsync, so their permissions come from this host, not from the remote:

  • In inbox/, the default ACL applies and the umask is ignored, so new content is granted to multica.
  • Everywhere else, UMask=0077 applies, so new content is private to obsync. That covers any new top-level folder and .obsidian/.
  • If Sync deletes and recreates inbox/ itself, the recreated folder is private and multica loses access. The failure is closed, not open, and re-running the play restores the grant.

Manual step: sign in and set up the vault (once per host)

The role never handles the Obsidian account. Run these as obsync; -H makes HOME point to /var/lib/obsync:

sudo -u obsync -H ob login
sudo -u obsync -H ob sync-list-remote
sudo -u obsync -H ob sync-setup --vault "<vault name>" \
     --path /srv/obsidian/vault --device-name spaceship-earth
sudo systemctl start obsidian-sync
journalctl -u obsidian-sync -f

Re-running the play after this starts the unit as well. Do not also run desktop Obsidian Sync on this host: Obsidian warns that two Sync clients on one device conflict.

Tags

obsidian_user, obsidian_install, obsidian_layout, obsidian_service, obsidian_verify. The play itself is tagged obsidian.