NATS - Hardened Message Broker with JetStream
بواسطة Lynxroute
NATS 2.15.0 - CIS Level 1 hardened message broker on Ubuntu 24.04, SBOM + CIS
What is NATS
NATS® is a messaging system for connecting services, devices and edge systems, hosted by the Cloud Native Computing Foundation. The core server gives you publish/subscribe on hierarchical subjects, request/reply with automatic load balancing across queue groups, and at-most-once delivery with very low latency. JetStream, built into the same binary, adds persistence: streams that retain messages on disk, durable pull and push consumers with explicit acknowledgement and replay, plus a key-value store and an object store built on top. Client libraries exist for more than forty languages. The whole server is a single static Go binary with no database, no broker cluster and no runtime to install alongside it.
Why self-host NATS
A message bus carries everything your services say to each other - orders, events, commands, personal data in transit. Self-hosting keeps that traffic inside your own network boundary and your own jurisdiction, which matters directly for GDPR and for sector rules on personal data. It also avoids per-message and per-connection pricing that scales with how chatty your architecture is rather than with the value it delivers, and it avoids a lock-in that is unusually deep: subject names and delivery semantics propagate into every service that publishes or subscribes.
What this VM image adds
Security hardening:
- TLS required on the client port - 4222 accepts TLS only; there is no cleartext path in or out, and no second unencrypted port
- Per-instance account passwords - generated on your own VM at first boot and stored as bcrypt hashes, so no two deployments of this image share a credential
- Anonymous connections refused - no no_auth_user mapping, so an unauthenticated client is rejected at connect rather than silently mapped onto an account
- Two isolated accounts - a messaging account that owns JetStream and a separate system account for server administration; neither can reach the other's namespace
- Monitoring bound to loopback - the monitoring endpoints are unauthenticated by design, so they are bound to 127.0.0.1 and reached over an SSH tunnel instead of being published
- JetStream persisted and capped - streams are stored on the data volume rather than the upstream default under /tmp, and the storage limits are sized from your VM's own disk and memory at first boot so a runaway stream cannot fill the root volume
- CVE scan - every image is scanned for vulnerabilities with Trivy before release
- UFW firewall - only 4222 and SSH on 22 are open; cluster, gateway and leafnode ports are not configured
- fail2ban - SSH brute-force protection
- AppArmor - mandatory access control
OS hardening (CIS Level 1):
- CIS Level 1 hardened - CIS Ubuntu 24.04 LTS Level 1 Benchmark via ansible-lockdown
- auditd - system call auditing for critical paths
- SSH hardening - PasswordAuthentication disabled, key-only access
- Kernel hardening - SYN cookies, ASLR, rp_filter, TCP BBR
- /tmp as tmpfs - nosuid, nodev, noexec
- Azure IMDS endpoints - egress rules pre-configured (169.254.169.254, 168.63.129.16)
Compliance artifacts (inside the VM):
- SBOM - CycloneDX 1.6 at /etc/lynxroute/sbom.json
- CIS Conformance Report - OpenSCAP HTML at /etc/lynxroute/cis-report.html
- Tailored CIS profile - /usr/share/doc/lynxroute/CIS_TAILORED_PROFILE.md
- Per-instance TLS certificate - generated at first boot with your VM's own addresses in the SAN list, replaceable with your own PKI
Quick Start
- Deploy the VM (Standard_D2s_v3 or larger recommended)
- SSH: ssh -i key.pem <username>@<PUBLIC_IP> (username set during VM creation, default: azureuser)
- Check status: the login banner shows the version, service state and client URL
- Read the generated credentials: sudo cat /root/nats-credentials.txt - it holds both account passwords and ready-to-run client commands
- Connect a client to tls://<PUBLIC_IP>:4222 with the messaging account user and password, trusting the certificate at /etc/nats/certs/server-cert.pem
Restrict inbound 4222 to the networks that need to publish and subscribe before putting production traffic on it. This image is built and maintained by Lynxroute and is not affiliated with, endorsed by or sponsored by the Linux Foundation, the Cloud Native Computing Foundation or Synadia.