Files
reverse-proxy/docs/architecture/decisions/002-custom-proxy-handler.md
glm-5.1 8ee6284b62 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.
2026-06-11 07:25:50 +00:00

1.9 KiB

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
  • Felix Knorr, "Replacing nginx with axum" (felix-knorr.net/posts/2024-10-13-replacing-nginx-with-axum.html)