Spooky
Releases
All notable changes to Spooky, following semantic versioning. Currently in beta — see the maturity model for the GA gate criteria.
0.3.0-beta
2026-06-20Added
- HTTP/1.1 upstream transport — http:// backends are now forwarded over a pooled HTTP/1.1 connection via new H1Client and H1Pool primitives.
- Scheme-aware dispatch in the data plane — backend scheme determines transport: https:// uses HTTP/2, http:// uses HTTP/1.1.
- Mixed HTTP/1.1 and HTTP/2 backend deployments supported within the same upstream pool.
- DNS refresh client rotation wired through UpstreamTransportPool for H1 backends, matching existing H2 behavior.
- Health checks routed through the scheme-aware transport pool — http:// backends are now probed over HTTP/1.1.
- TE: trailers header added to H1 upstream requests to preserve trailer forwarding semantics.
Fixed
- Config validator no longer applies TLS trust-store checks to http:// upstreams — HTTP-only configs boot without requiring CA paths or TLS material.
Changed
- Upstream transport layer unified under UpstreamTransportPool, which dispatches by BackendTransportKind (Http1 or H2).
0.2.1-beta
2026-06-20Fixed
- ProxyError::Pool displayed as "transport error: ..." — disambiguated to "pool error: ..." so pool and transport errors have distinct display text in logs.
- Watchdog mutex poison is now logged and recovered instead of silently causing the coordinator to skip state updates — watchdog restart logic remains operational after a worker panic.
- OTLP tracing endpoint is now configurable via OTEL_EXPORTER_OTLP_TRACES_ENDPOINT or OTEL_EXPORTER_OTLP_ENDPOINT environment variables, with the resolved source logged at startup alongside the endpoint.
- validate() now returns a structured ValidationError instead of bool, making the first validation failure available to callers as a typed error value.
- take_validation_error clears the slot on read, preventing stale validation errors from leaking across test cases.
- Logger fallback error messages now include both the file path and directory path when log directory creation fails.
Changed
- validate_config call site updated to handle the new Result return type from the validator.
0.2.0-beta
2026-06-18Added
- Live listener certificate reload — certificates can be reloaded without restarting the process.
- SNI-based server certificate selection with fallback for listener TLS, plus native QUIC SNI cert selection.
- Per-upstream TLS policy override — each upstream can now specify its own TLS settings independent of the global config.
- Certificate expiry telemetry — expiry timestamps exposed for monitoring.
- Downstream handshake telemetry — TLS handshake metrics on the listener path.
- Upstream TLS failure classification — failures are now categorized (cert, SNI mismatch, timeout, etc.) in logs and metrics.
- Wildcard host pattern matching in the route index with correct precedence over exact-host routes.
- Multi-listener support — independent listener worker groups can be spawned per listener entry.
- CONNECT tunnel support — HTTP CONNECT requests are validated, translated, and lifecycle-managed over H3.
- Response trailer forwarding over H3 — upstream response trailers are now relayed to the downstream client.
- Configurable X-Forwarded-For policy — choose append vs. overwrite semantics per deployment.
- Configurable Host header forwarding policy — preserve the original downstream Host or rewrite to the upstream authority.
- Periodic backend DNS refresh loop — backends are re-resolved at runtime without restart.
- Shared DNS resolver cache with atomic update semantics.
- Backend DNS refresh configuration (performance.backend_dns_refresh_enabled, performance.backend_dns_refresh_interval_ms).
- Backend connect and rotation telemetry — metrics for DNS refresh events, connection rotation, and backend selection.
- Canonical runtime config model — a normalized intermediate config representation validated before startup.
- Cross-field normalization checks enforced at startup with classified error types.
Fixed
- H2Client::default() panicked on invalid TLS config — default construction no longer panics.
- Bootstrap response streaming lacked a running body-size cap — body size is now enforced incrementally.
- Hop-by-hop headers were not stripped from bootstrap responses.
- Ambiguous route conflicts (overlapping prefix + host combinations) are now rejected at startup.
- Backend hostnames are now validated more strictly at config load time.
- Upstream send/connect failures are classified into backend health states instead of being silently swallowed.
- SNI certificate hostnames containing whitespace are now rejected at config load.
- Route decision reasons were unstable for wildcard and trie-level routes.
- Insecure upstream TLS (verify_certificates: false) now always emits a startup warning log.
Changed
- Bootstrap forwarding policy unified into a single code path.
- Route precedence decisions made explicit in the routing layer.
- Backend health identity made explicit — health checks align with live backend resolution.
- Pooled clients are rotated when backend DNS changes are detected.
- Listener TLS material loading centralized.
0.1.1-beta
2026-05-28Added
- upstream_tls.verify_certificates: false — new config option to disable upstream TLS certificate verification, useful for backends with self-signed certs in development or trusted internal environments.
Fixed
- Upstream send errors now log the full error cause chain instead of the opaque client error (Connect), making TLS failures (missing SAN, untrusted root, cert/SNI mismatch) immediately diagnosable from logs.
- Validator no longer hard-rejects upstream_tls.verify_certificates=false; it now emits a warning and allows startup to continue.
- Debian package and systemd unit: TLS certificate files must be owned root:spooky with mode 640 so the spooky service user can read them.
Changed
- Packaging layout cleanup: Debian assets moved under packaging/deb/.
- Installation and Docker docs updated to match current packaging paths and runtime behavior.
- Debian package version bumped to 0.1.1-beta.
0.1.0-beta
2026-05-12Initial release of Spooky HTTP/3 edge proxy and load balancer.
Added
- HTTP/3 termination using quiche (RFC 9114), QUIC transport (RFC 9000), HTTP/2 backend connectivity (RFC 9113), TLS 1.3 with certificate chain loading (RFC 8446).
- TLS bootstrap ingress for HTTP/1.1 + HTTP/2 compatibility and Alt-Svc upgrade flow.
- Route matching based on path prefix and host headers with longest-match selection; method-aware matching.
- Multiple load balancing algorithms: random, round-robin, consistent hashing, least-connections, latency-aware, sticky-cid.
- Active health checking with HTTP probes — configurable interval, timeout, failure/success thresholds, and cooldown.
- Connection ID-based routing for QUIC packets with peer-based fallback for connection migration.
- Sharded ingress dispatch — per-worker UDP sockets for parallel packet processing.
- Global route-queue cap with 503 + Retry-After shedding under overload.
- Dual ingress: QUIC/HTTP3 and TCP/TLS bootstrap for browser compatibility.
- YAML-based configuration with comprehensive validation at startup.
- Structured JSON logging, request/response metrics, and QUIC connection error classification.
- Bearer token authentication on control API with metrics endpoint, health and ready probes.
- Debian package with systemd unit; Docker packaging with compose bootstrap.
- Concurrent connection handling tested at 10,000+ connections; per-backend concurrency limiting.