Ask the Mercure hub for its health where it answers

Every E2E job has failed since 18 September with "dependency failed to start:
container pl_mail_test-mercure-1 is unhealthy". The hub was fine. Our
healthcheck was not.

dunglas/mercure is pinned to a floating tag, and the image moved its readiness
probe. "/healthz" now answers 404; `curl -f` treats a 404 as failure; the
container is marked unhealthy for ever while serving every subscription put to
it. Verified against the current image: /healthz gives 404, and
127.0.0.1:2019/mercure/health/ready gives 200 — which is the path the image's
OWN healthcheck has always used, and a container left to use it reports healthy.

Overriding the image's healthcheck with a URL of our choosing is precisely what
let the two drift apart, so the fix is to ask where it asks.

compose.yaml carried the same line, and that half was shipped. Nothing there
depends on the hub being healthy, so live updates kept working and the symptom
was an install permanently showing "(unhealthy)" in docker ps and in the
TrueNAS view — about nothing at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Paul LütznerandClaude Opus 5 committed 2026-09-21 11:38:21 +02:00
1 parent e714f568af
commit eca0f8b74d
3 files changed
+26 -2

No files matched your search

+12
View File
@@ -8,6 +8,18 @@ The published image tags: `latest` follows the most recent release below,
## Unreleased ## Unreleased
### Fixed
- **The Mercure hub reported itself unhealthy for ever while working perfectly.** Its readiness
probe moved: `/healthz` answers 404 now, `curl -f` reads that as a failure, and the container
never goes green again. On a normal install nothing waits on that, so live updates carried on
and the only symptom was `(unhealthy)` in `docker ps` and in the TrueNAS view — alarming, and
about nothing. The test stack does wait on it, so CI stopped being able to start at all.
The check now asks the hub where the hub actually answers, which is the path its own built-in
healthcheck has always used. Overriding that with a URL of our own is what let the two drift
apart in the first place.
## v0.2.29 — 2026-09-21 ## v0.2.29 — 2026-09-21
### Fixed ### Fixed
+7 -1
View File
@@ -188,7 +188,13 @@ services:
MERCURE_PUBLISHER_JWT_KEY: e2e-mercure-secret-not-for-production MERCURE_PUBLISHER_JWT_KEY: e2e-mercure-secret-not-for-production
MERCURE_SUBSCRIBER_JWT_KEY: e2e-mercure-secret-not-for-production MERCURE_SUBSCRIBER_JWT_KEY: e2e-mercure-secret-not-for-production
healthcheck: healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/healthz"] # The ADMIN endpoint, not "/healthz" on the hub port, and not a URL of
# our own choosing. The hub moved its readiness probe: "/healthz" now
# answers 404, `curl -f` treats that as failure, and the container is
# marked unhealthy for ever while serving perfectly. The image's own
# HEALTHCHECK has always used this path — overriding it with a guess is
# what let the two drift apart, and the guess is the half that rotted.
test: ["CMD", "curl", "-f", "http://127.0.0.1:2019/mercure/health/ready"]
interval: 5s interval: 5s
timeout: 5s timeout: 5s
retries: 10 retries: 10
+7 -1
View File
@@ -300,7 +300,13 @@ services:
secrets-init: secrets-init:
condition: service_completed_successfully condition: service_completed_successfully
healthcheck: healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/healthz"] # The ADMIN endpoint, not "/healthz" on the hub port, and not a URL of
# our own choosing. The hub moved its readiness probe: "/healthz" now
# answers 404, `curl -f` treats that as failure, and the container is
# marked unhealthy for ever while serving perfectly. The image's own
# HEALTHCHECK has always used this path — overriding it with a guess is
# what let the two drift apart, and the guess is the half that rotted.
test: ["CMD", "curl", "-f", "http://127.0.0.1:2019/mercure/health/ready"]
timeout: 5s timeout: 5s
retries: 5 retries: 5
start_period: 60s start_period: 60s