Last updated: 2026-05-14
NATS TLS Configuration
NATS is written in Go and uses Go's TLS stack, so cipher suite names follow Go's naming convention rather than OpenSSL's. The nats-server.conf format is NATS's own configuration language (similar to nginx config blocks).
NATS has three independent TLS surfaces: client connections, cluster peer connections, and leaf node connections. Each gets its own tls block.
Client TLS
Add a tls block at the top level of nats-server.conf:
tls {
cert_file: "/etc/nats/ssl/server.crt"
key_file: "/etc/nats/ssl/server.key"
ca_file: "/etc/nats/ssl/ca.crt"
verify: true
min_version: "1.2"
cipher_suites: [
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"
]
curve_preferences: [
"X25519",
"CurveP256",
"CurveP384"
]
}
Key settings:
verify: true: requires clients to present a certificate signed byca_file. Default isfalse.min_version: accepts"1.2"or"1.3".cipher_suites: applies to TLS 1.2 only. Go's TLS stack always enables TLS 1.3 when available and its ciphers are not configurable.curve_preferences: ECDH curves for key exchange.
If any client supports TLS 1.3, Go will negotiate it regardless of
cipher_suites. Setmin_version: "1.3"to enforce TLS 1.3 exclusively, only viable if all clients support it.
Cluster TLS
For peer-to-peer connections within a NATS cluster, add a tls block inside the cluster block:
cluster {
name: my-cluster
port: 6222
tls {
cert_file: "/etc/nats/ssl/server.crt"
key_file: "/etc/nats/ssl/server.key"
ca_file: "/etc/nats/ssl/ca.crt"
verify: true
min_version: "1.2"
}
routes: [
nats-route://nats1.internal:6222
nats-route://nats2.internal:6222
nats-route://nats3.internal:6222
]
}
With verify: true in the cluster block, each node must present a valid certificate, preventing unauthorized nodes from joining as cluster members.
Leaf Node TLS
For leaf nodes (extending a cluster across network or security boundaries):
leafnodes {
port: 7422
tls {
cert_file: "/etc/nats/ssl/server.crt"
key_file: "/etc/nats/ssl/server.key"
ca_file: "/etc/nats/ssl/ca.crt"
verify: true
min_version: "1.2"
}
}
Client Connections
nats CLI
nats --server tls://nats.example.com:4222 \
--tlscert /etc/nats/ssl/client.crt \
--tlskey /etc/nats/ssl/client.key \
--tlsca /etc/nats/ssl/ca.crt \
sub "my.subject"
Use the tls:// scheme in the server URL to require TLS. The nats:// scheme with TLS options will also negotiate TLS, but tls:// makes the requirement explicit.
Verification
Test the TLS handshake:
openssl s_client -connect nats.example.com:4222 -CAfile /etc/nats/ssl/ca.crt
After a successful handshake, NATS sends an INFO banner with server metadata. If TLS is required and a client connects without it, the server sends an error and closes the connection immediately.
Enable debug logging in nats-server.conf to trace TLS negotiation:
debug: true
trace: true