Phase 1 architecture docs covering proxy handler, TLS termination (ACME + manual), TOML config with static/dynamic split (ArcSwap), and operations (rate limiting, logging, health check, systemd, graceful shutdown). Nine ADRs documenting key decisions: Rust/axum, custom proxy handler, TOML config, rustls-acme for cert management, tokio-rustls direct, token bucket rate limiting, custom log format for fail2ban, static/dynamic config split, and signal handling strategy. Includes threat landscape research documenting the nginx CVEs motivating this project.
56 lines
1.9 KiB
Markdown
56 lines
1.9 KiB
Markdown
# ADR-002: Custom Proxy Handler
|
|
|
|
## Status
|
|
|
|
Accepted
|
|
|
|
## Context
|
|
|
|
We need to implement HTTP reverse proxying — receiving requests and forwarding
|
|
them to an upstream service (Gitea on localhost:3000). Two approaches are
|
|
available:
|
|
|
|
1. **`axum-reverse-proxy` crate**: Provides path-based routing, header
|
|
forwarding, round-robin load balancing, TLS support, retry mechanisms, and
|
|
RFC 9110 compliance.
|
|
2. **Custom handler** (Felix Knorr pattern): Build a handler using hyper's
|
|
`Client` to forward requests. ~50-100 lines of Rust for our needs.
|
|
|
|
Our use case is minimal: single upstream per domain, single domain, no load
|
|
balancing, no retry, no HTTP/2 proxying.
|
|
|
|
## Decision
|
|
|
|
Implement a custom proxy handler using hyper's `Client` for request forwarding,
|
|
following the pattern demonstrated by Felix Knorr and used in the alknet
|
|
project's channel proxy.
|
|
|
|
## Rationale
|
|
|
|
- `axum-reverse-proxy` adds complexity we don't need (load balancing, retry,
|
|
path-based routing to multiple backends)
|
|
- Our proxy case is the simplest possible: match a Host header, forward the
|
|
entire request to a single upstream, stream the response back
|
|
- The Felix Knorr pattern is proven, idiomatic, and ~50-100 lines
|
|
- We maintain full control over header injection, error handling, and upstream
|
|
connection behavior
|
|
- If requirements grow, we can adopt `axum-reverse-proxy` later
|
|
|
|
## Consequences
|
|
|
|
**Positive:**
|
|
- Minimal dependencies
|
|
- Full control over proxy behavior
|
|
- Easy to understand and audit (~100 lines of proxy code)
|
|
- No unnecessary abstraction layers
|
|
|
|
**Negative:**
|
|
- We implement and maintain proxy logic ourselves (but it's trivial for our
|
|
use case)
|
|
- If requirements grow to load balancing or retry, we'd need to add that
|
|
ourselves or switch to `axum-reverse-proxy`
|
|
|
|
## References
|
|
|
|
- [proxy.md](../proxy.md)
|
|
- Felix Knorr, "Replacing nginx with axum" (felix-knorr.net/posts/2024-10-13-replacing-nginx-with-axum.html) |