fix(vhosts): make SSL cert path validate and serve a real default cert#246
Merged
Conversation
Adding an SSL/Let's Encrypt vhost failed config-apply with "request failed"
because the generated haproxy.cfg references an absolute cert directory that
could not be resolved, and the placeholder certificate was not a real PEM.
Two defects fixed:
- The fallback default.pem was fabricated base64 that `haproxy -c` rejected
("too long"). Replace it with a self-signed certificate generated via
`cryptography`, written once and reused (idempotent). This lets an SSL vhost
validate before its real certificate is provisioned; SNI selects the real
cert when present and falls back to this one otherwise.
- Certificates were written per-release, but the template bakes in the
absolute path /etc/haproxy/generated/certs. The backend mounts the shared
volume at /var/lib/guard-proxy/generated, so that path did not exist during
`haproxy -c` validation. Write certs to a single shared <root>/certs
directory and alias /etc/haproxy/generated to the backend mount point so the
same shared volume resolves identically during validation and at runtime.
The shared volume layout and mounts are unchanged.
Add regression tests for default cert loadability/idempotency and the shared
certs directory layout.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adding an SSL/Let's Encrypt vhost failed
POST /config/applywith a "request failed" banner. The backend logged:Root cause — two independent defects
Both reproduced and verified against a live stack.
Fabricated default certificate. The fallback
default.pemwritten by_write_candidatewas hand-typed base64, not a real PEM. Even with the path fixed,haproxy -crejects it withunable to load certificate ... too long.Unresolvable cert path during validation. The template bakes in the absolute path
/etc/haproxy/generated/certs/, but:haproxy -cvalidation runs) mounts the sharedgenerated_configvolume at/var/lib/guard-proxy/generated, so that path does not exist there;<release>/certs/), not at the directory the template points to.Fix
default.pemviacryptography(already a dependency), written once and reused (idempotent). SNI selects the real certificate when present and falls back to this one otherwise — so an SSL vhost validates even before its Let's Encrypt certificate is provisioned.<root>/certsdirectory (not per-release), matching the absolute path baked intohaproxy.cfg./etc/haproxy/generatedto the backend mount point in the backend image sohaproxy -cresolves the same shared volume HAProxy uses at runtime.The shared
generated_configvolume and all mounts are unchanged — no change to mount points,RUNTIME_GENERATED_CONFIG_ROOT, or the HAProxy command/healthcheck.Tests
ruff check app/,mypy app/,pytest --cov— all green (393 passed).Verification
End-to-end on a live backend container: symlink resolution +
cryptography-generated default cert +haproxy -con an SSLbind→ passes. Full live deploy + real Let's Encrypt vhost test still pending (requires rebuilding the backend image on the target host).