Out of the box a node authenticates nobody: its port is plain HTTP, and every route answers any caller that can reach it. That keeps the first run to one command, and it is the first thing to change. Put one of two front doors on it (the broker’s own JWT for services, or the built-in proxy for API keys and people), keep the raft port private, and encrypt the queues whose payloads must not sit on disk in clear.
What listens where
| Port | Serves | Protected by |
|---|---|---|
6632 (PORT) |
The HTTP API, the dashboard, /health, the metrics |
Broker JWT, off by default. Plain HTTP. |
7400 (the raft address) |
Votes, log entries, snapshots, membership; a standby’s reads | QUEEN_RAFT_TOKEN, and QUEEN_LINK_TOKEN for a standby. Plain HTTP. |
| raft port + N | Raft group N | The same token. |
QUEEN_PROXY_PORT, e.g. 6711 |
The proxy: API keys, sessions, the console, /api/cp/* |
Keys and sessions; TLS with QUEEN_TLS_CERT and QUEEN_TLS_KEY. |
9092 |
The Kafka port | QUEEN_KAFKA_SASL=plain, off by default. No TLS in 2.6. |
Port 6632 never faces the internet without one of the front doors below. QUEEN_BIND_ADDR=127.0.0.1 keeps it on the host, which is wrong in Kubernetes, where probes arrive on the pod’s IP.
Broker JWT
JWT_ENABLED=true
JWT_ALGORITHM=RS256 # HS256 (default), HS384, HS512, RS256, RS384, RS512, EdDSA, auto
JWT_JWKS_URL=https://idp.example.com/.well-known/jwks.json # or JWT_PUBLIC_KEY, or JWT_SECRET for HS*
JWT_ISSUER=https://idp.example.com/
JWT_AUDIENCE=queenA token’s roles come from its role or roles claim. Each route has an access level, and the roles decide which levels a token passes:
| Level | Routes | Passes with role |
|---|---|---|
| public | /health, the metrics, the dashboard’s files, /auth/* |
none |
| read-only | listings, status, messages, groups, the DLQ, traces, KV and timer reads, reads by offset | read-only, read-write, admin |
| write-only | push, timer schedules, the ephemeral push | write-only, read-write, admin |
| read-write | everything else: pop, ack, transactions, KV writes, locks, configure | read-write, admin |
| admin | /api/v1/system/*, deletes of queues, groups and dead letters |
admin |
JWKS keys are cached and refreshed every hour, and exp, nbf and iat are checked with 30 seconds of skew. A token without exp is accepted, so issue tokens that expire. The HTTP reference has every route’s level.
API keys and people
The proxy built into the binary (QUEEN_PROXY_EMBEDDED=true) is the second front door: API keys bound to one tenant, sessions for people with a role per cluster, quotas, and TLS on a port of its own, which is the port to expose. See Tenants and API keys.
TLS
The broker port does not terminate TLS. The proxy’s port does (QUEEN_TLS_CERT, QUEEN_TLS_KEY). The Kafka port has none in 2.6, so with SASL its passwords cross the network in clear: keep it private, or terminate TLS in front of it. For anything else, terminate TLS at your ingress, with the hop to the node on a private network.
The raft token
QUEEN_RAFT_TOKEN="$(openssl rand -hex 32)" # the same value on every nodeEvery raft call carries the token, checked before the body is read. Unset, anything that reaches the raft port can vote, append entries and install snapshots. Set, it still travels in clear, so allow the raft port only from the other nodes. Rotating it is a rolling restart. With the broker’s JWT on, set it in any case: the nodes’ ephemeral hand-overs prove themselves with it, and without it ephemeral partitions that move lose their contents.
A standby reads on the same port with its own token, QUEEN_LINK_TOKEN. It opens only the log and the snapshot, but those are everything the cluster holds: guard it as you guard the data.
Encryption at rest
QUEEN_ENCRYPTION_KEY="$(openssl rand -hex 32)" # 64 hex characters, the same on every nodeThen turn encryptionEnabled on for the queues that need it. Their payloads are stored AES-256-GCM encrypted, including what transactions and timers push into them. Names, KV keys and KV values stay in clear.
Check the boot line encryption service initialized (AES-256-GCM): a missing or malformed key is silent, and the node stores flagged queues in plain text. A changed key makes the old payloads unreadable, and consumers get the ciphertext as data, with no error.
The data directory
QUEEN_RAFT_DIR holds everything a node knows: payloads (in clear unless encrypted), KV, timers, positions and, with the proxy, its users and key hashes. Treat the volume, and every snapshot of it, like a credential.
Limits
- Everything is open by default. With no JWT and no proxy, anyone who reaches port 6632 can read, delete queues and change the membership.
/metrics/prometheusis public on port 6632 and names every tenant’s queues. On the proxy’s port it needs the control-plane token.- There is no TLS between nodes, nor between a standby and its source.
- The messages a stream’s sink pushes are stored in clear, even in an encrypted queue.
To report a vulnerability, see About.