PostgreSQL compose file: POSTGRES_PASSWORD is read from docker/.env, and pasted unescaped into a URL #582
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#582
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 PostgreSQL compose file against the install instructions and parsing database URLs withdjango-environ.Related to #219.
Checked again on 2026-10-01 against
mainat0a5cad587: still present.${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}is Compose interpolation. Compose resolves it from the shell and from the.envin the project directory, which with-f docker/compose.postgres.ymland no--project-directoryisdocker/; theenv_file: ../.envlines only pass variables into containers and play no part in interpolation. The documented install fills.envat the repository root and runs the command from there, so the PostgreSQL install refuses to start with a message pointing at the file the operator already filled. Separately, the password is pasted raw intoPOSTULO_DATABASE_URL, so some ordinary password characters break the URL.docker/compose.postgres.yml:28and:56(postgres://postulo:${POSTGRES_PASSWORD:?…}@db:5432/postulo),:91(thedbservice); the wiki'sInstalling-Postulo.md:57-61("SetPOSTGRES_PASSWORDin.envfirst");.env.example, which has noPOSTGRES_PASSWORDline at all..env.exampleto.envat the checkout root, addsPOSTGRES_PASSWORD, and runsdocker compose -f docker/compose.postgres.yml up -dfrom the checkout. Compose stops with "required variable POSTGRES_PASSWORD is missing a value: set POSTGRES_PASSWORD in .env". The workaround (--env-file .env, or exporting the variable) is written nowhere./or?(common inopenssl rand -base64output) makesdjango-environfail at start-up withValueError: Port could not be cast to integer value, and a%xxsequence is percent-decoded, so Postulo connects with a different password from the one thedbservice was given. (@,:and#happen to parse correctly.)dbserviceenv_file: ../.envsoPOSTGRES_PASSWORDreaches PostgreSQL from the file, and let Postulo assemble its database settings from separate variables (for examplePOSTULO_DATABASE_PASSWORDread besidePOSTULO_DATABASE_URLwithout a password), so no character needs escaping. Failing that, add--env-file .envto every documentedcompose.postgres.ymlcommand and say that the password must not need URL-encoding. AddPOSTGRES_PASSWORDto.env.example, commented, with that note. Nothing in CI orscripts/check-image.shever runs this compose file; add a CI step that runsdocker compose -f docker/compose.postgres.yml configfrom the repository root with a root.env.Done when
scripts/check-image.sh) runsdocker compose -f docker/compose.postgres.yml configfrom the repository root with only a root.envholdingPOSTGRES_PASSWORD, and succeeds; it fails today.tests/test_settings.py(or wherever database settings are tested) configures a password containing/,?and%41and asserts that the resultingDATABASES["default"]["PASSWORD"]is exactly that string.