Add architecture specification for Rust/axum reverse proxy

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.
This commit is contained in:
2026-06-11 07:25:50 +00:00
parent 5c54a28822
commit 8ee6284b62
17 changed files with 1819 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
# 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)