Resolve all architecture review findings (7 critical, 14 warnings, 6 suggestions)
Critical findings resolved: - C1: Site routing is global (per-listener TOML, global runtime lookup) - C2: X-Forwarded-For replaces (not appends) — edge proxy model (ADR-021) - C3: Hop-by-hop header handling rules specified (proxy.md) - C4: ACME failure behavior defined (tls.md) - C5: Startup sequence with fail-fast semantics (operations.md) - C6: Per-listener Router instances with shared global state (overview.md) - C7: Rate limiter adopts new params on next request, no state clear (operations.md) Warnings resolved: - W1: Admin socket wire protocol specified - W2: Host header port stripped, hostnames only in config - W3: HTTP redirect URL construction with port handling - W4: /health on HTTPS matches regardless of Host header - W5: Static config changes logged as warning during reload - W6: Reload operations serialized via Mutex - W7: http_port validation rules added (9 new rules total) - W8: upstream format validation (host:port required, no scheme) - W9: TLS error handling table (SNI, version, cipher failures) - W10: IPv6 rate limited per /64 prefix - W11: Graceful shutdown sequence specified (6 steps) - W12: Error response bodies: minimal plain text, no version disclosure - W13: upstream_scheme HTTPS uses system CA store - W14: allow_wildcard_bind is OR between config and CLI - W15: ADR-010 Phase 2 list updated (timeouts moved to Phase 1) - W17: LoggingConfig static/restart note added Suggestions applied: - S2: ConnectInfo propagation note - S3: Case-insensitive host matching (RFC 7230) - S5: Response streaming behavior (chunk-by-chunk) - S6: Token bucket nodelay semantics - S7: File watching explicitly out of scope - S8: All paths forwarded without filtering - S9: shutdown_timeout_secs referenced in shutdown description - S11: Consolidated defaults table in config.md
This commit is contained in:
@@ -86,31 +86,35 @@ details.
|
||||
config.toml ───────► │ StaticConfig + DynamicConfig │
|
||||
(volume mount) │ (ArcSwap for hot-reload) │
|
||||
│ │
|
||||
│ ┌─ Listener 1 ─────────────────┐ │
|
||||
bind_addr:80 ────► │ │ HTTP → 301 redirect │ │
|
||||
(published) │ └────────────────────────────────┘ │
|
||||
│ │
|
||||
bind_addr:443 ────► │ │ TLS listener (tokio-rustls) │ │
|
||||
(published) │ │ ├─ ACME or Manual TLS config │ │
|
||||
│ │ └─ axum router │ │
|
||||
│ │ ├─ Host-based routing │ │
|
||||
│ │ ├─ git.alk.dev → gitea:3000 │ │
|
||||
│ │ └─ Rate limiting, headers │ │
|
||||
│ └────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─ Listener N ─────────────────┐ │
|
||||
bind_addr_N:80 ───► │ │ HTTP → 301 redirect │ │
|
||||
│ └────────────────────────────────┘ │
|
||||
│ │
|
||||
bind_addr_N:443 ───► │ │ TLS listener (tokio-rustls) │ │
|
||||
│ │ ├─ Manual TLS cert │ │
|
||||
│ │ └─ axum router │ │
|
||||
│ │ ├─ alk.dev → app:8080 │ │
|
||||
│ │ └─ Rate limiting, headers │ │
|
||||
│ └────────────────────────────────┘ │
|
||||
│ │
|
||||
│ /health → 200 OK (port 9900) │
|
||||
└────────────────────────────────────┘
|
||||
│ ┌─ Listener 1 ─────────────────┐ │
|
||||
bind_addr:80 ────► │ │ HTTP → 301 redirect │ │
|
||||
(published) │ └────────────────────────────────┘ │
|
||||
│ │
|
||||
bind_addr:443 ────► │ │ TLS listener (tokio-rustls) │ │
|
||||
(published) │ │ ├─ ACME or Manual TLS config │ │
|
||||
│ │ └─ axum router (per-listener) │ │
|
||||
│ │ ├─ /health → 200 OK (any) │ │
|
||||
│ │ ├─ Host → global site lookup │ │
|
||||
│ │ ├─ git.alk.dev → gitea:3000 │ │
|
||||
│ │ └─ Rate limiting, headers │ │
|
||||
│ └────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─ Listener N ─────────────────┐ │
|
||||
bind_addr_N:80 ───► │ │ HTTP → 301 redirect │ │
|
||||
│ └────────────────────────────────┘ │
|
||||
│ │
|
||||
bind_addr_N:443 ───► │ │ TLS listener (tokio-rustls) │ │
|
||||
│ │ ├─ Manual TLS cert │ │
|
||||
│ │ └─ axum router (per-listener) │ │
|
||||
│ │ ├─ /health → 200 OK (any) │ │
|
||||
│ │ ├─ Host → global site lookup │ │
|
||||
│ │ ├─ alk.dev → app:8080 │ │
|
||||
│ │ └─ Rate limiting, headers │ │
|
||||
│ └────────────────────────────────┘ │
|
||||
│ │
|
||||
│ /health → 200 OK (port 9900) │
|
||||
│ Admin socket (Unix domain) │
|
||||
└────────────────────────────────────┘
|
||||
│ │
|
||||
┌──────┘ └──────┐
|
||||
│ │
|
||||
@@ -121,6 +125,13 @@ details.
|
||||
└─ admin socket (rw)
|
||||
```
|
||||
|
||||
Each listener has its own `axum::Router` instance with its own middleware stack,
|
||||
but all routers share `Arc<ArcSwap<DynamicConfig>>` and
|
||||
`Arc<Mutex<HashMap<IpAddr, TokenBucket>>>` via axum State. Site routing is
|
||||
global: the `Host` header is matched against a single routing table collected
|
||||
from all listeners' site definitions. Hostnames must be unique across all
|
||||
listeners — see C1 resolution in the architecture review.
|
||||
|
||||
In container deployments (ADR-020), the proxy runs in a minimal container with
|
||||
`0.0.0.0` bind address and Docker port publishing. Upstream addresses use Docker
|
||||
DNS names for same-host containers (e.g., `gitea:3000`) but also support
|
||||
@@ -196,6 +207,7 @@ All design decisions are documented as ADRs in [decisions/](decisions/).
|
||||
| [018](decisions/018-body-size-limit.md) | Request body size limit | 100 MB default matching nginx, Gitea push compatibility |
|
||||
| [019](decisions/019-multi-config-listeners.md) | Multi-config listeners | `[[listeners]]` supporting both dedicated-IP and shared-IP deployment models |
|
||||
| [020](decisions/020-container-deployment.md) | Container deployment model | Defense-in-depth via container isolation; file-primary logging; flexible upstream addressing |
|
||||
| [021](decisions/021-x-forwarded-for-edge-proxy.md) | X-Forwarded-For edge proxy model | Replace, don't append — proxy is the edge, no trusted upstream proxies |
|
||||
|
||||
## Open Questions
|
||||
|
||||
|
||||
Reference in New Issue
Block a user