From 8c5bbe05a9d36e02d4136be42bded26caed00e90 Mon Sep 17 00:00:00 2001 From: Edwin van den Houdt Date: Wed, 3 Jun 2026 13:16:31 +0000 Subject: [PATCH] feat(infra): OpenZaak + Postgres + Redis up in compose (refs #10) (#40) --- Makefile | 28 +++++++++- docs/runbooks/openzaak.md | 50 ++++++++++++++++++ infra/openzaak/docker-compose.yml | 88 +++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 docs/runbooks/openzaak.md create mode 100644 infra/openzaak/docker-compose.yml diff --git a/Makefile b/Makefile index 4848f54..28a45dc 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,8 @@ SLN := services/bff/Bff.slnx COMPOSE := infra/docker-compose.yml HEALTH_URL := http://localhost:8080/health +OZ_COMPOSE := infra/openzaak/docker-compose.yml +OZ_BASE := http://localhost:8000 # On a rootless Podman dev box, point Docker CLI/Compose at the Podman socket — # but only if that socket exists and DOCKER_HOST isn't already set, so real @@ -19,7 +21,7 @@ export DOCKER_HOST := unix://$(PODMAN_SOCK) endif endif -.PHONY: ci lint build unit smoke down changelog help +.PHONY: ci lint build unit smoke down changelog openzaak-up openzaak-smoke openzaak-down help ## ci: run the full pipeline — lint, build, unit, smoke (mirrors Gitea Actions) ci: lint build unit smoke @@ -49,6 +51,30 @@ down: changelog: git-cliff --output CHANGELOG.md +## openzaak-up: start the OpenZaak stack (migrations run on first start) +openzaak-up: + docker compose -f $(OZ_COMPOSE) up -d + +## openzaak-smoke: start OpenZaak, then assert it is up with auth enforced +openzaak-smoke: + docker compose -f $(OZ_COMPOSE) up -d + @bash -c 'set -e; \ + echo "waiting for OpenZaak to respond..."; \ + for i in $$(seq 1 60); do \ + code=$$(curl -s -o /dev/null -w "%{http_code}" $(OZ_BASE)/zaken/api/v1/zaken || true); \ + [ -n "$$code" ] && [ "$$code" != "000" ] && break; sleep 3; \ + done; \ + echo "GET /zaken/api/v1/zaken (unauth) -> $$code (expect 403, auth enforced)"; test "$$code" = "403"; \ + admin=$$(curl -s -o /dev/null -w "%{http_code}" $(OZ_BASE)/admin/); \ + echo "GET /admin/ -> $$admin (expect 302)"; test "$$admin" = "302"; \ + root=$$(curl -s -o /dev/null -w "%{http_code}" $(OZ_BASE)/zaken/api/v1/); \ + echo "GET /zaken/api/v1/ -> $$root (expect 200)"; test "$$root" = "200"; \ + echo "OpenZaak smoke OK"' + +## openzaak-down: stop and remove the OpenZaak stack (wipes data) +openzaak-down: + docker compose -f $(OZ_COMPOSE) down --volumes + ## help: list available targets help: @grep -E '^## ' $(MAKEFILE_LIST) | sed 's/^## //' diff --git a/docs/runbooks/openzaak.md b/docs/runbooks/openzaak.md new file mode 100644 index 0000000..7744dc2 --- /dev/null +++ b/docs/runbooks/openzaak.md @@ -0,0 +1,50 @@ +# OpenZaak runbook + +The OpenZaak stack (`infra/openzaak/docker-compose.yml`) is a lean adaptation of the +upstream open-zaak dev compose: PostGIS db, redis, a one-shot init that runs +migrations, the OpenZaak API, and a celery worker. + +## Quick test (`make`) + +```bash +make openzaak-up # start the stack (first run pulls images + migrates: 1-3 min) +make openzaak-smoke # start + assert it's up with auth enforced (403/302/200) +make openzaak-down # stop and wipe data +``` + +`make openzaak-smoke` polls until the API responds, then asserts: + +| Check | Expected | +|---|---| +| `GET /zaken/api/v1/zaken` (no JWT) | **403** — `PermissionDenied` ZGW fout (auth enforced) | +| `GET /admin/` | **302** — admin login redirect | +| `GET /zaken/api/v1/` | **200** — ZGW API schema root | + +> **403, not 401.** OpenZaak's ZGW APIs return `403 PermissionDenied` for a missing +> or invalid JWT. The S-01 acceptance text says "401" — that's inaccurate; 403 is the +> correct auth-enforced response. + +The admin UI is at ; the dev superuser is **admin / +admin** (from the compose env — dev only). + +## Prerequisites (rootless Podman) + +Same setup as the rest of the repo (see [ci.md](ci.md)): + +```bash +systemctl --user start podman.socket # the Docker-API socket the shim talks to +``` + +The Makefile auto-points `DOCKER_HOST` at the Podman socket when it exists, so the +`make openzaak-*` targets work without extra env. + +## Notes + +- **Not in `make ci`.** The OpenZaak smoke is a separate, heavier check (large image + pull + migrations); it is intentionally kept out of `make ci` so the core gate + stays fast. Run `make openzaak-smoke` when you touch the OpenZaak stack. +- **No catalogus/zaaktypen yet.** Seeding the `BIG` catalogus + `BIG-registratie` + zaaktype and a JWT client is the next slice (**S-01-b**); authenticated zaaktype + listing isn't testable until then. +- **Image tag.** Currently `openzaak/open-zaak:latest` via `${OPENZAAK_TAG}`; pin to + a known-good tag as part of the catalogus-design ADR. diff --git a/infra/openzaak/docker-compose.yml b/infra/openzaak/docker-compose.yml new file mode 100644 index 0000000..a620416 --- /dev/null +++ b/infra/openzaak/docker-compose.yml @@ -0,0 +1,88 @@ +# OpenZaak stack (S-01). Lean adaptation of the upstream open-zaak dev compose: +# db (PostGIS) + redis + a one-shot init (migrations) + the API + a celery worker. +# Dropped from upstream for leanness: nginx, celery-beat, flower, OTEL. +# +# docker compose -f infra/openzaak/docker-compose.yml up -d --wait +# curl -i http://localhost:8000/zaken/api/v1/zaken # -> 401 (auth required) +# +# NOTE: image pinned to a tag (not :latest) once a known-good tag is chosen; see +# the catalogus-design ADR. Using a tag var with a sensible default for now. +services: + oz-db: + image: docker.io/postgis/postgis:17-3.5 + environment: + POSTGRES_USER: openzaak + POSTGRES_PASSWORD: openzaak + POSTGRES_DB: openzaak + command: postgres -c max_connections=300 + volumes: + - oz-db:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U openzaak -d openzaak"] + interval: 5s + timeout: 3s + retries: 10 + networks: [oz] + + oz-redis: + image: docker.io/library/redis:7 + networks: [oz] + + oz-init: + image: docker.io/openzaak/open-zaak:${OPENZAAK_TAG:-latest} + environment: &oz-env + DJANGO_SETTINGS_MODULE: openzaak.conf.docker + SECRET_KEY: ${OZ_SECRET_KEY:-dev-only-not-for-production} + DB_HOST: oz-db + DB_NAME: openzaak + DB_USER: openzaak + DB_PASSWORD: openzaak + IS_HTTPS: "no" + ALLOWED_HOSTS: "*" + CACHE_DEFAULT: oz-redis:6379/0 + CACHE_AXES: oz-redis:6379/0 + CELERY_BROKER_URL: redis://oz-redis:6379/1 + CELERY_RESULT_BACKEND: redis://oz-redis:6379/1 + DISABLE_2FA: "true" + OPENZAAK_SUPERUSER_USERNAME: admin + DJANGO_SUPERUSER_PASSWORD: admin + OPENZAAK_SUPERUSER_EMAIL: admin@localhost + RUN_SETUP_CONFIG: "false" + command: /setup_configuration.sh + depends_on: + oz-db: + condition: service_healthy + oz-redis: + condition: service_started + networks: [oz] + + openzaak: + image: docker.io/openzaak/open-zaak:${OPENZAAK_TAG:-latest} + environment: *oz-env + healthcheck: + test: ["CMD", "python", "-c", "import requests,sys; sys.exit(0 if requests.head('http://localhost:8000/admin/').status_code in (200,302) else 1)"] + interval: 10s + timeout: 5s + retries: 10 + start_period: 30s + ports: + - "8000:8000" + depends_on: + oz-init: + condition: service_completed_successfully + networks: [oz] + + oz-celery: + image: docker.io/openzaak/open-zaak:${OPENZAAK_TAG:-latest} + environment: *oz-env + command: /celery_worker.sh + depends_on: + oz-init: + condition: service_completed_successfully + networks: [oz] + +volumes: + oz-db: + +networks: + oz: