- provision-agent-host.yml: multica_pat now comes from vault_multica_pats[inventory_hostname_short], one daemon-<host> token per host. A pre_task asserts the key exists (never prints the value) so a missing entry fails by host name instead of as a no_log "censored". - provision-wong-host.yml: spaceship-earth only. Grows the root partition, PV and LV/filesystem with growpart + community.general.lvg/lvol; idempotent (second run changed=0). Then applies obsidian_headless. - roles/obsidian_headless: Obsidian's official headless Sync client (obsidian-headless 0.0.14) as system user obsync under a sandboxed systemd unit with UMask=0077. Vault at /srv/obsidian/vault: everpure/ and wip/ obsync-only, inbox/ granted to multica via access + default ACLs, vault root traverse-only. Verifies the isolation as multica. Sign-in to Obsidian Sync stays manual (see the role README). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3.5 KiB
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:rwx, plus the same 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. 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.