# obsidian_headless Runs Obsidian's official headless Sync client ([`obsidian-headless`](https://obsidian.md/help/sync/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`, plus the same 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`. - `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`: ```bash sudo -u obsync -H ob login sudo -u obsync -H ob sync-list-remote sudo -u obsync -H ob sync-setup --vault "" \ --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`.