Resolve OQ-08 through OQ-12 after reviewing implementation findings: - OQ-08: Remove /health route from the main HTTPS listener entirely. Health checking belongs on port 9900 and admin socket only, not on the public-facing proxy. This eliminates upstream collision problems and special-case routing logic. (ADR-022) - OQ-09: Not an architectural unknown — ADR-015 already decided on a separate connect timeout. The implementation gap is a known issue. - OQ-10: Not an open question — acme_contact is already specified as required in config.md. The empty contact list is bug C2. - OQ-11: Hardcoded is_https=true is correct for a TLS-terminating proxy. HTTP listener redirects, doesn't proxy. Just needs a comment. - OQ-12: Access logging is already specified as mandatory/always-on in operations.md. Missing log_request! calls are bug W13. Updated docs: proxy.md, operations.md, overview.md, config.md, open-questions.md, README.md, ADR-013. Created ADR-022.
5.4 KiB
5.4 KiB
status, last_updated
| status | last_updated |
|---|---|
| draft | 2026-06-12 |
Reverse Proxy — Architecture
Current State
Phase 0 (Exploration) — Complete. Phase 1 (Architecture) — In progress.
This project replaces our vulnerable nginx 1.24.0 installation with a memory-safe Rust/axum reverse proxy. The primary motivation is CVE-2026-42945 (unauthenticated RCE in nginx's rewrite module) and the broader pattern of memory corruption bugs in nginx's C codebase.
The proxy supports multiple domains from initial release (git.alk.dev and alk.dev), with per-domain host-based routing and a single multi-domain SAN certificate via ACME.
Architecture Documents
| Document | Status | Description |
|---|---|---|
| overview.md | Draft | Vision, scope, crate dependencies, exports |
| proxy.md | Draft | Reverse proxy handler, request flow, header injection |
| tls.md | Draft | TLS termination, ACME, manual certs, SNI |
| config.md | Draft | TOML config format, static/dynamic split, ArcSwap reload |
| operations.md | Draft | Rate limiting, logging, health check, systemd, shutdown |
ADR Table
| ADR | Title | Status |
|---|---|---|
| 001 | Rust with Axum | Accepted |
| 002 | Custom Proxy Handler | Accepted |
| 003 | TOML Configuration Format | Accepted |
| 004 | ACME-Primary Certificate Management | Accepted |
| 005 | tokio-rustls Directly, Not axum-server | Accepted |
| 006 | Token Bucket Rate Limiting | Accepted |
| 007 | Custom Structured Log Format | Accepted |
| 008 | Static/Dynamic Config Split with ArcSwap | Accepted |
| 009 | Signal Handling Strategy | Accepted |
| 010 | Multi-Site Support in Phase 1 | Accepted |
| 011 | Multi-Domain TLS Configuration | Accepted |
| 012 | Restrict Cipher Suites to nginx Scope | Accepted |
| 013 | Health Check on Separate Local Port | Accepted |
| 014 | Unix Domain Socket Config Reload API | Accepted |
| 015 | Per-Site Upstream Timeouts with Defaults | Accepted |
| 016 | Explicit Bind Address Requirement | Accepted |
| 017 | Upstream Connection Defaults | Accepted |
| 018 | Request Body Size Limit | Accepted |
| 019 | Multi-Config Listener Support | Accepted |
| 020 | Container Deployment Model | Accepted |
| 021 | X-Forwarded-For Edge Proxy Model | Accepted |
| 022 | Health Check Scope — Local Port and Admin Socket Only | Accepted |
Open Questions
See open-questions.md for the full tracker.
| OQ | Question | Priority | Status |
|---|---|---|---|
| resolved (ADR-012) | |||
| resolved (ADR-007) | |||
| resolved (ADR-013) | |||
| resolved (ADR-014) | |||
| resolved (single bind_addr sufficient) | |||
| resolved (ADR-015) | |||
| resolved (ADR-019) | |||
/health use a less common path to avoid upstream collision? |
resolved (ADR-022: no /health route on main listener) |
||
upstream_connect_timeout_secs be enforced? |
resolved (implementation gap — ADR-015 already decides this) | ||
| resolved (already specified in config.md; implementation bug C2) | |||
X-Forwarded-Proto be derived per-listener? |
resolved (hardcoded https is correct for TLS-terminating proxy) |
||
| resolved (mandatory, always-on per operations.md) |
Document Lifecycle
| Status | Meaning | Transitions |
|---|---|---|
draft |
Under active development. May change significantly. | → reviewed when open questions are resolved |
reviewed |
Architecture is final. Implementation may begin. Changes require review. | → stable when implementation is complete |
stable |
Locked. Changes require review and may warrant an ADR. | → deprecated when superseded |
deprecated |
Superseded. Kept for reference. | Removed when no longer referenced |