Image health check: answered 400 unless POSTULO_ALLOWED_HOSTS keeps 127.0.0.1, so scheduler and worker never start #580
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#580
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found on 2026-09-29 in a read-only review of postulo at
95348908d, reading the image's health check against the settings and confirming it with the test client.Checked again on 2026-10-01 against
mainat0a5cad587: still present.The image's
HEALTHCHECKaskshttp://127.0.0.1:8000/healthz, which sendsHost: 127.0.0.1:8000.CommonMiddlewarevalidates the host before any view runs, so on an instance whosePOSTULO_ALLOWED_HOSTSnames only its public host, as the install docs show, every probe is refused with 400 and the container is marked unhealthy while it serves pages normally. The scheduler and worker services wait for a healthy web container, so they never start.docker/Dockerfile:334-335(theHEALTHCHECK);config/settings/base.py:29(ALLOWED_HOSTSfrom the environment, defaultlocalhost,127.0.0.1);config/settings/prod.py:55exemptshealthzfrom the HTTPS redirect only;docker/compose.yml:74-79and:118-123,docker/compose.postgres.yml:76-83(depends_on: postulo: condition: service_healthy); the wiki'sInstalling-Postulo.md:8and:193(POSTULO_ALLOWED_HOSTS=postulo.example.org) andTroubleshooting.md:199-201;scripts/check-image.sh:33, which always runs withlocalhost,127.0.0.1.localhost,127.0.0.1in.envwith their domain, as the README and wiki instruct.400 Bad Requestand aDisallowedHosterror with its traceback is logged; Docker marks the container unhealthy.docker compose --profile scheduler up -dand--profile worker up -dwait onservice_healthyand never start, so reminders, gone-quiet notices, store copies, syncs and queued background work never run./healthz"answered 503 or did not answer at all", which sends the operator to the database.With the test client and
ALLOWED_HOSTS=["postulo.example.org"],GET /healthzwithHost: 127.0.0.1:8000returns 400; with127.0.0.1added it returns 200.GET /healthzfrom a loopbackREMOTE_ADDRbefore host validation, or have the production settings always admitlocalhostand send-H 'Host: localhost'from theHEALTHCHECK. Say in Health, metrics and logs which host the probe uses, and correct the Troubleshooting sentence. Related to #82 (closed), which fixed the HTTPS-redirect half of the same probe but not the host check.Done when
tests/test_image_build.py(or a newtests/core/test_healthz.py) requests/healthzexactly as theHEALTHCHECKdoes, underoverride_settings(ALLOWED_HOSTS=["postulo.example.org"]), and expects 200; it gets 400 today.scripts/check-image.shgains a run withPOSTULO_ALLOWED_HOSTS=postulo.example.orgthat waits for Docker's own health status to becomehealthy./healthztreats a request as forwarded only onX-Forwarded-For, so behind a loopback proxy every visitor is a "probe" #977