Home
Spooky is an open-source HTTP/3 (QUIC) edge reverse proxy written in Rust that terminates QUIC connections and forwards traffic to HTTP/2 backends.
Where to start
Operator — install, configure, run in production
| Document | What you'll find |
|---|---|
| Installation | Debian package, build from source, system requirements, TLS certificate layout |
| Docker | Container image, Compose bootstrap, smoke-test scripts |
| Configuration Reference | Every config key, type, default, and constraint in one place |
| TLS Setup | Certificate generation, mTLS client auth, key ownership and permissions |
| Production Deployment | Systemd unit, privilege drop, sysctl tuning, canary rollout guidance |
| Production Readiness | Canonical statement of what is production-ready today and what still blocks GA |
| Limitations | The current hard product limits, without marketing language |
Developer — understand the architecture, contribute
| Document | What you'll find |
|---|---|
| Architecture Overview | Design principles, data-plane topology, sharded ingress model |
| Component Breakdown | Per-crate responsibilities, inter-crate boundaries, key types |
| Load Balancing | All six algorithms with characteristics, use-case guidance, and config examples |
| Contributing Guide | Dev setup, build commands, test matrix, PR conventions |
Reference — config schema, API, benchmarks, changelog
| Document | What you'll find |
|---|---|
| Configuration Reference | Authoritative schema reference for every configuration block |
| Feature Matrix | Strict feature-by-feature inventory of what is done, partial, and missing |
| Security Model | Current trust boundaries, admin-plane assumptions, and missing security layers |
| Terminology | Canonical definitions for listener, upstream, backend, route, drain, and related terms |
| API Overview | Metrics endpoint, control API (health, ready, runtime), bearer auth |
| Benchmarking | Benchmark crate, micro/macro suites, and regression-gate workflow |
| Roadmap | Planned features, GA exit criteria, known limitations |
| Changelog | Version history with added, fixed, and changed entries |
Status
| Field | Value |
|---|---|
| Version | v0.3.1-beta |
| Maturity | Beta |
| License | GPLv3 |
Beta means core proxying, routing, load balancing, and health-check features are implemented and actively validated, but the project remains pre-GA — extended soak validation and broader failure-mode hardening are still in progress.
Controlled production rollout is supported. See release-maturity.md for operator expectations, environment guidance, and GA exit criteria.
Quick reference
Minimal working config
version: 1
listen:
address: "0.0.0.0"
port: 9889
tls:
cert: /etc/spooky/certs/fullchain.pem
key: /etc/spooky/certs/privkey.pem
upstream:
default:
route:
path_prefix: "/"
backends:
- id: backend1
address: "127.0.0.1:8080"
health_check:
path: "/health"
interval: 5000
Backends are verified HTTPS by default. To forward to a cleartext HTTP backend, set upstream_tls.verify_certificates: false and be aware that a warning is logged at startup. The full schema is in configuration/reference.md.
Common commands
Start the proxy:
spooky --config /etc/spooky/config.yaml
Test an HTTP/3 connection (requires curl built with HTTP/3 support):
curl --http3-only -k \
--resolve proxy.example.com:9889:127.0.0.1 \
https://proxy.example.com:9889/health
Check health and readiness (control API, default port 9902):
curl http://127.0.0.1:9902/health
curl http://127.0.0.1:9902/ready
Log levels
Spooky accepts both its own names and the standard equivalents in log.level or RUST_LOG.
| Spooky name | Standard equivalent | Verbosity |
|---|---|---|
whisper |
trace |
Everything, including internal QUIC events |
haunt |
debug |
Per-request routing, backend selection, health transitions |
spooky |
info |
Startup, shutdown, configuration summary (default) |
scream |
warn |
Recoverable errors, degraded-mode events |
poltergeist |
error |
Fatal or unrecoverable conditions |
silence |
off |
No output |
Set per-crate verbosity with RUST_LOG (e.g., RUST_LOG=spooky_edge=haunt,info). Output format is controlled by log.format: plain | json.