Repository navigation
add tenant: zuiddrecht-prod - #145
rubenvdlinde wants to merge 19 commits into
Conversation
…enant Optioneel veld tenant.extraHostnames. De ApplicationSet zet de extra hosts in nextcloud.trustedDomains en rendert via extraManifests een tweede Ingress nextcloud-extra-hosts, met één TLS-blok (en dus één HTTP-01-Certificate) per host. Chart 8.9.0 zet in zijn eigen Ingress alleen nextcloud.host als rule. Annotaties, ingressClassName en poort komen via de tpl van de chart uit dezelfde values als de hoofd-Ingress. Bestaande tenants renderen byte-identiek: alle 89 tenantbestanden op main en op deze branch gerenderd en vergeleken, values en manifests gelijk. validate-values.sh controleert het veld; fixtures in tests/cases/tenant-extra-hostnames-*. Docs: ADDING-TENANT, CHECKS-AND-BALANCES, GATEWAY-API. Changelog-fragment in changelog.d/.
#138 (comment) validate_extra_hostnames vergeleek alleen met een expliciete tenant.hostname. Nieuwe helper primary_host() berekent de primaire host zoals de ApplicationSet (tenant.hostname, anders <org>.commonground.nu / <org>.<omgeving>.commonground.nu, inclusief het ontbreken van 'demo' als suffix in het template). Gecontroleerd tegen de gerenderde nextcloud.host van alle 89 tenants: gelijk. Fixture tenant-extra-hostnames-berekende-primaire-host (zonder hostname) faalt nu met 'bevat de primaire host'; tegen de PR-head-validator slaagde hij. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…laimen #138 (comment) validate-values.sh bouwt nu per run een host-register over alle tenantbestanden in values/tenants/ (primaire host zoals de ApplicationSet hem bepaalt, tenant.extraHostnames, tenant.frontend.host, tenant.frontend.extraHosts) en weigert elke host die twee tenants claimen (validate_host_claims). Een bestand op de commandoregel vervangt het tenantbestand met dezelfde tenant.name, dus ook `validate-values.sh <één bestand>` vergelijkt met de hele vloot en een gewijzigde kopie botst niet met zichzelf. De check werkt in beide richtingen: een nieuwe tenant B faalt ook als een bestaande A zijn host al als extra host heeft (getest met een tijdelijk tenantbestand). Een extra host onder commonground.nu moet volgens de naamconventie van validate_hostname_convention bij de eigen tenant horen (convention_hosts: <org>.commonground.nu / <org>.migrate.commonground.nu voor prod, <org>.<suffix>.commonground.nu anders). Geen nieuwe opt-in. Class sweep: binnen één tenant mag een extra host ook niet de host van de eigen WOO-frontend zijn (zelfde botsing, andere Ingress). Checklijsten bijgewerkt in de commentaarkop van validate_extra_hostnames, docs/CHECKS-AND-BALANCES.md en changelog.d/tenant-extra-hostnames.md; run-tests.sh noemt dat de botsingsfixtures op tenant-dinkelland-prod leunen (de runner kent alleen enkelvoudige cases; de validator leest values/tenants/ zelf, dus de runner hoefde niet te veranderen). Fixtures: andere-tenant (primaire host van dinkelland-prod), andere-frontend (frontend.host van dinkelland-prod), commonground-vreemd, commonground-eigen (PASS), eigen-frontend. De vier foute cases slagen tegen de PR-head-validator. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#138 (comment) validate_extra_hostnames weigert nu een afgeleide TLS-secretnaam die al bij een andere extra host hoort (punten worden streepjes, dus a-b.nl en a.b.nl gaven hetzelfde secret). Een dubbele host meldt alleen 'dubbel' en slaat de overige checks over, zodat hij niet ook als secretbotsing telt. Fixture tenant-extra-hostnames-zelfde-secret; slaagde tegen de PR-head-validator. Class sweep: de checklijst in docs/CHECKS-AND-BALANCES.md, changelog.d/tenant-extra-hostnames.md en de commentaarkop noemen nu een unieke secretnaam. De secretnaam van de hoofd-Ingress (nextcloud-<tenant>-tls) kan niet met een afgeleide naam botsen (die heeft altijd een host-deel). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…bels >63 #138 (comment) Nieuwe helper is_valid_hostname: RFC 1123-labels zoals voorheen, plus minstens één punt, elk label max 63 en het geheel max 253 tekens. validate_extra_hostnames gebruikt hem; de melding noemt de regels. Class sweep: validate_hostname (tenant.hostname) gebruikte dezelfde regex en had hetzelfde gat; ook die gebruikt nu is_valid_hostname. De 89 tenants blijven groen. Fixtures: tenant-extra-hostnames-localhost, -getal (123), -label-te-lang (label van 64 tekens) en tenant-hostname-zonder-punt; alle vier slaagden tegen de PR-head-validator. Een host > 253 werd voor extraHostnames al via de secretnaamlengte gevangen, dus daar geen aparte fixture. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ss.path #138 (comment) De extra Ingress nextcloud-extra-hosts volgt nu templates/ingress.yaml van chart 8.9.0: hij staat achter `if .Values.ingress.enabled` en neemt ingress.path en ingress.pathType via de tpl over in plaats van vast `/` en `Prefix`. Class sweep (zelfde afwijking van de chart-template): annotations en ingressClassName staan nu ook achter `with`, zoals in de chart, zodat een lege waarde geen `annotations: {}` of lege `ingressClassName:` oplevert. Docs-tabel in docs/ADDING-TENANT.md en changelog.d/tenant-extra-hostnames.md bijgewerkt. Gerenderd met helm (dinkelland-prod + extraHostnames, chart 8.9.0): met de standaardwaarden byte-identiek aan de PR-head; ingress.enabled=false geeft geen enkele Ingress meer (PR-head rendert dan nog nextcloud-extra-hosts); ingress.path=/x en pathType=ImplementationSpecific komen in beide Ingresses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#138 (comment) docs/ADDING-TENANT.md: een host uit extraHostnames halen prunet de Ingress, maar de host blijft in config.php tot `occ config:system:delete trusted_domains <n>`. Eerst `occ config:system:get trusted_domains` draaien om de juiste <n> te vinden, want `set` op een bezette index overschrijft die entry. Class sweep: dezelfde beperking staat in changelog.d/tenant-extra-hostnames.md en noemt nu ook het verwijderen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#138 (comment) Sinds f7 volgt nextcloud-extra-hosts ingress.enabled, net als de chart. Met ingress.enabled: false (de Gateway-cutover) hadden de extra hosts dan geen enkele route, want charts/tenant-httproute neemt alleen de primaire host. validate_extra_hostnames weigert nu extraHostnames samen met een effectieve ingress.enabled die niet true is. effective_ingress_enabled leest de waarde in dezelfde valueFiles-volgorde als de ApplicationSet (common, env, db, canary-overrides als tenant.canary, tenantbestand; de inline values zetten hem niet). Alle 89 tenants: true, gelijk aan de renders (89 met Ingress). Fixture tenant-extra-hostnames-zonder-ingress; met de check weggehaald slaagt hij (mutatie gecontroleerd). docs/GATEWAY-API.md (extraHostnames-alinea en de cutover-alinea) en docs/ADDING-TENANT.md zeggen het nu. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…keer bouwen #138 (comment) Dubbele tenant.name: build_host_claims hield één bestand per naam aan, dus een tweede tenantbestand met dezelfde naam viel stil uit de botsingscheck. dump_host_claims (het register van values/tenants/) geeft nu een error voor elk tweede bestand daar met een bestaande naam. Alleen een bestand BUITEN values/tenants/ (fixture, gewijzigde kopie) vervangt de tenant met dezelfde naam; een bestand binnen values/tenants/ wordt nooit als vervanger gebruikt, dus de omweg bestaat niet meer. Twee bestanden buiten de map met dezelfde naam zijn ook een error. Getest met een tijdelijke kopie in values/tenants/ (error, daarna verwijderd) en met fixture tenant-dubbele-naam, die een eigen vloot heeft in tenant-dubbele-naam.fleet/ (run-tests.sh zet daarvoor VALIDATE_TENANT_DIR). Met de dup-check weggehaald wordt die fixture rood. Looptijd: run-tests.sh bouwde per case het register over 89 bestanden opnieuw (~2,8 s per case). De validator accepteert nu VALIDATE_HOST_CLAIMS_FILE (geschreven met `validate-values.sh --dump-host-claims`); run-tests.sh bouwt het één keer. Ontbreekt het bestand, dan bouwt de validator het register zelf. Eén fixture: 2,8 s -> 0,3 s; hele suite (34 cases): ~14 s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#138 (comment) is_valid_hostname accepteerde 81.24.6.82; Kubernetes neemt geen IP-adres als Ingress-host. Een naam waarvan het laatste label alleen cijfers is, wordt nu geweigerd. Geldt via de helper voor zowel tenant.extraHostnames als tenant.hostname; de meldingen noemen het. Fixture tenant-extra-hostnames-ip-adres; tegen de validator van de vorige commit slaagt hij (mutatie gecontroleerd). De 89 tenants blijven groen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ixtures noemen #138 (comment) De fixtures tenant-extra-hostnames-andere-tenant en -andere-frontend toetsen een botsing met tenant-dinkelland-prod. Een regel bovenin zegt nu dat ze breken als de hosts van dinkelland veranderen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#138 (comment) De checklijsten noemen nu ook de checks uit de pre-push-ronde: extraHostnames niet samen met ingress.enabled: false, geen IP-adres als host (ook voor tenant.hostname), en geen dubbele tenant.name over tenantbestanden heen. Bijgewerkt in docs/CHECKS-AND-BALANCES.md, changelog.d/tenant-extra-hostnames.md en de commentaarkop van validate_extra_hostnames (git grep: geen andere lijsten). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(review): #138 review findings, round 1
…includeSubDomains Een extra host met twee labels (gemeente.nl) wordt geweigerd tenzij de tenant tenant.extraHostnamesAllowApex: true zet. HSTS met includeSubDomains op een apex dwingt HTTPS af op elk subdomein van de klant, en dat is in een browser niet terug te draaien. Apex-hosts krijgen een eigen Ingress nextcloud-extra-hosts-apex met nginx.ingress.kubernetes.io/hsts-include-subdomains: "false" over de annotaties heen (merge in een nieuwe dict, de gedeelde values blijven ongemoeid). De hoofd-Ingress en nextcloud-extra-hosts houden hun waarde. Fixtures: apex zonder opt-in faalt, met opt-in slaagt, opt-in false en opt-in als tekst falen. Nieuwe render-check tests/render-extra-hosts.sh (in verify.sh) rendert de fixtures via de ApplicationSet en chart 8.9.0 en controleert de Ingresses. De fixture "geldig" heeft geen kale apex meer. Alle 89 tenants renderen byte-identiek aan a17181e (values en manifests).
…t's Encrypt ADDING-TENANT gebruikt www.example.nl als voorbeeld en noemt het gevolg van includeSubDomains op een apex, de opt-in en dat de zone-eigenaar dat moet accepteren. Ook staat er dat ingress-nginx geen HSTS-annotatie per Ingress leest (HSTS komt uit de controller-ConfigMap), dus wat live wel zou helpen. Extra hosts krijgen alleen Let's Encrypt: hun Ingresses erven cert-manager.io/cluster-issuer. Een eigen of betaald cert per extra host kan nog niet; tenant.frontend.tls is het bestaande patroon.
Demogemeente Zuiddrecht op cloud.zuiddrecht.nl, met zuiddrecht.nl, www.zuiddrecht.nl en mijn.zuiddrecht.nl als extra hosts (vereist #138). 16 Conduction-apps gepind op de unstable releases van 14 oktober, registration uit de app store, overwrite.cli.url per tenant en een startupProbe van ongeveer 15 minuten.
De generale repetitie van 15 oktober deed 22 minuten over de eerste start. startupProbe.failureThreshold gaat van 84 naar 180 (~30 min). Veertien pins naar de set die de repetitie draaide; integriq naar 0.4.12-unstable.20261015175726, de release met de fix voor integriq#2433 (zonder vendor/symfony/console, dat elk occ-commando brak).
WatTweede ronde voor tenant
De pins, elk nagekeken als GitHub-release met
Wat de startupProbe wel en niet doetMet nginx als sidecar zet chart 8.9.0 de startupProbe alleen op de nginx-container, niet op de Nextcloud-container waarin de hook draait. Een te krappe probe breekt de hook dus niet af: hij herstart nginx tot die in CrashLoopBackOff staat, en dan komt de tenant pas online na de backoff, ook als de hook al klaar is. Met 30 minuten valt de repetitietijd (22 minuten) erbinnen met marge. Waarom de hook twee keer draaideBij een eerste installatie roept de entrypoint van de image eerst Voorstel, niet in deze PR (het is een wijziging aan
dan logt de hook "already at pin", doet geen download, geen wissel en geen Gedraaid
Niet gedraaid: VolgordeTenantwijziging, label De integriq-release met de fix is niet door de repetitie gegaan. De eerste start op het cluster is dus de eerste keer dat deze set van 16 samen draait; kijk na de start in 🤖 Generated with Claude Code |
…q voorlopig uit integriq loopt in cron tegen het geheugen aan bij een externe synchronisatie en komt terug met een pin-bump zodra die fix uit is. decidiq staat een release verder: alleen de voorbeelddata van de vergaderingen is aangepast, zodat de nachtelijke reset slaagt. Alle 15 releases hebben hun tarball.
Update: pins van de derde generale repetitie (16 oktober)Commit
Alle 15 releases hebben hun
Uit de repetitie: de install-hook deed er 13m23s over, binnen de startupProbe van ~30 minuten. Wat volgt, als aparte tenant-PR na #147: 🤖 Generated with Claude Code |
Nieuwe tenant
zuiddrecht-prod: de demogemeente Zuiddrecht, één Nextcloud op vier hostnamen.Gestapeld op #138: volgorde
Deze PR heeft
tenant.extraHostnamesentenant.extraHostnamesAllowApexuit #138 nodig. Hij is gemaakt van de branch van #138 metmainerin gemerged, dus tot #138 binnen is toont de diff ook de wijzigingen van #138.maininscripts/verify.sh,docs/ADDING-TENANT.mdendocs/index.md. De oplossing staat in de merge-commit van deze branch: inverify.shbeide checks houden (render-extra-hosts en hook-tests), in de twee docslast_reviewed: 2026-10-14.nextcloud-platform-bootstrapin Argo, zodat de ApplicationSet metextraHostnameslive staat. Die app heeft geenautomated; dat doet een mens.mainerin mergen (de diff is dan alleen het tenantbestand) en mergen.promote-tenant-changesschuift danreleaseenrelease-acceptdoor.Label:
change/tenant-additive. Zolang #138 niet gemerged is, ziet governance-check ook platformbestanden in de diff en blijft hij rood. Dat is hier de rem: deze PR hoort niet vóór #138 binnen te komen.Wat de tenant krijgt
cloud.zuiddrecht.nlnextcloudzuiddrecht.nlnextcloud-extra-hosts-apex, HSTS zonder includeSubDomainswww.zuiddrecht.nlnextcloud-extra-hostsmijn.zuiddrecht.nlnextcloud-extra-hostsElke host krijgt een eigen certificaat via HTTP-01 (
letsencrypt-prod). De apex staat erin metextraHostnamesAllowApex: true; de zone is van de demo.dbType: postgres,secrets.managed: true(ESO maaktnextcloud-secrets, zoals bij elke nieuwe tenant sinds augustus).<id>en<version>inappinfo/info.xml.registrationuit de Nextcloud app store, zonder pin: de hook installeert een ongepinde app metocc app:install. Inwoners maken daarmee zelf een account aan.overwrite.cli.urlnaarhttps://cloud.zuiddrecht.nlvia een eigenzuiddrecht.config.php(docs/CONFIG-CHANGES.md, één tenant), zodat links uit cron naar de werkplek wijzen. Taalnl, localenl_NLen telefoonregioNLstaan al voor de hele vloot incommon.yaml.startupProbe.failureThreshold: 84: 30 s + 840 s, ongeveer 15 minuten. De eerste start haalt 16 apps van GitHub voordat php-fpm opkomt. De probe zit op de nginx-container; met de standaard (5,5 minuut) zou nginx in CrashLoopBackOff gaan en kwam de tenant pas na de backoff online.Niet in deze tenant: learniq, larpinq, zaakafhandelapp, humaniq, planninq.
Pins
2.1.41-unstable.202610141803232.1.22-unstable.202610140659170.4.12-unstable.202610121803380.2.7-unstable.202610141049571.2.27-unstable.202610140957011.1.8-unstable.202610140909250.2.6-unstable.202610131555520.4.53-unstable.202610141718430.5.21-unstable.202610141351580.5.7-unstable.202610141210220.2.10-unstable.202610141800471.2.7-unstable.202610141813000.7.17-unstable.202610121612340.3.12-unstable.202610121259580.2.18-unstable.202610131711531.6.8-unstable.20261012134348Gecontroleerd
Lokaal op deze branch, met exitcode:
nextcloud-platform/scripts/validate-values.sh: 0 (zuiddrecht-prod slaagt, alleen de verwachte waarschuwingen voor hostnameOverride en extraHostnames)nextcloud-platform/tests/run-tests.sh: 0 (43 geslaagd, 0 gefaald)scripts/verify.sh: 0 (validate-values, smoke-checks, doc-assertions, validator-tests, render-extra-hosts, hook-tests)pre-commit run --all-files --hook-stage pre-push: 0yamllintop het tenantbestand: 0helm templatemet chart 8.9.0 in de valueFiles-volgorde, pluscharts/tenant-secret), enkubeconform -strictop het resultaat: 0 (21 resources, 19 geldig, 2 overgeslagen CRD's). In de render: drie Ingresses met één certificaat per host,NEXTCLOUD_TRUSTED_DOMAINSmet alle vier hosts,CONDUCTION_APPSmet 17 apps,CONDUCTION_APP_VERSIONSmet 16 pins,zuiddrecht.config.phpin de config-ConfigMap, de ExternalSecret en de startupProbe metfailureThreshold: 84.Wat een mens nog doet
zuiddrecht.nl: vier A-records naar81.24.6.82, DNS only (niet geproxied):zuiddrecht.nl,www.zuiddrecht.nl,mijn.zuiddrecht.nl,cloud.zuiddrecht.nl. De zone valt niet onder external-dns. Zonder kloppende DNS faalt HTTP-01 voor die host; de andere hosts hebben er geen last van.nextcloud-secretsop de eerste sync (een kortesecret "nextcloud-secrets" not foundheelt vanzelf). Terugval als ESO het niet doet:./nextcloud-platform/scripts/create-tenant-secret.sh zuiddrecht-prod --postgres --namespace zuiddrecht-prod --generate-passwords, en dansecrets.manageduit het bestand halen.nextcloud-platform-bootstrapsyncen; na de merge van deze PR de ApplicationSet verversen (/sync-tenant zuiddrecht-prod --refresh-appset).existingSecretnoemt de sleutelssmtp-host,smtp-usernameensmtp-password, maar er is geennextcloud.mail-blok,smtp.config.phpstaat uit en geen script maakt die sleutels aan.🤖 Generated with Claude Code