# Architekturskizze — `demo-gymburgdorf` Diese Skizze zeigt, wie das `reference-ansible`-Repo am Beispiel der Inventory `demo-gymburgdorf` funktioniert: welche Hosts existieren, welche Rollen darauf laufen, wo welche Variablen hingehören und wie Secrets aus OpenBao gelookupt werden. ## 1. Variablen-Hierarchie (Ansible Precedence) ```mermaid flowchart TB classDef rolelayer fill:#fef3c7,stroke:#92400e,color:#000 classDef grouplayer fill:#dbeafe,stroke:#1e40af,color:#000 classDef hostlayer fill:#dcfce7,stroke:#166534,color:#000 classDef vaultlayer fill:#fee2e2,stroke:#991b1b,color:#000 R["role defaults/main.yml
(niedrigste Precedence)
~180 Variablen über 12 Rollen
z.B. traefik_use_ssl: false
keycloak_admin_password: changeme"]:::rolelayer GA["group_vars/all/
docker.yml → docker_registry_mirrors
vault.yml → vault_addr, vault_mount"]:::grouplayer GT["group_vars/traefik_servers/
traefik.yml
traefik_use_ssl, traefik_cert_mode: acme
traefik_acme_dns_zone
traefik_acme_tsig_* (Vault-Lookup!)"]:::grouplayer GB["group_vars/backend_servers/
traefik.yml → traefik_mode: backend"]:::grouplayer HR["host_vars/reverseproxy/
traefik.yml → traefik_mode: dmz"]:::hostlayer HA["host_vars/application/ (fehlt aktuell!)
FQDNs, OIDC-Clients, DB-Passwords
nextcloud_domain, authentik_domain, ..."]:::hostlayer HS["host_vars/storage/ (fehlt aktuell!)
garage_s3_domain, garage_*_token
traefik_dmz_exposed_services (für DMZ)"]:::hostlayer V["HashiCorp Vault / OpenBao
bao.digitalboard.ch
mount: demo-gymburgdorf
z.B. demo-gymburgdorf/data/acme-tsig"]:::vaultlayer R --> GA --> GT --> GB --> HR GB --> HA GB --> HS GT -.Lookup zur Laufzeit.-> V HA -.Lookup zur Laufzeit.-> V HS -.Lookup zur Laufzeit.-> V ``` Höhere Ebene überschreibt tiefere. `host_vars/reverseproxy/traefik_mode: dmz` schlägt also `group_vars/backend_servers/traefik_mode: backend` — möglich, weil `reverseproxy` *nicht* in `backend_servers` ist. ## 2. Inventory-Topologie demo-gymburgdorf ```mermaid flowchart LR classDef dmz fill:#fee2e2,stroke:#991b1b,color:#000 classDef app fill:#dcfce7,stroke:#166534,color:#000 classDef stor fill:#dbeafe,stroke:#1e40af,color:#000 classDef turn fill:#fef9c3,stroke:#854d0e,color:#000 subgraph ALL["group: all_servers (alle Hosts)"] direction LR subgraph DMZ["DMZ-Segment 172.16.9.0/24"] RP["reverseproxy
172.16.9.111
traefik_mode: dmz"]:::dmz TURN["turn
172.16.9.112
(STUN/TURN)"]:::turn end subgraph BE["Backend-Segment 172.16.19.0/24
(group: backend_servers)"] APP["application
172.16.19.101
traefik_mode: backend
+ nextcloud, opencloud,
collabora, drawio,
authentik, authentik_outpost_ldap"]:::app ST["storage
172.16.19.102
traefik_mode: backend
+ garage (S3)"]:::stor end end RP -.HTTP/HTTPS reverse proxy.-> APP RP -.HTTP/HTTPS reverse proxy.-> ST ``` Gruppen-Mitgliedschaften (`hosts.yml`): - `traefik_servers` ⊇ `all_servers` → **alle 4 Hosts** bekommen Traefik (DMZ-Modus für `reverseproxy`, Backend-Modus für `application`/`storage`). - `backend_servers = {application, storage}` → setzt `traefik_mode: backend` via group_vars. - Service-Gruppen (`nextcloud_servers`, `garage_servers`, …) sind Single-Host-Wrapper, mit denen `playbooks/site.yml` gezielt deploybare Rollen targetet. ## 3. Service-Layout & Variablen-Verortung ```mermaid flowchart TB classDef rp fill:#fee2e2,stroke:#991b1b,color:#000 classDef ap fill:#dcfce7,stroke:#166534,color:#000 classDef st fill:#dbeafe,stroke:#1e40af,color:#000 classDef ext fill:#e9d5ff,stroke:#6b21a8,color:#000 Internet((Internet)) DNS["DNS ns1.digitalboard.ch
RFC2136 TSIG (key: acme_update_key_demo_gymb)
dynamic zone: demo-gymb._acme.digitalboard.ch
CNAME-bridge: _acme-challenge.*.gymb.souveredu.ch"]:::ext BAO["OpenBao
bao.digitalboard.ch
mount: demo-gymburgdorf"]:::ext subgraph RP["reverseproxy — traefik dmz"] TRDMZ["traefik (file provider)
📍 group_vars/traefik_servers/traefik.yml
→ acme, tsig, ssl
📍 host_vars/reverseproxy/traefik.yml
→ traefik_mode: dmz
📍 host_vars/reverseproxy/...
→ traefik_dmz_exposed_services"]:::rp end subgraph APP["application — backend"] TRA["traefik (docker provider)
📍 group_vars/backend_servers
→ traefik_mode: backend"]:::ap NC["nextcloud
📍 host_vars/application/nextcloud.yml
domain, postgres_pw, oidc, s3, ldap"]:::ap OC["opencloud
📍 host_vars/application/opencloud.yml
oidc_issuer, ldap, s3"]:::ap AK["authentik
📍 host_vars/application/authentik.yml
secret_key, postgres, ldap_apps, oidc_apps"]:::ap AKO["authentik_outpost_ldap
📍 host_vars/application/authentik_outpost_ldap.yml
host, token"]:::ap COL["collabora
📍 host_vars/application/collabora.yml
domain, allowed_domains"]:::ap DRW["drawio
📍 host_vars/application/drawio.yml"]:::ap end subgraph ST["storage — backend"] TRS["traefik (docker provider)"]:::st GAR["garage (S3)
📍 host_vars/storage/garage.yml
s3_domain, rpc_secret,
admin_token, s3_keys"]:::st end Internet -->|HTTPS :443| TRDMZ TRDMZ -->|HTTP backend| TRA TRDMZ -->|HTTP backend| TRS TRA --> NC & OC & AK & COL & DRW & AKO TRS --> GAR NC -. S3 .-> GAR OC -. S3 .-> GAR NC -. OIDC .-> AK OC -. OIDC .-> AK NC -. WOPI .-> COL OC -. WOPI .-> COL NC -. LDAP .-> AKO OC -. LDAP .-> AKO AKO -. RPC + token .-> AK TRDMZ -. ACME DNS-01 TSIG .-> DNS TRDMZ -. lookup acme-tsig .-> BAO AK -. lookup secrets .-> BAO NC -. lookup secrets .-> BAO GAR -. lookup secrets .-> BAO ``` ## 4. Deploy-Flow ```mermaid sequenceDiagram participant U as User (make) participant M as Makefile participant A as ansible-playbook participant V as OpenBao participant H as Hosts U->>M: make bao M->>V: bao login (OIDC) V-->>M: VAULT_TOKEN U->>M: make deploy_site_demo_gymburgdorf M->>A: ansible-playbook site.yml -i inventories/demo-gymburgdorf/hosts.yml A->>A: lade group_vars/all → group_vars/traefik_servers → group_vars/backend_servers → host_vars/* A->>V: community.hashi_vault Lookups (acme-tsig, secrets) V-->>A: secret values A->>H: Play "base" → all_servers A->>H: Play "traefik" → traefik_servers (dmz auf reverseproxy, backend auf application/storage) A->>H: Play "garage" → storage A->>H: Play "authentik / nextcloud / collabora / ..." → application ``` ## 5. Variablen-Cheatsheet — wo gehört was hin? | Variable | Wohin in `demo-gymburgdorf/` | Warum | |---|---|---| | `vault_addr`, `vault_mount` | `group_vars/all/vault.yml` ✅ | Vault-Endpoint gilt site-weit | | `docker_registry_mirrors` | `group_vars/all/docker.yml` ✅ | Pulls aus Mirror auf allen Hosts | | `traefik_acme_*`, `traefik_use_ssl`, `traefik_cert_mode` | `group_vars/traefik_servers/traefik.yml` ✅ | Gilt für alle Traefik-Instanzen (dmz + backend) | | `traefik_mode: backend` | `group_vars/backend_servers/traefik.yml` ✅ | Default für app + storage | | `traefik_mode: dmz` | `host_vars/reverseproxy/traefik.yml` ✅ | Host-spezifischer Override | | `traefik_dmz_exposed_services` | **`host_vars/reverseproxy/`** | Liste, welche Backend-Services die DMZ proxyt (nur dort sinnvoll) | | `nextcloud_*`, `authentik_*`, `opencloud_*`, `collabora_*`, `drawio_*` | **`host_vars/application/.yml`** | Service läuft genau auf `application` | | `garage_*` | **`host_vars/storage/garage.yml`** | Service läuft genau auf `storage` | | Secrets (Passwords, Tokens, Keys) | Inline-Variable mit `lookup('community.hashi_vault.hashi_vault', vault_mount + '/data/', url=vault_addr)` | Single source of truth; Pattern wie bei `_acme_tsig` | ## 6. Traefik-Modi (zentral für die Architektur) **`traefik_mode: dmz`** (Public-facing Reverse Proxy auf `reverseproxy`): - Aggregiert Services von Backend-Servern via `traefik_dmz_exposed_services` (Host-Variablen). - Nutzt **file provider** mit `services.yml` für statisches Routing. - Kein Docker-Socket gemountet — keine lokalen Container. - Routet zu `backend_host` auf anderen Maschinen. - Selektive Backend-Auswahl via `traefik_backend_servers_to_proxy`. **`traefik_mode: backend`** (Application/Storage Server): - Mountet Docker-Socket (`/var/run/docker.sock`). - Nutzt **docker provider** für Auto-Discovery lokaler Container. - Services mit Label `traefik.enable=true` werden automatisch exponiert. - Beide Modi unterstützen ACME (RFC2136 DNS Challenge) oder Self-Signed. ## 7. Was im aktuellen `demo-gymburgdorf` noch fehlt Im Vergleich zur `vagrant`-Inventory (Referenz) fehlen für eine vollständige Deployment: - `host_vars/application/main.yml` — Backbone-Vars für den Host (FQDN-Pattern, gemeinsame Defaults). - `host_vars/application/{nextcloud,opencloud,authentik,authentik_outpost_ldap,collabora,drawio}.yml` — die service-spezifischen Konfigurationen. - `host_vars/storage/{main.yml,garage.yml}` — Garage-Cluster-Setup. - `host_vars/reverseproxy/<…>.yml` mit `traefik_dmz_exposed_services` — sonst routet die DMZ nichts. Die `vagrant`-Inventory ist das Template: dieselbe Struktur auf `application`/`storage` mappen, FQDNs auf `*.gymb.souveredu.ch` umstellen, Secrets durch Bao-Lookups ersetzen.