From 5de2e9367d3fbd54124df865e5de8449c82d3a45 Mon Sep 17 00:00:00 2001 From: Niek Otten Date: Thu, 16 Jul 2026 15:43:03 +0200 Subject: [PATCH] fix(infra): portal nginx resolver works on podman too, not just Docker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The portal reverse proxies hardcoded Docker's embedded DNS (resolver 127.0.0.11); on rootless podman the DNS is network-specific (aardvark), so every proxied BFF call 502'd. Add an /docker-entrypoint.d hook that rewrites the resolver from the container's /etc/resolv.conf at startup — a no-op on Docker (nameserver IS 127.0.0.11), correct on podman. Verified: the built image rewrites to 10.89.0.1 and /behandel/werkbak proxies to the BFF (401, not 502). Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/behandel/Dockerfile | 4 ++++ apps/openbaar/Dockerfile | 4 ++++ apps/portal-nginx-resolver.sh | 17 +++++++++++++++++ apps/self-service/Dockerfile | 4 ++++ 4 files changed, 29 insertions(+) create mode 100644 apps/portal-nginx-resolver.sh diff --git a/apps/behandel/Dockerfile b/apps/behandel/Dockerfile index a25680b..b017248 100644 --- a/apps/behandel/Dockerfile +++ b/apps/behandel/Dockerfile @@ -19,5 +19,9 @@ COPY --from=build /src/dist/apps/behandel/browser /usr/share/nginx/html # Compose-time OIDC config: the browser (Playwright, on the compose network) reaches Keycloak by # service name, so the token issuer matches the BFF's medewerker authority (host-consistent, ADR-0013). RUN printf '{ "authority": "http://keycloak:8080/realms/medewerker" }\n' > /usr/share/nginx/html/config.json +# Make the reverse-proxy resolver engine-portable (Docker 127.0.0.11 vs podman aardvark); runs from +# the nginx image's /docker-entrypoint.d before nginx starts. +COPY apps/portal-nginx-resolver.sh /docker-entrypoint.d/40-resolver.sh +RUN chmod +x /docker-entrypoint.d/40-resolver.sh EXPOSE 80 diff --git a/apps/openbaar/Dockerfile b/apps/openbaar/Dockerfile index ffeacf6..3707da1 100644 --- a/apps/openbaar/Dockerfile +++ b/apps/openbaar/Dockerfile @@ -17,5 +17,9 @@ FROM nginx:1.27-alpine AS runtime COPY apps/openbaar/nginx.conf /etc/nginx/conf.d/default.conf COPY --from=build /src/dist/apps/openbaar/browser /usr/share/nginx/html # No runtime config: the openbaar register is anonymous (no OIDC authority to inject). +# Make the reverse-proxy resolver engine-portable (Docker 127.0.0.11 vs podman aardvark); runs from +# the nginx image's /docker-entrypoint.d before nginx starts. +COPY apps/portal-nginx-resolver.sh /docker-entrypoint.d/40-resolver.sh +RUN chmod +x /docker-entrypoint.d/40-resolver.sh EXPOSE 80 diff --git a/apps/portal-nginx-resolver.sh b/apps/portal-nginx-resolver.sh new file mode 100644 index 0000000..ed6c3ce --- /dev/null +++ b/apps/portal-nginx-resolver.sh @@ -0,0 +1,17 @@ +#!/bin/sh +# Point nginx's reverse-proxy `resolver` at THIS container's real DNS server. +# +# The portal nginx configs use a variable proxy_pass, which needs a `resolver` so the BFF hostname is +# resolved at request time (nginx can start before the BFF is up). The config hardcodes Docker's +# embedded DNS (127.0.0.11) — correct on Docker/Docker Desktop, but rootless podman uses a +# network-specific address (aardvark, e.g. 10.89.0.1), so proxied calls 502 there. Read the actual +# nameserver from /etc/resolv.conf and substitute it, so the reverse proxy works on any engine. +# +# Runs from the nginx image's /docker-entrypoint.d/ before nginx starts. On Docker the nameserver IS +# 127.0.0.11, so the substitution is a no-op. Guarded (no `set -e`) so it's safe whether the nginx +# entrypoint executes or sources it. +ns="$(awk '/^nameserver/{print $2; exit}' /etc/resolv.conf 2>/dev/null)" +if [ -n "$ns" ] && [ "$ns" != "127.0.0.11" ]; then + sed -i "s/resolver 127\.0\.0\.11/resolver $ns/" /etc/nginx/conf.d/default.conf 2>/dev/null || true + echo "portal-nginx-resolver: set resolver to $ns" +fi diff --git a/apps/self-service/Dockerfile b/apps/self-service/Dockerfile index 6f72a08..20213df 100644 --- a/apps/self-service/Dockerfile +++ b/apps/self-service/Dockerfile @@ -19,5 +19,9 @@ COPY --from=build /src/dist/apps/self-service/browser /usr/share/nginx/html # Compose-time OIDC config: the browser (Playwright, on the compose network) reaches Keycloak by # service name, so the token issuer matches the BFF's authority (host-consistent, ADR-0010). RUN printf '{ "authority": "http://keycloak:8080/realms/digid" }\n' > /usr/share/nginx/html/config.json +# Make the reverse-proxy resolver engine-portable (Docker 127.0.0.11 vs podman aardvark); runs from +# the nginx image's /docker-entrypoint.d before nginx starts. +COPY apps/portal-nginx-resolver.sh /docker-entrypoint.d/40-resolver.sh +RUN chmod +x /docker-entrypoint.d/40-resolver.sh EXPOSE 80 -- 2.49.1