Files
reverse-proxy/docs/architecture/decisions/024-ansi-disabled-logging.md
glm-5.1 0d54eba41e Update architecture specs to reflect live deployment findings and fix two bugs
Architecture updates based on gaps discovered during live deployment testing:

- ADR-023: HTTP/2 client-facing support via ALPN-based protocol detection.
  The spec previously said HTTP/2 was out of scope, but the deployment
  revealed that modern browsers negotiate HTTP/2 via ALPN. The proxy now
  correctly detects the negotiated ALPN protocol and uses the appropriate
  HTTP server builder (http2::Builder for h2, auto::Builder for http/1.1).
  Upstream connections remain HTTP/1.1. Host resolution now falls back to
  URI host for HTTP/2 :authority pseudo-headers.

- ADR-024: ANSI-disabled logging. All tracing-subscriber layers now use
  with_ansi(false) to prevent ANSI escape codes in log output, which broke
  fail2ban regex matching in Docker deployments. Also documents the fail2ban
  regex anchor fix (^RATE_LIMIT → RATE_LIMIT).

Bug fixes found by architecture review:

- Fix missing ALPN protocols in manual TLS mode. build_manual_server_config
  and build_multi_domain_server_config did not set alpn_protocols, meaning
  manual TLS mode could not support HTTP/2. Added h2 and http/1.1 ALPN
  entries to both functions (acme-tls/1 only in ACME mode).

- Fix missing with_ansi(false) in JSON log format. The init_json function
  with file output did not disable ANSI on stdout or file layers, which would
  break fail2ban in production JSON logging mode.

Other spec updates:

- All document statuses updated from draft to reviewed
- proxy.md: documented Server header removal, upstream HTTPS client,
  two-phase timeout enforcement, HTTP/2 host resolution, connect timeout
- tls.md: documented ALPN configuration differing by mode (ACME vs manual)
- overview.md: added HTTP/2 client-facing support to scope, updated crate
  deps (hyper-rustls, rustls-native-certs, hyper-util), clarified out-of-scope
- config.md: fixed http_port type (u16→u32) to match implementation, added
  ANSI-disabled note for LoggingConfig
- operations.md: documented ANSI-disabled logging, fail2ban regex anchor
- open-questions.md: updated OQ-09 resolution (connect timeout fully
  implemented), OQ-10 (C2 bug is fixed)
2026-06-12 11:28:31 +00:00

53 lines
2.1 KiB
Markdown

# ADR-024: ANSI-Disabled Logging for Container Deployments
## Status
Accepted
## Context
During deployment, the proxy's log output contained ANSI escape codes (color
codes) because `tracing-subscriber`'s default `fmt::layer()` enables ANSI
output when connected to a terminal. In a Docker container, `docker logs`
captures stdout/stderr, and the log file written to
`/var/log/reverse-proxy/access.log` is also a plain text file.
ANSI escape codes in logs cause two problems:
1. **fail2ban regex failure**: The fail2ban filter regex expects plain text with
a `RATE_LIMIT` prefix. ANSI codes embedded in the log line before the prefix
break pattern matching, causing fail2ban to miss rate limit events entirely.
2. **Docker log readability**: `docker logs` output is cluttered with escape
sequences when not running in a terminal that supports them.
## Decision
All `tracing-subscriber` fmt layers now use `with_ansi(false)`:
- **File layer**: Always plain text, no ANSI codes
- **Stdout layer**: Always plain text, no ANSI codes
- **JSON layer**: Always plain text (JSON format doesn't benefit from colors)
This applies to both text and JSON log formats, in both file and stdout
destinations.
Additionally, the fail2ban regex was corrected: the `^` anchor was removed from
the `failregex` pattern because log lines have a timestamp/level prefix before
the `RATE_LIMIT` keyword. The corrected pattern matches `RATE_LIMIT` anywhere
in the line rather than only at the start.
## Consequences
**Positive:**
- fail2ban regex matching works reliably in all environments
- Log output is clean and parseable regardless of environment
- No behavioral difference between Docker, systemd, and terminal environments
**Negative:**
- Loss of color-coding in terminal output during development (acceptable
trade-off for reliability; developers can use `RUST_LOG` filtering instead)
## References
- [operations.md](../operations.md) — logging and fail2ban integration
- [ADR-007](007-custom-log-format.md) — custom structured log format
- [ADR-020](020-container-deployment.md) — container deployment model