Formulieren deployen via GitHub (zonder server-toegang)¶
Een developer hoeft niet op de server in te loggen. Alles loopt via GitHub. Een self-hosted runner op de server pakt de jobs op (alleen uitgaande verbinding; geen open poorten).
Een nieuw of gewijzigd formulier live zetten¶
- Ontwerp het formulier in de repo. Maak/bewerk
config/forms/<slug>/: form.py— de definitie (kopieerconfig/forms/skeleton-form.pyals startpunt)objecttype.json— het objecttype dat bij dit formulier hoortdeploy.sh— de deploy-wrapper (kopieer van een bestaand formulier)
Zie ../developer/formulieren-tips.md voor de valkuilen.
-
Commit op een branch en open een PR. Een commit of merge doet op zichzelf niets op de server — er gaat dus niets automatisch live en er is geen downtime.
-
Merge de PR naar
main(na review). -
Deploy met de knop. GitHub → tab Actions → workflow "Formulieren deployen" → Run workflow:
- laat het veld leeg om alle formulieren te (her)deployen, of
- vul de mapnaam in (bv.
evenementenvergunning) voor één formulier.
De runner haalt main op, maakt het objecttype aan als het nog niet bestaat,
en bouwt het formulier in Open Forms. Dit is zero-downtime: er draait alleen
manage.py shell ín de draaiende container, geen herstart.
Idempotent: je kunt de deploy zo vaak draaien als je wilt. Het script is de bron van waarheid — pas het script aan, niet de admin-UI.
Losse objecttypes deployen¶
Objecttypes die bij een formulier horen (config/forms/<slug>/objecttype.json)
gaan automatisch mee met "Formulieren deployen". Voor de standalone
objecttypes in config/objecttypes/ (niet form-gebonden) is er een aparte knop:
GitHub → Actions → "Objecttypes deployen" → Run workflow. Dit is
zero-downtime en doet twee dingen:
1. de objecttype-definitie(s) aanmaken/bijwerken (bootstrap-objecttype.sh);
2. de Objects-API-permissies toepassen (objects.yaml → setup_configuration),
zodat een nieuw objecttype ook echt beschrijfbaar is (anders krijg je 403).
Voorwaarde voor een nieuw standalone objecttype dat beschreven moet worden: voeg het toe aan
config/objects.yaml(permissie-entry) en aan de envsubst- whitelist inscripts/setup-service.sh. Let op:bootstrap-objecttype.shpubliceert alleen versie 1; een schema-wijziging van een bestaand type is een nieuwe objecttype-versie en valt buiten deze knop.
Onderhoud (acties die WEL downtime geven)¶
Image-updates, migraties en herstarts maken de stack even onbeschikbaar. Die zitten bewust in een aparte handmatige workflow, zodat downtime alleen op een zelfgekozen moment gebeurt — nooit automatisch bij een commit of merge.
GitHub → Actions → "Onderhoud (kan downtime geven)" → Run workflow:
- kies de actie (image-update + herstart / migraties / herstart);
- typ JA ter bevestiging (anders breekt de workflow af zonder iets te doen).
De workflow voert deze stappen uit (gebruikers zien een nette pagina, HTTP 503,
i.p.v. een fout — zie platform/docs/onderhoud.md):
- Onderhoudspagina AAN — vóór de actie.
- De gekozen actie — image-update + herstart / migraties / herstart.
- Wachten tot Open Forms weer reageert (readiness-stap) —
docker compose restart/upkeert al terug zodra de containers dráaien, maar Open Forms heeft daarna nog ~15–20s nodig om te serveren. Deze stap pollt OF rechtstreeks op het interne netwerk (langs de onderhoudspagina heen; elke HTTP-statusregel = OF is up) en gaat pas door zodra OF echt antwoordt. Zonder deze stap zou de pagina te vroeg uitgaan en zagen gebruikers alsnog een 502. - Onderhoudspagina UIT — alleen bij succes (dus pas nadat OF weer reageert).
Mislukt een stap (incl. een time-out van de readiness-stap, ~120s), dan blijft
de pagina bewust aan — liever de pagina dan een kapotte site. De run-log
waarschuwt dat je 'm na herstel handmatig uitzet met
cd platform && make onderhoudsmodus-uit.
Onder de motorkap¶
- Runner: systemd-service
gh-runner-zgwop de server (/opt/actions-runner-zgw), labelsself-hosted, zgw. Draait als de apartedeploy-user (niet root), die in dedocker-groep zit en via een ACL alleen/root/zgwmag benaderen. Status: GitHub → Settings → Actions → Runners. - Secrets: de runner gebruikt de live
/root/zgw/.envop de server; er staan geen secrets in GitHub. Degit fetchin de workflow authenticeert met de repo-gescopete job-token (github.token), niet met een opgeslagen sleutel. - Workflows:
.github/workflows/deploy-forms.ymlen.github/workflows/onderhoud.yml. Beide draaiengit reset --hard origin/mainzodat de server exactmainvolgt (de gegenereerde/gitignorede bestanden zoals.envblijven staan).
Beveiliging:
deployzit in dedocker-groep — dat is in de praktijk root-equivalent (docker kan de host-fs mounten). De winst t.o.v. root is procesisolatie, helder eigenaarschap en geen per ongeluk root-geschreven bestanden. Wil je écht minder rechten, dan kan een smallesudo-regel voor alleen de specifieke compose-commando's i.p.v. docker-groep.