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>
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
-
Creates the system user
obsync, with a0700home in/var/lib/obsync. That home holds the Obsidian account token and per-vault sync state. -
Installs the pinned
obsidian-headlessinto that user's npm prefix and linksobinto/usr/local/bin. Node.js is not installed here. The role asserts that the runtimemultica_agent_hostinstalls is present and is at least version 22. -
Lays out the vault folder and its permissions:
Path Mode ACL /srv/obsidian/0710 obsyncuser:multica:--x/srv/obsidian/vault/0710 obsyncuser:multica:--x, somulticacan traverse but not listvault/everpure/,vault/wip/0700 obsyncnone vault/inbox/0770 obsyncuser:multica:rwxanduser:obsync:rwx, each also as a default entryOn a directory with an ACL, the mode's group bits are the ACL mask. A
chmod 0700would therefore void every named entry, which is why the shared paths use0710and0770. The owning group isobsync's private group, so those bits grant nobody anything. -
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. -
Verifies the isolation as the users themselves:
multicawrites, reads and deletes ininbox/.- A folder and file created by
obsyncunder umask0077(the way Sync creates them) stay readable and writable bymultica. - What
multicacreates stays readable and writable byobsync. Those files are ownedmultica:multica, so without the nameduser:obsyncdefault entry Sync could not read them and would never upload them. multicais refused both listing the vault root and listing or writingeverpure/andwip/.
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 tomultica. - Everywhere else,
UMask=0077applies, so new content is private toobsync. That covers any new top-level folder and.obsidian/. - If Sync deletes and recreates
inbox/itself, the recreated folder is private andmulticaloses 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.