9.6 KiB
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)
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["<b>role defaults/main.yml</b><br/>(niedrigste Precedence)<br/>~180 Variablen über 12 Rollen<br/>z.B. traefik_use_ssl: false<br/>keycloak_admin_password: changeme"]:::rolelayer
GA["<b>group_vars/all/</b><br/>docker.yml → docker_registry_mirrors<br/>vault.yml → vault_addr, vault_mount"]:::grouplayer
GT["<b>group_vars/traefik_servers/</b><br/>traefik.yml<br/>traefik_use_ssl, traefik_cert_mode: acme<br/>traefik_acme_dns_zone<br/>traefik_acme_tsig_* (Vault-Lookup!)"]:::grouplayer
GB["<b>group_vars/backend_servers/</b><br/>traefik.yml → traefik_mode: backend"]:::grouplayer
HR["<b>host_vars/reverseproxy/</b><br/>traefik.yml → traefik_mode: dmz"]:::hostlayer
HA["<b>host_vars/application/</b> (fehlt aktuell!)<br/>FQDNs, OIDC-Clients, DB-Passwords<br/>nextcloud_domain, authentik_domain, ..."]:::hostlayer
HS["<b>host_vars/storage/</b> (fehlt aktuell!)<br/>garage_s3_domain, garage_*_token<br/>traefik_dmz_exposed_services (für DMZ)"]:::hostlayer
V["<b>HashiCorp Vault / OpenBao</b><br/>bao.digitalboard.ch<br/>mount: demo-gymburgdorf<br/>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
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["<b>reverseproxy</b><br/>172.16.9.111<br/>traefik_mode: dmz"]:::dmz
TURN["<b>turn</b><br/>172.16.9.112<br/>(STUN/TURN)"]:::turn
end
subgraph BE["Backend-Segment 172.16.19.0/24<br/>(group: backend_servers)"]
APP["<b>application</b><br/>172.16.19.101<br/>traefik_mode: backend<br/>+ nextcloud, opencloud,<br/>collabora, drawio,<br/>authentik, authentik_outpost_ldap"]:::app
ST["<b>storage</b><br/>172.16.19.102<br/>traefik_mode: backend<br/>+ 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ürreverseproxy, Backend-Modus fürapplication/storage).backend_servers = {application, storage}→ setzttraefik_mode: backendvia group_vars.- Service-Gruppen (
nextcloud_servers,garage_servers, …) sind Single-Host-Wrapper, mit denenplaybooks/site.ymlgezielt deploybare Rollen targetet.
3. Service-Layout & Variablen-Verortung
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<br/>RFC2136 TSIG (key: acme_update_key_demo_gymb)<br/>dynamic zone: demo-gymb._acme.digitalboard.ch<br/>CNAME-bridge: _acme-challenge.*.gymb.souveredu.ch"]:::ext
BAO["OpenBao<br/>bao.digitalboard.ch<br/>mount: demo-gymburgdorf"]:::ext
subgraph RP["<b>reverseproxy</b> — traefik dmz"]
TRDMZ["traefik (file provider)<br/>📍 group_vars/traefik_servers/traefik.yml<br/> → acme, tsig, ssl<br/>📍 host_vars/reverseproxy/traefik.yml<br/> → traefik_mode: dmz<br/>📍 host_vars/reverseproxy/...<br/> → traefik_dmz_exposed_services"]:::rp
end
subgraph APP["<b>application</b> — backend"]
TRA["traefik (docker provider)<br/>📍 group_vars/backend_servers<br/> → traefik_mode: backend"]:::ap
NC["nextcloud<br/>📍 host_vars/application/nextcloud.yml<br/> domain, postgres_pw, oidc, s3, ldap"]:::ap
OC["opencloud<br/>📍 host_vars/application/opencloud.yml<br/> oidc_issuer, ldap, s3"]:::ap
AK["authentik<br/>📍 host_vars/application/authentik.yml<br/> secret_key, postgres, ldap_apps, oidc_apps"]:::ap
AKO["authentik_outpost_ldap<br/>📍 host_vars/application/authentik_outpost_ldap.yml<br/> host, token"]:::ap
COL["collabora<br/>📍 host_vars/application/collabora.yml<br/> domain, allowed_domains"]:::ap
DRW["drawio<br/>📍 host_vars/application/drawio.yml"]:::ap
end
subgraph ST["<b>storage</b> — backend"]
TRS["traefik (docker provider)"]:::st
GAR["garage (S3)<br/>📍 host_vars/storage/garage.yml<br/> s3_domain, rpc_secret,<br/> 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
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/<service>.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/<path>', 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.ymlfür statisches Routing. - Kein Docker-Socket gemountet — keine lokalen Container.
- Routet zu
backend_hostauf 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=truewerden 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/<…>.ymlmittraefik_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.