Addresses the WKS PoC review (Notion 2026-05-26). All docs in English. - README: purpose, docs table of contents, annotated repo tree - docs/getting_started.md: prerequisites (WKS account, OIDC, SSH, VPN) + first deploy - docs/ansible.md: playbook table, "Running Ansible", service parameters, cheatsheet - docs/secrets.md: canonical Bao login (moved out of README) + demo defaults - docs/operations.md: full Makefile reference - docs/inventories.md: repo layout, topology, standard folder structure, walkthrough - docs/testing.md: static checks, inventory resolution, smoke test / dry run - remove ARCHITECTURE.md (architecture docs live externally) Also includes the gymburgdorf inventory build-out (bookstack, homarr, opnform, send) and scripts/bao-seed.sh. site.yml keeps a third traefik play (traefik_servers minus the vagrant _dmz/_backend split) so the demo inventories still configure their reverse proxy after the rebase onto main.
5.8 KiB
Setup & operations
Prerequisites (control node)
ansible(Core ≥ 2.15)baoCLI (OpenBao) — e.g.sudo pacman -S openbao python-hvac(Arch) or via Homebrewpython-hvac(forcommunity.hashi_vaultlookups)- On macOS:
OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES(set in the Makefile; without this env var, Ansible forks crash on the firstcommunity.hashi_vaultlookup, because the Objective-C runtime is not fork-safe)
Initial setup
git clone <repo>
cd reference-ansible
make install # Galaxy + digitalboard.core into ./collections/
make install installs community.hashi_vault and the
digitalboard.core collection (Git, see requirements.yml)
into ./collections/. There is no roles/ directory in the
repo root — all roles come from the collection, see
inventories.md § Repo layout.
Secrets (OpenBao)
Before every deploy, authenticate to OpenBao in the same shell. The
full login flow, the make bao caveat, the lookup pattern, and
tenant isolation are documented in secrets.md.
Smoke test
make ping_demo # pings all three demo inventories (ping module)
Deploy
make deploy_site_demo_gymburgdorf # single demo site
make deploy_site_demo_mbazürich
make deploy_site_demo_phbern
make deploy_site_demo # all three in sequence
--diff is set in the Gymburgdorf target → changes are visible per task.
The play order and which plays run as no-ops:
see ansible.md § Playbooks.
Makefile reference
The Makefile bundles setup, secret handling, and deploy.
It defines no variables for passing in except DRY_RUN (for the
seed_bao_* targets) — control is via the chosen target.
Exported env vars (apply to all targets)
| Variable | Value | Purpose |
|---|---|---|
BAO_ADDR |
https://bao.digitalboard.ch |
OpenBao endpoint for bao and community.hashi_vault calls |
OBJC_DISABLE_INITIALIZE_FORK_SAFETY |
YES |
macOS fork safety: without this var, Ansible forks crash on the first hashi_vault lookup, because the Objective-C runtime is not fork-safe |
Both are set via
exportat the top of the Makefile and thus inherited by every target shell process — regardless of which target runs.
Setup & secrets
| Target | Effect |
|---|---|
make install |
ansible-galaxy collection install -r requirements.yml -p collections — installs community.hashi_vault + digitalboard.core into ./collections/ |
make bao |
bao login -method=oidc -path=Digitalboard role=default + sets VAULT_TOKEN via $(eval …). ⚠️ The token only lives within this single make invocation — see caveat below |
make seed_bao_gymburgdorf |
Seed/merge OpenBao secrets for demo-gymburgdorf via scripts/bao-seed.sh. Idempotent: existing keys remain, only missing ones are generated |
make seed_bao_mbazürich |
same for demo-mbazürich |
make seed_bao_phbern |
same for demo-phbern |
The
seed_bao_*targets understandDRY_RUN=1— shows the diff without writing:make seed_bao_gymburgdorf DRY_RUN=1. Requirement:bao,jq,opensslin$PATHand a validVAULT_TOKEN.
Smoke test & deploy
| Target | Effect |
|---|---|
make ping_demo |
ansible … -m ping against all three demo inventories in sequence; failures of individual hosts do not abort (|| true) |
make deploy_site_demo_gymburgdorf |
ansible-playbook playbooks/site.yml -i …/demo-gymburgdorf/hosts.yml --diff |
make deploy_site_demo_mbazürich |
same for demo-mbazürich — without --diff |
make deploy_site_demo_phbern |
same for demo-phbern — without --diff |
make deploy_site_demo |
calls the three deploy_site_demo_* targets in sequence |
Inconsistency: Only the Gymburgdorf target sets
--diff. Formbazürichandphbernyou do not see the task changes — if needed, invoke directly withansible-playbook … --diff, see ansible.md § Running Ansible.
Token caveat (make bao)
make bao alone is not enough for a deploy: each make target
runs in its own shell, the VAULT_TOKEN set there only lives
during make bao itself and is already gone in the next make deploy_….
Two working approaches:
# Variant A — log in manually in the active shell (survives multiple make invocations)
export BAO_ADDR=https://bao.digitalboard.ch
bao login -method=oidc -path=Digitalboard
export VAULT_TOKEN=$(bao print token)
make deploy_site_demo_gymburgdorf
# Variant B — chain both as ONE make invocation (token lives for the chain)
make bao deploy_site_demo_gymburgdorf
Login details and the secret pattern: secrets.md.
Known gaps and trade-offs
opencloudindemo-gymburgdorf: Play present, but noopencloud_serversgroup — runs as a no-op. If needed, add a group +host_vars, see inventories.md.turnhost: defined in the DMZ, but no STUN/TURN role in playbooks/site.yml — provisioned only viabase+traefik.- Idempotency: Roles are Docker-Compose-based; re-runs can trigger container restarts when Compose inputs change. No rollback mechanism — on failure, roll back manually.
- TLS renewal: handled internally by Traefik via ACME, no external renew cron in the repo.
- CI/testing: currently not in the repo; smoke test via
make ping_demo. - Logging:
traefik_log_level: DEBUGindemo-gymburgdorfandvagrant(role defaultINFO) — reduce before adapting to prod.