# Secrets & security [← Documentation index](README.md) > This repo is explicitly intended for **demo setups**. All > default values in the roles are insecure and are overridden in > `demo-*` inventories via Bao lookups or host_vars. ## OpenBao login A prerequisite is a WKS account with OIDC access to OpenBao and a read policy on the inventory mount — see [getting_started.md § Vorbedingungen](getting_started.md#prerequisites). Before each deploy, authenticate in **the same shell** in which `ansible-playbook` then runs: ```bash export BAO_ADDR=https://bao.digitalboard.ch bao login -method=oidc -path=Digitalboard export VAULT_TOKEN=$(bao print token) ``` > ⚠️ `make bao` alone is **not** enough — every `make` target runs in > a new shell, and the `VAULT_TOKEN` set there lives only during > `make bao` itself. Either run the three commands above manually > or chain `make bao deploy_site_demo_gymburgdorf` as **one** call > — otherwise the deploy has no token. ## Secret pattern (Bao lookup) Secrets are never stored in plaintext, but read from OpenBao at runtime: ```yaml # host_vars/.../.yml — one lookup per service path, # individual keys as properties: _nextcloud: "{{ lookup('community.hashi_vault.hashi_vault', vault_mount + '/data/nextcloud', url=vault_addr) }}" nextcloud_admin_password: "{{ _nextcloud.admin_password }}" nextcloud_postgres_password: "{{ _nextcloud.postgres_password }}" ``` - `vault_mount` and `vault_addr` come from [group_vars/all/vault.yml](../inventories/demo-gymburgdorf/group_vars/all/vault.yml). - KV-v2 paths need an explicit `/data/` in the path — Ansible does not resolve this on its own. - `vault_mount` is unique per inventory (`demo-gymburgdorf`, `demo-phbern`, …) → tenant isolation in Bao via mount + policy. Secrets are seeded idempotently with [scripts/bao-seed.sh](../scripts/bao-seed.sh) (or `make seed_bao_`): existing keys remain, only missing ones are generated. OIDC client secrets are kept in sync between `/data/authentik` and the respective service secret. ## Demo-only defaults — must be overridden These defaults in `digitalboard.core` are insecure. In every **production-grade** deployment they must be overridden via a Bao lookup or host_var: | Variable | Default | Where to override | | --- | --- | --- | | `keycloak_admin_password` | `changeme` | host_vars `keycloak_servers` | | `keycloak_postgres_password` | `changeme` | same as above | | `authentik_secret_key` | `changeme-generate-a-random-string` | `host_vars/application/authentik.yml` | | `authentik_postgres_password` | `changeme` | same as above | | `nextcloud_admin_password` | `admin` | `host_vars/application/nextcloud.yml` | | `nextcloud_postgres_password` | `changeme` | same as above | | `nextcloud_s3_key` / `nextcloud_s3_secret` | `changeme` / `changeme` | same as above | | `garage_webui_password` | `admin` | `host_vars/storage/garage.yml` | | `garage_rpc_secret` | `0123…cdef` (64-hex constant) | same as above | | `garage_admin_token` | identical to `rpc_secret` | same as above | | `garage_metrics_token` | identical to `rpc_secret` | same as above | > **Convention:** Every value above **must** have a Bao lookup in > `demo-*/host_vars/.../...yml` before the > inventory counts as deployable. ## Threat boundaries (status: demo) | Boundary | Status | Note | | --- | --- | --- | | DMZ ↔ backend (172.16.9 ↔ 172.16.19) | **plaintext HTTP** | auth bearer, OIDC code, session cookies travel unencrypted. Demo-ok; prod: mTLS or WireGuard overlay. | | Host firewall | **missing** | The `base` role installs no UFW/nftables. Segmentation depends on the hypervisor/VLAN. | | SSH | `ansible_user: root` | No bastion, no jump host. Key distribution out-of-band. | | Authentik SPOF | **accepted** | IdP and SP services on the same host (`application`). Authentik outage = login outage including LDAP outpost. No break-glass path. | | ACME TSIG key | Bao lookup | One TSIG key per demo zone (`acme_update_key_demo_gymb`), zone-isolated. Rotation manual. | | Backup/DR | **out-of-scope** | Garage `replication_factor: 1`, no Postgres backup job, no Bao snapshot cron. | ## Add for production adaptation - Host FW (extend the `base` role or a dedicated `firewall` role). - mTLS or WireGuard between DMZ and backend. - Authentik on a separate host, with a recovery admin token. - Bao policies per inventory mount (read-only for the deploy token, write-only for the bootstrap job). - Backup cron for Postgres + Garage + Bao. - SSH bastion + key rotation.