Skip to content

fix(hosted): name the ingress network on routed runtime services - #30

Merged
jeremi merged 1 commit into
mainfrom
fix/pin-ingress-network-for-routed-services
Aug 20, 2026
Merged

fix(hosted): name the ingress network on routed runtime services#30
jeremi merged 1 commit into
mainfrom
fix/pin-ingress-network-for-routed-services

Conversation

@jeremi

@jeremi jeremi commented Aug 20, 2026

Copy link
Copy Markdown
Member

The failure

After the authority-cells reset deployed, the hosted routes answered
inconsistently: cra-relay, cra-evidence, nia-evidence, sro-evidence,
mosd-programme-evidence, sipf-relay and nagdi-relay returned 200 while
nia-relay, mosd-programme-relay, sipf-evidence and nagdi-evidence hung
until curl timed out with zero bytes. The split held across repeated attempts
over six minutes, so it did not look transient.

Restarting nia-relay alone then flipped cra-relay, which had not been
touched, from 200 to a hang. That is the tell.

The cause

Coolify puts each routed container on two networks: the application network
named after the application uuid, which carries coolify-proxy, and the
compose-declared <uuid>_runtime network on 172.29.x, which does not. From
inside coolify-proxy, every backend answers on its 10.0.x address and none
answers on its 172.29.x address.

Coolify generates the Traefik router and service labels itself but emits no
traefik.docker.network, and Traefik v3 with no network named reads the
address from the first network it iterates. Go randomises map iteration order,
so each proxy configuration rebuild re-rolls the choice for every container,
and any docker event rebuilds the whole configuration.

The live solmara-lab* fleet never hit this because it uses a single network
per application. The reset introduced the second one.

The fix

Name the network on the twelve routed services that join both. The value comes
from COOLIFY_RESOURCE_UUID, which Coolify exports into the environment it
runs docker compose up in, so no new operator-set variable is needed. The
:? form fails the deployment loudly rather than letting an empty value put
Traefik back on the lottery.

The five routed core services that join the ingress network alone
(static-metadata, scenario-runner, child-benefit-federator, home,
portal) have no choice to remove and stay unlabelled.

Tests

test_routed_services_on_the_runtime_network_name_the_ingress_network asserts
both halves of that rule and pins the count at twelve, so a new dual-homed
routed service cannot land unlabelled. It fails on the parent commit.

check-coolify-compose.sh and the compose-rendering tests now supply
COOLIFY_RESOURCE_UUID, which is what Coolify supplies.

just lint, just test, just compose and just relay-check pass.

Coolify puts every routed container on two networks: the application network
that carries the ingress proxy, and the private runtime network its peers
address. Traefik reads a container's address from the first network it iterates
when no network is named, and Go randomises that order, so about half of the
routed services were resolved to their 172.29.x runtime address after every
proxy configuration rebuild and answered nothing on their public route.
Restarting one container reshuffled the choice for all of them.

Name the network explicitly on the twelve routed services that join both.
Coolify exports the application uuid into the environment it runs Compose in,
and names the proxy-carrying network after it, so the label resolves without a
new operator-set variable and fails the deployment loudly if it is ever absent.

Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
@jeremi
jeremi merged commit 18143bb into main Aug 20, 2026
1 check passed
@jeremi
jeremi deleted the fix/pin-ingress-network-for-routed-services branch August 20, 2026 12:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant