Compare commits

..

3 commits

Author SHA1 Message Date
Simon Bärlocher
ae4eb799bb
docs(reference-ansible): add docs/ tree and document repo, playbooks, Makefile
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.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 21:31:53 +02:00
Simon Bärlocher
b59b2df82a
chore(demo-gymburgdorf): finish ACME, LDAP, DMZ routing for live inventory
- ACME via DNS-01 against internal NS (172.16.9.169) with TCP-only +
  disableANSChecks so the DMZ traefik can issue LE certs without
  reaching public NS IPs.
- Migrate single-domain vars to `*_domains` lists (authentik, nextcloud,
  collabora, garage_s3) so public + *.int.* SANs share one cert and
  server-to-server traffic stays in the LAN.
- Wire `traefik_dmz_exposed_services` per backend host (application,
  storage) with explicit `backend_host` overrides pointing at internal
  FQDNs — DMZ traefik now validates upstream certs against SAN names.
- Nextcloud notify_push setup on internal FQDN to avoid DMZ hairpin;
  collabora WOPI / authentik LDAP outpost wired to *.int.* equivalents.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 23:26:18 +02:00
Simon Bärlocher
103d95740d
chore: wip on demo-gymburgdorf inventory and architecture notes 2026-05-18 15:20:01 +02:00
8 changed files with 24 additions and 83 deletions

2
.gitignore vendored
View file

@ -18,5 +18,3 @@
/collections/ansible_collections/ /collections/ansible_collections/
.vagrant/ .vagrant/
bao bao
playbooks/secrets/backend/homarr_secret_encryption_key

View file

@ -18,33 +18,22 @@ consists of a sequence of plays, each applying one role from
| # | Play / role | `hosts:` | Target in `demo-gymburgdorf`? | | # | Play / role | `hosts:` | Target in `demo-gymburgdorf`? |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| 1 | `digitalboard.core.base` | `all_servers` | ✅ all 4 hosts | | 1 | `digitalboard.core.base` | `all_servers` | ✅ all 4 hosts |
| 2 | `digitalboard.core.traefik` | `traefik_servers_backend` | — no-op (vagrant-only group) | | 2 | `digitalboard.core.traefik` | `traefik_servers` | ✅ all 4 (dmz on `reverseproxy`, otherwise backend) |
| 3 | `digitalboard.core.traefik` | `traefik_servers_dmz` | — no-op (vagrant-only group) | | 3 | `digitalboard.core.httpbin` | `httpbin_servers` | — no-op |
| 4 | `digitalboard.core.traefik` | `traefik_servers:!traefik_servers_dmz:!traefik_servers_backend` | ✅ all 4 (dmz on `reverseproxy`, otherwise backend) | | 4 | `digitalboard.core.389ds` | `ds389_servers` | — no-op |
| 5 | `digitalboard.core.httpbin` | `httpbin_servers` | — no-op | | 5 | `digitalboard.core.keycloak` | `keycloak_servers` | — no-op |
| 6 | `digitalboard.core.389ds` | `ds389_servers` | — no-op | | 6 | `digitalboard.core.garage` | `garage_servers` | ✅ `storage` |
| 7 | `digitalboard.core.keycloak` | `keycloak_servers` | — no-op | | 7 | `digitalboard.core.collabora` | `collabora_servers` | ✅ `application` |
| 8 | `digitalboard.core.garage` | `garage_servers` | ✅ `storage` | | 8 | `digitalboard.core.authentik` | `authentik_servers` | ✅ `application` |
| 9 | `digitalboard.core.collabora` | `collabora_servers` | ✅ `application` | | 9 | `digitalboard.core.authentik_outpost_ldap` | `authentik_outpost_ldap_servers` | ✅ `application` |
| 10 | `digitalboard.core.authentik` | `authentik_servers` | ✅ `application` | | 10 | `digitalboard.core.nextcloud` | `nextcloud_servers` | ✅ `application` |
| 11 | `digitalboard.core.authentik_outpost_ldap` | `authentik_outpost_ldap_servers` | ✅ `application` | | 11 | `digitalboard.core.drawio` | `drawio_servers` | ✅ `application` |
| 12 | `digitalboard.core.nextcloud` | `nextcloud_servers` | ✅ `application` | | 12 | `digitalboard.core.send` | `send_servers` | ✅ `application` |
| 13 | `digitalboard.core.drawio` | `drawio_servers` | ✅ `application` | | 13 | `digitalboard.core.opnform` | `opnform_servers` | ✅ `application` |
| 14 | `digitalboard.core.send` | `send_servers` | ✅ `application` | | 14 | `digitalboard.core.homarr` | `homarr_servers` | ✅ `application` |
| 15 | `digitalboard.core.opnform` | `opnform_servers` | ✅ `application` | | 15 | `digitalboard.core.bookstack` | `bookstack_servers` | ✅ `application` |
| 16 | `digitalboard.core.homarr` | `homarr_servers` | ✅ `application` | | 16 | `digitalboard.core.opencloud` | `opencloud_servers` | — no-op (no group) |
| 17 | `digitalboard.core.bookstack` | `bookstack_servers` | ✅ `application` |
| 18 | `digitalboard.core.opencloud` | `opencloud_servers` | — no-op (no group) |
> **Three traefik plays, two topologies.** `vagrant` splits the reverse
> proxy into `traefik_servers_dmz` + `traefik_servers_backend` (plays 2
> and 3). The demo inventories (e.g. `demo-gymburgdorf`) instead group
> all hosts under `traefik_servers` and select dmz/backend per host via
> `traefik_mode`; play 4's `:!…` intersection targets exactly those
> hosts and stays a no-op for the vagrant split. Each topology thus
> triggers only the traefik play(s) that fit it — no host runs traefik
> twice.
>
> Which plays take effect for a tenant is controlled **solely through > Which plays take effect for a tenant is controlled **solely through
> group membership** in `hosts.yml`. A service becomes active as soon as > group membership** in `hosts.yml`. A service becomes active as soon as
> its `<service>_servers` group contains a host and a matching > its `<service>_servers` group contains a host and a matching

View file

@ -1,11 +0,0 @@
homarr_domain: "home.local.test"
homarr_secret_dir: "{{ playbook_dir }}/secrets/{{ inventory_hostname }}"
homarr_secret_file: "homarr_secret_encryption_key"
homarr_secret_length: 64
homarr_secret_encryption_key: >-
{{ lookup('ansible.builtin.password',
homarr_secret_dir ~ '/' ~ homarr_secret_file,
length=homarr_secret_length,
chars='hexdigits') }}

View file

@ -35,7 +35,6 @@ nextcloud_extra_networks:
nextcloud_extra_hosts: nextcloud_extra_hosts:
- "storage.local.test:192.168.56.11" - "storage.local.test:192.168.56.11"
- "office.local.test:192.168.56.11"
- "keycloak.local.test:192.168.56.11" - "keycloak.local.test:192.168.56.11"
- "authentik.local.test:192.168.56.11" - "authentik.local.test:192.168.56.11"
# - "389ds:192.168.56.11" # only needed when using 389ds LDAP directly # - "389ds:192.168.56.11" # only needed when using 389ds LDAP directly

View file

@ -1,13 +0,0 @@
opnform_domain: "forms.local.test"
opnform_secret_dir: "{{ playbook_dir }}/secrets/{{ inventory_hostname }}"
opnform_secret_file: "opnform_secret_encryption_key"
opnform_secret_length: 64
opnform_admin_email: "admin@digitalboard.ch"
opnform_admin_password: "ChangeMe123!"
opnform_secret_encryption_key: >-
{{ lookup('ansible.builtin.password',
opnform_secret_dir ~ '/' ~ opnform_secret_file,
length=opnform_secret_length,
chars='hexdigits') }}

View file

@ -16,7 +16,7 @@ traefik_dmz_exposed_services:
domain: nextcloud.local.test domain: nextcloud.local.test
port: 443 port: 443
protocol: https protocol: https
- name: nextcloud-collabora - name: collabora
domain: office.local.test domain: office.local.test
port: 443 port: 443
protocol: https protocol: https
@ -24,12 +24,12 @@ traefik_dmz_exposed_services:
domain: authentik.local.test domain: authentik.local.test
port: 443 port: 443
protocol: https protocol: https
- name: homarr - name: opencloud
domain: home.local.test domain: opencloud.local.test
port: 443 port: 443
protocol: https protocol: https
- name: opnform - name: drawio
domain: forms.local.test domain: drawio.local.test
port: 443 port: 443
protocol: https protocol: https
# Example: Add more services as you deploy them # Example: Add more services as you deploy them

View file

@ -45,11 +45,11 @@ all:
backend: backend:
backend2: backend2:
ds389_servers: keycloak_servers:
hosts: hosts:
backend: backend:
keycloak_servers: ds389_servers:
hosts: hosts:
backend: backend:
@ -69,10 +69,6 @@ all:
hosts: hosts:
backend: backend:
homarr_servers:
hosts:
backend:
collabora_servers: collabora_servers:
hosts: hosts:
backend: backend:
@ -85,6 +81,6 @@ all:
hosts: hosts:
backend: backend:
opnform_servers: openforms_servers:
hosts: hosts:
backend: backend:

View file

@ -5,25 +5,8 @@
roles: roles:
- digitalboard.core.base - digitalboard.core.base
- name: Configure reverse proxy on application servers
hosts: traefik_servers_backend
become: yes
roles:
- digitalboard.core.traefik
- name: Configure reverse proxy on DMZ servers
hosts: traefik_servers_dmz
become: yes
roles:
- digitalboard.core.traefik
# Inventories without the _dmz/_backend split (e.g. demo-gymburgdorf,
# where traefik_servers groups all_servers and dmz/backend is selected
# per host via traefik_mode). The :!… intersection keeps this a no-op
# for the vagrant topology, where every traefik_servers host is already
# covered by the two plays above.
- name: Configure reverse proxies - name: Configure reverse proxies
hosts: traefik_servers:!traefik_servers_dmz:!traefik_servers_backend hosts: traefik_servers
become: yes become: yes
roles: roles:
- digitalboard.core.traefik - digitalboard.core.traefik