- 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>
85 lines
2.9 KiB
YAML
85 lines
2.9 KiB
YAML
---
|
|
# =============================================================================
|
|
# provision-wong-host.yml — spaceship-earth (WDWL-22)
|
|
#
|
|
# spaceship-earth runs exactly ONE agent: wong, the personal vault's librarian
|
|
# and its only writer. No other agent may be pinned to its runtime. The
|
|
# isolation is enforced by the OS, not by agent instructions: Obsidian Sync
|
|
# runs as `obsync`, and Wong's daemon user (multica) can reach inbox/ only.
|
|
#
|
|
# Run order on a fresh host:
|
|
# 1. ansible-playbook playbooks/provision-agent-host.yml --limit spaceship-earth
|
|
# (multica daemon user, Node.js, multica CLI, Claude Code)
|
|
# 2. ansible-playbook playbooks/provision-wong-host.yml
|
|
# (root LV growth, headless Obsidian, vault folder isolation)
|
|
#
|
|
# Step 2 needs Node.js and the multica user from step 1, and asserts both.
|
|
# The Obsidian account sign-in is manual; see roles/obsidian_headless/README.md.
|
|
# =============================================================================
|
|
|
|
- name: Grow the root filesystem to fill the disk
|
|
hosts: spaceship-earth
|
|
become: true
|
|
tags: [wong_disk]
|
|
|
|
vars:
|
|
root_vg: ubuntu-vg
|
|
root_lv: ubuntu-lv
|
|
|
|
tasks:
|
|
- name: Disk | Find the PV backing the root VG
|
|
ansible.builtin.set_fact:
|
|
_root_pv: >-
|
|
{{ ansible_facts['lvm']['pvs'] | dict2items
|
|
| selectattr('value.vg', 'equalto', root_vg)
|
|
| map(attribute='key') | first }}
|
|
|
|
- name: Disk | Split the PV into disk and partition number
|
|
ansible.builtin.set_fact:
|
|
_root_disk: "{{ _root_pv | regex_replace('p?[0-9]+$', '') }}"
|
|
_root_partno: "{{ _root_pv | regex_search('[0-9]+$') }}"
|
|
|
|
- name: Disk | Install growpart
|
|
ansible.builtin.package:
|
|
name: cloud-guest-utils
|
|
state: present
|
|
|
|
# growpart exits 1 with "NOCHANGE" when the partition already fills the disk.
|
|
- name: Disk | Grow the partition
|
|
ansible.builtin.command:
|
|
argv: [growpart, "{{ _root_disk }}", "{{ _root_partno }}"]
|
|
register: _growpart
|
|
changed_when: _growpart.rc == 0 and 'CHANGED' in _growpart.stdout
|
|
failed_when: _growpart.rc != 0 and 'NOCHANGE' not in _growpart.stdout
|
|
|
|
- name: Disk | Grow the PV and VG
|
|
community.general.lvg:
|
|
vg: "{{ root_vg }}"
|
|
pvs: "{{ _root_pv }}"
|
|
pvresize: true
|
|
|
|
- name: Disk | Extend the root LV and its filesystem into the free space
|
|
community.general.lvol:
|
|
vg: "{{ root_vg }}"
|
|
lv: "{{ root_lv }}"
|
|
size: +100%FREE
|
|
resizefs: true
|
|
|
|
- name: Headless Obsidian Sync with vault folder isolation
|
|
hosts: spaceship-earth
|
|
become: true
|
|
tags: [obsidian]
|
|
|
|
vars:
|
|
obsidian_headless_vault_path: /srv/obsidian/vault
|
|
obsidian_headless_device_name: spaceship-earth
|
|
obsidian_headless_private_folders:
|
|
- everpure
|
|
- wip
|
|
obsidian_headless_shared_folders:
|
|
- path: inbox
|
|
user: multica
|
|
|
|
roles:
|
|
- role: obsidian_headless
|