From 1c6b16e82349e494652477022a6d6dbd6ba46bc3 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Wed, 3 Jun 2026 19:18:39 -0400 Subject: [PATCH] fix: align caddy route container's site declarator with web's The non-web container's caddy=DOMAIN label and web's caddy=DOMAIN:80 label declare separate Caddyfile site blocks, so caddy-docker-proxy never merges the route's handle directive into the site that actually serves port 80. fn-caddy-route-labels now mirrors web's letsencrypt + 443 check and emits DOMAIN:80 in the HTTP-only path. The bats T1 also dumps the web container's labels alongside api's so future declarator mismatches are visible in CI logs. --- plugins/caddy-vhosts/internal-functions | 25 +++++++++++++++++++++---- tests/unit/proxy-route-caddy.bats | 7 +++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/plugins/caddy-vhosts/internal-functions b/plugins/caddy-vhosts/internal-functions index 472a4b684..003ea1d37 100755 --- a/plugins/caddy-vhosts/internal-functions +++ b/plugins/caddy-vhosts/internal-functions @@ -18,10 +18,27 @@ fn-caddy-route-labels() { output="" if [[ -n "$caddy_domains" ]]; then - # Joining the same site declared by the web container so this container's - # handler directives are merged into the existing site block by - # caddy-docker-proxy. - output="--label 'caddy=${caddy_domains}'" + # Mirror web's site-declarator computation in docker-args-process-deploy so + # both containers join the same Caddyfile site block. caddy treats DOMAIN + # and DOMAIN:80 as separate sites - if web declares DOMAIN:80 and we + # declare DOMAIN, caddy-docker-proxy renders two unrelated site blocks + # and the route's handle never sees port-80 traffic. + local letsencrypt_email port_map scheme host_port + local has_443_mapping=false + letsencrypt_email="$(fn-caddy-computed-letsencrypt-email)" + while read -r port_map; do + scheme="$(awk -F ':' '{ print $1 }' <<<"$port_map")" + host_port="$(awk -F ':' '{ print $2 }' <<<"$port_map")" + if [[ "$scheme" == "https" ]] || [[ "$host_port" == "443" ]]; then + has_443_mapping=true + fi + done < <(plugn trigger ports-get "$APP") + + if [[ -n "$letsencrypt_email" ]] && [[ "$has_443_mapping" == "true" ]]; then + output="--label 'caddy=${caddy_domains}'" + else + output="--label 'caddy=${caddy_domains//, /:80, }:80'" + fi fi while IFS='|' read -r route_proc route_port route_path route_strip; do diff --git a/tests/unit/proxy-route-caddy.bats b/tests/unit/proxy-route-caddy.bats index f64f6f412..f9c4ca33f 100644 --- a/tests/unit/proxy-route-caddy.bats +++ b/tests/unit/proxy-route-caddy.bats @@ -42,6 +42,13 @@ teardown() { run /bin/bash -c "docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1 | jq . 2>/dev/null || docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1" echo "api labels: $output" + # Also dump the web container's labels so we can compare site declarators + # between web and api - caddy treats DOMAIN and DOMAIN:80 as separate + # sites, and a mismatch keeps caddy-docker-proxy from merging the two + # containers' directives into a single site block. + run /bin/bash -c "docker inspect ${TEST_APP}.web.1 --format '{{json .Config.Labels}}' 2>&1 | jq . 2>/dev/null || docker inspect ${TEST_APP}.web.1 --format '{{json .Config.Labels}}' 2>&1" + echo "web labels: $output" + # Give the daemon a moment to read the new labels. sleep 5