skip to content
szczecin 53.43N 14.55E ./start-project
nuts 0.6.1 Caddy module · open source · free

bartosz@idct:~/software/nuts$ man nuts

features

NUTS turns a NATS JetStream stream into a browser-friendly, replayable event stream, with the guard rails you need to run it in production.

GET /events?topic=orders&topic=payments&topic=telemetry200 text/event-stream
EventSource · connected # sample events producers publish to JetStream · NUTS bridges · the browser subscribes with EventSource Sample JSON events streaming from NATS JetStream to the browser over Server-Sent Events.
NUTS(1)NUTS ManualNUTS(1)

STREAMING

EventSource
Real-time SSE Stream NATS messages directly to browsers with the standard EventSource API. No WebSocket bridge, no polling and no client SDK.
?topic=
Many topics per connection Subscribe to several NATS subjects in one SSE stream with repeated ?topic= parameters, or the path-based shorthand.
topic_prefix
Topic prefixing A server-side prefix lets clients use friendly names while NUTS subscribes to the fully qualified NATS subjects.
heartbeat_interval
Heartbeat keep-alives Configurable heartbeat frames keep idle connections open through proxies and CDNs.

REPLAY

stream_name
JetStream-backed durability Messages live in JetStream; NUTS only routes them to subscribers, so retention, deduplication and storage policies stay in NATS.
Last-Event-ID
Resumable streams Reconnecting clients pick up exactly where they left off with ?last-id= or the standard Last-Event-ID header, which EventSource sends for free.
replay_max_messages
Replay storm guards replay_max_messages and replay_window bound large catch-ups, so one stale client cannot drag the server through tens of thousands of old events.
slow_client
No silent message loss Slow clients are disconnected before queued messages are dropped; they reconnect with their last event ID and resume cleanly.

SECURITY

subscriber_jwt_key
JWT subscriber auth HMAC-signed JWTs with per-topic subscribe claims, read from Authorization: Bearer or a cookie for browser EventSource clients.
nats_credentials
NATS authentication Connect to NATS with a credentials file, a token or a user and password, and secure the broker independently of subscriber auth.
nats_tls_ca
NATS TLS and mTLS nats_tls_ca, nats_tls_cert and nats_tls_key encrypt and mutually authenticate the connection to NATS.
allowed_origins
CORS done right Echoes Origin from the allow-list, adds Vary: Origin and only allows credentials for listed origins: no accidental wildcard credential leaks.

OPERATIONS

nuts_*
Prometheus metrics Counters and gauges for active connections, delivered messages, slow-client disconnects, replays and rejected connections.
/livez /readyz
Liveness and readiness probes Separate probes for Kubernetes and load balancers; readiness actually checks the NATS connection and the stream.
max_connections
Connection caps Bounds concurrent SSE streams; rejected clients get 429 with Retry-After instead of degrading the whole instance.
write_timeout
Write deadlines A deadline for every SSE write keeps a stalled downstream connection from holding a handler indefinitely.
hub_url
Hub discovery An optional Link header with rel="nuts" lets clients discover the hub URL from any response that carries it.
disconnect_reason
Structured logs Every stream logs structured fields (topics, subjects, replay mode, disconnect reason), ready for log aggregation.

DEPLOYMENT

xcaddy
Caddy native A first-class Caddy module: install it with xcaddy, configure it in a Caddyfile or JSON, and inherit Caddy's TLS and routing.
idcttech/nuts
Prebuilt Docker image A multi-arch image on Docker Hub for amd64 and arm64: mount a Caddyfile and go.
docker compose
Compose-ready The repository's docker-compose.yml brings up NATS with JetStream and NUTS together for local development.

$ nuts --quick-start

Ready to wire it up?

Build it with xcaddy or pull the Docker image: you will be streaming in minutes.