Date: 2026-03-05 Goal: Get ExApp sidecar wrappers (OpenKlant, OpenZaak, Valtimo, OpenTalk, Keycloak) up and running, following the n8n pattern.
All 5 ExApp Docker containers are running and healthy. They are registered with AppAPI in Nextcloud. However, AppAPI's heartbeat mechanism is not fully completing the initialization cycle for all apps yet.
- keycloak-nextcloud — New repo created at ConductionNL/keycloak-nextcloud, added as submodule
- open-webui-nextcloud — Added as submodule (repo already existed)
- openklant, openzaak, valtimo, opentalk — Existing submodules,
ex_app/lib/main.pyrewritten to usenc_py_apipattern
| App | Image | Base | Status |
|---|---|---|---|
| Keycloak | ghcr.io/conductionnl/keycloak-nextcloud:latest |
UBI9-minimal + microdnf Python + Keycloak 26.5.4 | Built, running |
| OpenKlant | ghcr.io/conductionnl/openklant-exapp:latest |
maykinmedia/open-klant:2.15.0 | Built, running |
| OpenZaak | ghcr.io/conductionnl/openzaak-exapp:latest |
openzaak/open-zaak:1.27.0 | Built, running |
| Valtimo | ghcr.io/conductionnl/valtimo-exapp:latest |
eclipse-temurin:17-jre-jammy + ritense/valtimo-backend:12.0.0 | Built, running |
| OpenTalk | ghcr.io/conductionnl/opentalk-exapp:latest |
python:3.11-slim + opentalk controller v0.31.0-3 | Built, running |
- All 5 ExApp services added under
commonground+exappsprofiles - Shared infrastructure:
exapp-redis(Redis 7),exapp-livekit(LiveKit WebRTC) - PostgreSQL databases created: keycloak, openklant, openzaak, opentalk, valtimo
- AppAPI-generated secrets hardcoded in compose for each ExApp
- Healthchecks use Python urllib (no wget/curl dependency)
- 5 manual-install daemons registered (one per ExApp)
- All 5 apps registered in
oc_ex_appstable - Keycloak: enabled, OpenKlant/OpenZaak/Valtimo/OpenTalk: disabled (pending init)
| App | Port |
|---|---|
| n8n | 23000 |
| Keycloak | 23002 |
| OpenZaak | 23003 |
| Valtimo | 23004 |
| OpenKlant | 23005 |
| OpenTalk | 23005 |
All 8 ExApp containers running and healthy:
openregister-exapp-keycloak healthy
openregister-exapp-openklant healthy
openregister-exapp-openzaak healthy
openregister-exapp-valtimo healthy
openregister-exapp-opentalk healthy
openregister-exapp-livekit healthy
openregister-exapp-redis healthy
openregister-exapp-n8n healthy
AppAPI checks heartbeat on each ExApp's assigned port. Some ExApps (valtimo, opentalk) are getting heartbeat counts but others (keycloak, openklant, openzaak) are stuck at 0. This may be an AppAPI internal scheduling issue or related to the high failure count from before we fixed the heartbeat endpoints.
Possible fix: Unregister and re-register the stuck ExApps, or investigate AppAPI's heartbeat scheduling.
The heartbeat endpoints return {"status":"waiting"} (HTTP 200) because the wrapped services (Django, Spring Boot, Rust) only start when AppAPI calls /init or /enabled. This is the chicken-and-egg: heartbeat must succeed → AppAPI calls init → internal service starts → heartbeat returns "ok".
The 200 status fix should resolve this — AppAPI should proceed to call /init once it sees successful heartbeats.
/settings/admin/app_api crashes with "Unknown named parameter $app" in ZaakAfhandelAppAdmin.php:55. This is unrelated to the ExApp work but blocks the AppAPI admin UI.
OpenZaak may need PostGIS extension but the pgvector PostgreSQL image doesn't include it. OpenZaak may need a different approach (PostGIS Docker image or skip geo features).
Changes to entrypoint.sh, main.py (heartbeat fix), Dockerfiles, and docker-compose.yml are local only. Need to commit and push to feature branches for each submodule.
docker-compose.yml— Added 5 ExApp services, volumes, healthchecks, secrets, port assignments
- Full ExApp structure:
ex_app/lib/main.py,Dockerfile,entrypoint.sh,appinfo/info.xml, CI workflows
ex_app/lib/main.py— Rewritten with nc_py_api, heartbeat returns 200Dockerfile— Updated base image to 2.15.0entrypoint.sh— Fixed to usepython3 ex_app/lib/main.py
ex_app/lib/main.py— Rewritten with nc_py_api, heartbeat returns 200Dockerfile— Updated base image to 1.27.0entrypoint.sh— Fixed to usepython3 ex_app/lib/main.pyappinfo/info.xml— Fixed registry to ghcr.io
ex_app/lib/main.py— Rewritten with nc_py_api, heartbeat returns 200Dockerfile— Rewritten with proper Python installentrypoint.sh— Fixed to usepython3 ex_app/lib/main.pyappinfo/info.xml— Fixed registry to ghcr.io
ex_app/lib/main.py— Rewritten with nc_py_api, heartbeat returns 200Dockerfile— Added controller.toml config filecontroller.toml— New minimal config for OpenTalk controllerentrypoint.sh— Fixed to usepython3 ex_app/lib/main.pyappinfo/info.xml— Fixed registry to ghcr.io
- Keycloak UBI9-micro has no package manager — use UBI9-minimal with microdnf instead
- glibc compatibility matters — Python from Debian/Ubuntu cannot run on UBI9 (glibc 2.38 vs 2.34)
- AppAPI assigns unique ports per ExApp — containers must listen on the assigned port, not hardcoded 23000
- APP_SECRET must match between docker-compose env and AppAPI's database — get secrets from
oc_ex_appstable - Healthcheck must return 200 even when internal service isn't running, or AppAPI won't proceed to
/init - Docker compose
${VAR}in healthcheck resolves at compose level, not container level — use Pythonos.environor$$VARinstead
- Investigate why some ExApps aren't getting heartbeat checks from AppAPI
- Once heartbeats work, verify
/initis called and internal services start - Enable all 4 disabled ExApps
- Test through browser at http://localhost:8080
- Commit all changes to feature branches
- Push Docker images to ghcr.io