Add container deployment model (ADR-020) and fix review issues

- ADR-020: Document defense-in-depth rationale for running in a minimal
  Docker container (memory-safe language + container isolation), flexible
  upstream addressing (Docker DNS, loopback, LAN, tunnel endpoints),
  file-primary logging for fail2ban, and volume mount strategy
- ADR-016: Add allow_wildcard_bind override for container deployments
  where 0.0.0.0 is correct inside the container network namespace
- operations.md: Add container deployment section with Docker Compose
  example, networking table, volume mounts, and health check integration;
  flip logging to file-primary for fail2ban reliability; note systemd as
  alternative to container deployment
- config.md: Restructure logging fields into nested LoggingConfig (matching
  TOML [logging] section), add allow_wildcard_bind, shutdown_timeout_secs,
  and log_file_path fields; clarify upstream addressing supports Docker
  DNS and tunnel endpoints; update validation rule for 0.0.0.0 override
- overview.md: Update architecture diagram for container model with Docker
  networking and volume mounts; add ADR-020 reference
- proxy.md: Clarify X-Forwarded-Proto is determined by listener port, not
  hardcoded 80/443
- ADR-013: Fix health_check_port default contradiction (default is 9900,
  not 0/disabled as previously stated)
This commit is contained in:
2026-06-11 10:10:32 +00:00
parent 346754fb2b
commit fecc385d75
8 changed files with 385 additions and 48 deletions

View File

@@ -81,36 +81,51 @@ details.
## Architecture
```
┌────────────────────────────────────┐
reverse-proxy (Rust/axum)
config.toml ───────► │ StaticConfig + DynamicConfig │
│ (ArcSwap for hot-reload) │
│ │
│ ┌─ Listener 1 ─────────────────┐ │
bind_addr_1:80 ─── │ │ HTTP → 301 redirect │ │
│ └────────────────────────────────┘ │
bind_addr_1:443 ───► │ │ TLS listener (tokio-rustls)
│ │ ├─ ACME or Manual TLS config │ │
│ │ axum router │ │
Host-based routing │ │
│ │ ├─ git.alk.dev → :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 → :8080 │ │
└─ Rate limiting, headers │ │
└────────────────────────────────┘
│ /health → 200 OK (port 9900)
└────────────────────────────────────┘
┌────────────────────────────────────┐
│ reverse-proxy container (Rust/axum)│
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) │
└────────────────────────────────────┘
│ │
┌──────┘ └──────┐
│ │
Docker network Volume mounts:
(upstream DNS) ├─ config (ro)
├─ gitea:3000 ├─ ACME cache (rw)
├─ app:8080 ├─ log dir (rw, fail2ban)
└─ admin socket (rw)
```
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
loopback, LAN, and tunnel endpoints for multi-host deployments.
## Crate Dependencies
### Core
@@ -180,6 +195,7 @@ All design decisions are documented as ADRs in [decisions/](decisions/).
| [017](decisions/017-upstream-connection-defaults.md) | Upstream connection defaults | HTTP/1.1, no redirects, connection pooling |
| [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 |
## Open Questions