diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..807f408 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,207 @@ + +# 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. diff --git a/Makefile b/Makefile index 6cc2944..67b2a75 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,7 @@ export BAO_ADDR=https://bao.digitalboard.ch +# macOS fork-safety: Objective-C runtime is not fork-safe; Ansible forks +# per host. Without this, hashi_vault lookups crash workers. +export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES install: ansible-galaxy collection install -r requirements.yml -p collections @@ -17,7 +20,7 @@ ping_demo: deploy_site_demo_gymburgdorf: echo "deploying demo site gymburgdorf" - ansible-playbook playbooks/site.yml -i inventories/demo-gymburgdorf/hosts.yml + ansible-playbook playbooks/site.yml -i inventories/demo-gymburgdorf/hosts.yml --diff deploy_site_demo_mbazürich: echo "deploying demo site mbazürich" @@ -30,4 +33,4 @@ deploy_site_demo_phbern: deploy_site_demo: make deploy_site_demo_gymburgdorf make deploy_site_demo_mbazürich - make deploy_site_demo_phbern \ No newline at end of file + make deploy_site_demo_phbern diff --git a/inventories/demo-gymburgdorf/group_vars/all/ansible.yml b/inventories/demo-gymburgdorf/group_vars/all/ansible.yml new file mode 100644 index 0000000..e425179 --- /dev/null +++ b/inventories/demo-gymburgdorf/group_vars/all/ansible.yml @@ -0,0 +1,2 @@ +--- +ansible_python_interpreter: /usr/bin/python3 diff --git a/inventories/demo-gymburgdorf/group_vars/traefik_servers/traefik.yml b/inventories/demo-gymburgdorf/group_vars/traefik_servers/traefik.yml index a0f587e..c42dc79 100644 --- a/inventories/demo-gymburgdorf/group_vars/traefik_servers/traefik.yml +++ b/inventories/demo-gymburgdorf/group_vars/traefik_servers/traefik.yml @@ -5,7 +5,7 @@ traefik_cert_mode: "acme" traefik_log_level: DEBUG traefik_network: proxy -traefik_acme_dns_zone: "gymb._acme.digitalboard.ch" +traefik_acme_dns_zone: "demo-gymb._acme.digitalboard.ch" traefik_acme_dns_nameserver: "{{ _acme_tsig.server }}" traefik_acme_tsig_algorithm: "hmac-sha256" traefik_acme_tsig_key: "{{ _acme_tsig.tsig_key }}" diff --git a/inventories/demo-gymburgdorf/host_vars/application/authentik.yml b/inventories/demo-gymburgdorf/host_vars/application/authentik.yml new file mode 100644 index 0000000..aba8775 --- /dev/null +++ b/inventories/demo-gymburgdorf/host_vars/application/authentik.yml @@ -0,0 +1,53 @@ +--- +# Bao secret expected at /data/authentik with keys: +# secret_key, postgres_password, admin_password, +# ldap_outpost_token, +# nextcloud_oidc_secret +_authentik: "{{ lookup('community.hashi_vault.hashi_vault', vault_mount + '/data/authentik', url=vault_addr) }}" + +authentik_domain: "auth.gymb.souveredu.ch" +authentik_secret_key: "{{ _authentik.secret_key }}" +authentik_postgres_password: "{{ _authentik.postgres_password }}" + +# LDAP outpost (provider for nextcloud) +authentik_ldap_apps: + - slug: ldap + name: LDAP + base_dn: "dc=gymb,dc=souveredu,dc=ch" + search_group: admins + +authentik_ldap_outpost: + name: "ldap-outpost" + token: "{{ _authentik.ldap_outpost_token }}" + config: + authentik_host: "https://auth.gymb.souveredu.ch/" + log_level: "info" + +# OIDC clients +authentik_oidc_apps: + - slug: nextcloud + name: Nextcloud + client_id: nextcloud + client_secret: "{{ _authentik.nextcloud_oidc_secret }}" + redirect_uris: + - url: "https://cloud.gymb.souveredu.ch/apps/user_oidc/code" + matching_mode: strict + signing_key_name: "authentik Self-signed Certificate" + flows: + authorization_slug: default-provider-authorization-implicit-consent + invalidation_slug: default-provider-invalidation-flow + scopes: [openid, email, profile, offline_access] + +authentik_groups: + - name: admins + - name: users + +authentik_local_users: + - username: akadmin + name: "Authentik Admin" + email: "admin@gymb.souveredu.ch" + password: "{{ _authentik.admin_password }}" + is_active: true + groups: + - authentik Admins + - admins diff --git a/inventories/demo-gymburgdorf/host_vars/application/authentik_outpost_ldap.yml b/inventories/demo-gymburgdorf/host_vars/application/authentik_outpost_ldap.yml new file mode 100644 index 0000000..c02b660 --- /dev/null +++ b/inventories/demo-gymburgdorf/host_vars/application/authentik_outpost_ldap.yml @@ -0,0 +1,7 @@ +--- +# Same token as authentik_ldap_outpost.token above — outpost uses it to +# authenticate against the authentik server it talks to. +_authentik: "{{ lookup('community.hashi_vault.hashi_vault', vault_mount + '/data/authentik', url=vault_addr) }}" + +authentik_outpost_ldap_host: "https://auth.gymb.souveredu.ch" +authentik_outpost_ldap_token: "{{ _authentik.ldap_outpost_token }}" diff --git a/inventories/demo-gymburgdorf/host_vars/application/collabora.yml b/inventories/demo-gymburgdorf/host_vars/application/collabora.yml new file mode 100644 index 0000000..b02760c --- /dev/null +++ b/inventories/demo-gymburgdorf/host_vars/application/collabora.yml @@ -0,0 +1,8 @@ +--- +collabora_domain: "office.gymb.souveredu.ch" + +collabora_allowed_domains: + - "cloud.gymb.souveredu.ch" + +collabora_frame_ancestors: + - "cloud.gymb.souveredu.ch" diff --git a/inventories/demo-gymburgdorf/host_vars/application/drawio.yml b/inventories/demo-gymburgdorf/host_vars/application/drawio.yml new file mode 100644 index 0000000..beef6a5 --- /dev/null +++ b/inventories/demo-gymburgdorf/host_vars/application/drawio.yml @@ -0,0 +1,2 @@ +--- +drawio_domain: "draw.gymb.souveredu.ch" diff --git a/inventories/demo-gymburgdorf/host_vars/application/main.yml b/inventories/demo-gymburgdorf/host_vars/application/main.yml new file mode 100644 index 0000000..49248a6 --- /dev/null +++ b/inventories/demo-gymburgdorf/host_vars/application/main.yml @@ -0,0 +1,3 @@ +--- +# application host runs: authentik, authentik-ldap-outpost, +# nextcloud, collabora, drawio diff --git a/inventories/demo-gymburgdorf/host_vars/application/nextcloud.yml b/inventories/demo-gymburgdorf/host_vars/application/nextcloud.yml new file mode 100644 index 0000000..a1719f4 --- /dev/null +++ b/inventories/demo-gymburgdorf/host_vars/application/nextcloud.yml @@ -0,0 +1,90 @@ +--- +# Bao secret /data/nextcloud expected to contain: +# postgres_password, admin_password +_nextcloud: "{{ lookup('community.hashi_vault.hashi_vault', vault_mount + '/data/nextcloud', url=vault_addr) }}" +_authentik: "{{ lookup('community.hashi_vault.hashi_vault', vault_mount + '/data/authentik', url=vault_addr) }}" + +nextcloud_domain: "cloud.gymb.souveredu.ch" +nextcloud_postgres_password: "{{ _nextcloud.postgres_password }}" +nextcloud_admin_user: admin +nextcloud_admin_password: "{{ _nextcloud.admin_password }}" + +nextcloud_enable_notify_push: true + +# Collabora integration +nextcloud_enable_collabora: true +nextcloud_collabora_domain: "office.gymb.souveredu.ch" + +# Draw.io integration +nextcloud_enable_drawio: true +nextcloud_drawio_url: "https://draw.gymb.souveredu.ch" + +nextcloud_apps_to_install: + - groupfolders + - richdocuments + - spreed + - user_ldap + - user_oidc + - whiteboard + - drawio + - files_lock + - notify_push + +# S3 primary storage via Garage +nextcloud_use_s3_storage: true +nextcloud_s3_key: "{{ lookup('digitalboard.core.garage_credentials', 'nextcloud', host='storage')['key_id'] }}" +nextcloud_s3_secret: "{{ lookup('digitalboard.core.garage_credentials', 'nextcloud', host='storage')['secret_key'] }}" +nextcloud_s3_bucket: "nextcloud" +nextcloud_s3_host: "{{ hostvars['storage']['garage_s3_domain'] }}" +nextcloud_s3_port: 443 +nextcloud_s3_ssl: true +nextcloud_s3_usepath_style: true + +# Share the LDAP docker network with the authentik LDAP outpost +nextcloud_extra_networks: + - ldap + +# LDAP backend (Authentik LDAP outpost) +nextcloud_ldap_enabled: true +nextcloud_ldap_config: + ldapHost: "ldap://authentik-outpost-ldap-ldap-1" + ldapPort: "3389" + ldapAgentName: "cn=akadmin,ou=users,dc=gymb,dc=souveredu,dc=ch" + ldapAgentPassword: "{{ _authentik.admin_password }}" + ldapBase: "dc=gymb,dc=souveredu,dc=ch" + ldapBaseUsers: "ou=users,dc=gymb,dc=souveredu,dc=ch" + ldapTLS: "0" + turnOffCertCheck: "1" + ldapUserFilter: "(&(objectClass=user)(cn=*))" + ldapUserFilterObjectclass: "user" + ldapLoginFilter: "(&(objectClass=user)(cn=%uid))" + ldapLoginFilterUsername: "1" + ldapUserDisplayName: "cn" + ldapEmailAttribute: "mail" + ldapExpertUsernameAttr: "cn" + ldapExpertUUIDUserAttr: "uid" + ldapExpertUUIDGroupAttr: "uid" + ldapBaseGroups: "ou=groups,dc=gymb,dc=souveredu,dc=ch" + ldapGroupFilter: "(&(objectClass=group))" + ldapGroupFilterObjectclass: "group" + ldapGroupDisplayName: "cn" + ldapGroupMemberAssocAttr: "member" + ldapAdminGroup: "admins" + ldapCacheTTL: "600" + ldapPagingSize: "500" + ldapExperiencedAdmin: "1" + ldapConfigurationActive: "1" + +# OIDC providers for login (Authentik) +nextcloud_oidc_providers: + - identifier: authentik + display_name: "Login with Authentik" + client_id: nextcloud + client_secret: "{{ _authentik.nextcloud_oidc_secret }}" + discovery_url: "https://auth.gymb.souveredu.ch/application/o/nextcloud/.well-known/openid-configuration" + scope: "openid email profile" + unique_uid: true + mapping: + uid: preferred_username + display_name: name + email: email diff --git a/inventories/demo-gymburgdorf/host_vars/reverseproxy/traefik.yml b/inventories/demo-gymburgdorf/host_vars/reverseproxy/traefik.yml index 35f8874..c43e6be 100644 --- a/inventories/demo-gymburgdorf/host_vars/reverseproxy/traefik.yml +++ b/inventories/demo-gymburgdorf/host_vars/reverseproxy/traefik.yml @@ -1 +1,28 @@ -traefik_mode: dmz \ No newline at end of file +--- +traefik_mode: dmz + +traefik_dmz_exposed_services: + - name: authentik + domain: auth.gymb.souveredu.ch + port: 443 + protocol: https + - name: nextcloud + domain: cloud.gymb.souveredu.ch + port: 443 + protocol: https + - name: collabora + domain: office.gymb.souveredu.ch + port: 443 + protocol: https + - name: drawio + domain: draw.gymb.souveredu.ch + port: 443 + protocol: https + - name: garage-webui + domain: console.s3.gymb.souveredu.ch + port: 443 + protocol: https + - name: garage-s3 + domain: s3.gymb.souveredu.ch + port: 443 + protocol: https diff --git a/inventories/demo-gymburgdorf/host_vars/storage/garage.yml b/inventories/demo-gymburgdorf/host_vars/storage/garage.yml new file mode 100644 index 0000000..bc392c9 --- /dev/null +++ b/inventories/demo-gymburgdorf/host_vars/storage/garage.yml @@ -0,0 +1,27 @@ +--- +# Bao secret /data/garage expected to contain: +# rpc_secret, admin_token, metrics_token, webui_password +_garage: "{{ lookup('community.hashi_vault.hashi_vault', vault_mount + '/data/garage', url=vault_addr) }}" + +garage_s3_domain: "s3.gymb.souveredu.ch" +garage_webui_domain: "console.s3.gymb.souveredu.ch" +garage_use_ssl: true +garage_webui_enabled: true +garage_webui_username: "admin" +garage_webui_password: "{{ _garage.webui_password }}" + +garage_rpc_secret: "{{ _garage.rpc_secret }}" +garage_admin_token: "{{ _garage.admin_token }}" +garage_metrics_token: "{{ _garage.metrics_token }}" + +# Initial cluster bootstrap (single-node) +garage_bootstrap_enabled: true +garage_bootstrap_zone: "burgdorf1" +garage_bootstrap_capacity: "100G" + +# Buckets and keys consumed by nextcloud +garage_s3_keys: + - name: nextcloud + buckets: + - name: nextcloud + permissions: ["read", "write"] diff --git a/inventories/demo-gymburgdorf/host_vars/storage/main.yml b/inventories/demo-gymburgdorf/host_vars/storage/main.yml new file mode 100644 index 0000000..75e487d --- /dev/null +++ b/inventories/demo-gymburgdorf/host_vars/storage/main.yml @@ -0,0 +1,2 @@ +--- +# storage host runs: garage (S3 + WebUI) diff --git a/inventories/demo-gymburgdorf/hosts.yml b/inventories/demo-gymburgdorf/hosts.yml index 648b2cf..220784b 100644 --- a/inventories/demo-gymburgdorf/hosts.yml +++ b/inventories/demo-gymburgdorf/hosts.yml @@ -32,10 +32,6 @@ all: hosts: application: - opencloud_servers: - hosts: - application: - collabora_servers: hosts: application: @@ -45,5 +41,9 @@ all: application: authentik_servers: + hosts: + application: + + authentik_outpost_ldap_servers: hosts: application: \ No newline at end of file diff --git a/playbooks/site.yml b/playbooks/site.yml index d46b5b7..ba9f7ca 100644 --- a/playbooks/site.yml +++ b/playbooks/site.yml @@ -71,6 +71,18 @@ roles: - digitalboard.core.drawio +- name: Deploy send service + hosts: send_servers + become: yes + roles: + - digitalboard.core.send + +- name: Deploy openforms service + hosts: openforms_servers + become: yes + roles: + - digitalboard.core.openforms + - name: Deploy opencloud service hosts: opencloud_servers become: yes