From 3761924242e2afc116a212987f17c0e9a5277a58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kr=C3=BCger?= Date: Mon, 17 Aug 2026 19:29:43 +0200 Subject: [PATCH] fix(traefik): expose API on an internal-only entrypoint for container-to-container access The public traefik.pivoine.art path round-trips through the host's published port, and Docker's hairpin NAT there rewrites the source IP before it reaches vpn-only's allowlist, so pulsenode's own request was getting a 403 despite falcon_network being allowlisted. Port 8080 is not published to the host, so it's reachable only from other falcon_network containers - no TLS/vpn-only needed, and it's not exposed externally. --- pulsenode/config/config.yml | 2 +- traefik/compose.yml | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/pulsenode/config/config.yml b/pulsenode/config/config.yml index faeb163..0a64a80 100644 --- a/pulsenode/config/config.yml +++ b/pulsenode/config/config.yml @@ -12,7 +12,7 @@ groups: - type: traefik name: Traefik - apiUrl: https://traefik.pivoine.art/api + apiUrl: http://traefik:8080/api interval: 15s - type: docker diff --git a/traefik/compose.yml b/traefik/compose.yml index b6034a9..dcae35b 100644 --- a/traefik/compose.yml +++ b/traefik/compose.yml @@ -21,6 +21,13 @@ services: - "--entrypoints.web.http.redirections.entryPoint.scheme=https" - "--entrypoints.web.http.redirections.entryPoint.permanent=true" - "--entrypoints.web-secure.http.middlewares=security-headers@file,fail2ban@file" + # Not published to the host - reachable only container-to-container on + # falcon_network. Lets other stacks (e.g. pulsenode) read the API + # directly without going through the public hostname, where a hairpin + # NAT round-trip through the host's published port rewrites the source + # IP and defeats vpn-only's IP allowlist. + - "--entrypoints.internal.address=:8080" + - "--ping.entrypoint=web-secure" - "--certificatesresolvers.resolver.acme.tlschallenge=true" - "--certificatesresolvers.resolver.acme.email=${ACME_EMAIL}" - "--certificatesresolvers.resolver.acme.storage=/letsencrypt/acme.json" @@ -53,6 +60,9 @@ services: - "traefik.http.routers.traefik-dashboard-web-secure.tls.certresolver=resolver" - "traefik.http.routers.traefik-dashboard-web-secure.middlewares=vpn-only@file,security-headers@file,no-index@file" - "traefik.http.routers.traefik-dashboard-web-secure.service=api@internal" + - "traefik.http.routers.traefik-internal.rule=PathPrefix(`/`)" + - "traefik.http.routers.traefik-internal.entrypoints=internal" + - "traefik.http.routers.traefik-internal.service=api@internal" networks: - compose_network - coolify_network