Install NATS Server v2.15.1 on Ubuntu with the official Linux binary or a matching Debian package, validate a configuration in /etc/nats-server.conf, then run it as an unprivileged, hardened systemd service. Before exposing port 4222, configure authentication; add TLS for encrypted transport and a JetStream store_dir when messages must survive a restart.
Need a server to try this on? Antihost offers Linux VPS plans with NVMe storage, full root access and a 14-day free trial.
What you are installing
NATS Server is a lightweight messaging server. Core NATS delivers subjects in memory, while JetStream adds persistence, replay and retention controls. The current official release identified for this guide is v2.15.1, released October 9, 2026. Use that version, or another deliberately selected release, rather than allowing a production installation to follow an unpinned latest channel.
As an Amazon Associate I earn from qualifying purchases.
A normal Ubuntu deployment has four layers:
- the
nats-serverexecutable; - a restricted configuration file;
- a dedicated
natsservice account and, for JetStream, a writable data directory; - a
systemdunit that starts the server at boot, restarts it after failure and limits its privileges.
Port 4222 is the client listener. Port 8222 is the optional HTTP monitoring endpoint and should be reachable only from a controlled administrative network. Never expose an unauthenticated listener to an untrusted network.
Choose an installation method
| Method | Best use | Important consideration |
|---|---|---|
| Official Linux installer | Fast installation on a supported Linux architecture | The command tracks latest unless you replace it with a pinned versioning strategy. |
| Versioned Debian package | Production hosts that need an explicitly recorded release and package-managed installation | Select the package matching the host architecture and verify its release-page checksum. |
The official download page provides Debian assets for amd64, arm64, arm6, arm7 and 386. Check the machine architecture before downloading a package:
#1 Best Overall
dpkg --print-architecture
uname -m
For a production rollout, record the selected NATS release, retain the downloaded package or binary, and verify the checksum published with that release. The installer examples below are convenient for a test or a host where you control version pinning separately.
Install NATS Server
Install with the official Linux script
Run the installer as your normal administrator, then place the resulting executable in a system-wide path:
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11curl -sf https://binaries.nats.dev/nats-io/nats-server/v2@latest | sh
sudo install -m 0755 nats-server /usr/local/bin/nats-server
nats-server --version
The final command must report the release you intended to deploy. If it reports a different version, stop and correct the binary before creating the service. For a pinned production installation, obtain the versioned release asset, verify its checksum, and install that artifact instead of silently following latest.
Install a Debian release asset
Download the .deb that matches the output of dpkg --print-architecture from the official NATS release page. Install it with Ubuntu’s package tooling, then verify the executable:
sudo apt install ./nats-server_<version>_<architecture>.deb
nats-server --version
Replace the angle-bracketed portions with the exact filename you downloaded. Do not install an arm64 package on an amd64 host, and do not treat a package’s filename as proof of authenticity: compare its checksum with the value published for that release.
Perform a safe first run
Before creating a service, run the server in the foreground to confirm that the binary starts on the host:
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →nats-server
By default, clients connect to port 4222. Stop the foreground process with Ctrl+C after the smoke test. To add the monitoring endpoint for development or a controlled administrative network, use:
nats-server -m 8222
Monitoring is an access decision separate from messaging. Keep 8222 behind a firewall or management network; it is not a replacement for authentication on the client listener.
Rank #2
You can also test JetStream temporarily without a configuration file:
nats-server -js
The -js switch is useful for a short-lived test. Persistent deployments should put JetStream storage in an explicit configuration block and run under the service account described below.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Create the service account and directories
Do not run a long-lived NATS process as root. Create a system account with no interactive shell, install the configuration with restricted ownership, and create the JetStream directory with matching ownership:
sudo useradd --system --home /nonexistent --shell /usr/sbin/nologin nats
sudo install -d -o nats -g nats -m 0750 /var/lib/nats/jetstream
sudo install -o root -g nats -m 0640 /dev/null /etc/nats-server.conf
If the nats account already exists, keep it and verify that the data directory is owned by that account. The configuration can contain passwords and private-key paths, so limit read access to root and the service group. Private TLS keys should be more restrictive still, normally readable only by root and the NATS process.
Write and validate /etc/nats-server.conf
Start with a local listener while you are building the configuration. This example enables persistent JetStream but leaves monitoring commented out:
listen: "127.0.0.1:4222"
# Uncomment only for controlled local monitoring.
# http: 8222
jetstream {
store_dir: "/var/lib/nats/jetstream"
}
NATS configuration syntax accepts comments, either = or : assignments, arrays and maps. Validate every change before asking systemd to load it:
sudo nats-server -t -c /etc/nats-server.conf
A successful validation checks syntax without starting the service. It does not prove that a certificate exists, a port is free, or that the service account can write to the JetStream path; those checks still belong in the startup and verification steps.
Enable authentication before network exposure
A bare NATS server has security disabled by default. For a small, centrally managed installation, define users in the authorization block:
authorization {
users: [
{ user: app, password: "replace-with-a-long-secret" }
]
}
Replace the example secret with a long, unique value, protect the configuration file, and restart the server after changing it. Do not put a real password in a script, ticket or shell history merely to make a demonstration convenient.
This approach keeps the full user list in the server configuration. The official authentication guidance describes that model as centralized authentication. It is practical for a small number of clients, but it becomes awkward when separate accounts, delegated administration or frequent credential rotation are required. Larger or more distributed deployments should use the NATS credentials/JWT model, which separates account and user administration from a single static user list.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →| Authentication choice | When it fits | Operational trade-off |
|---|---|---|
Users in authorization |
Small, centrally managed server with a short user list | Every user and password change requires editing and protecting the server configuration. |
| NATS credentials/JWTs | Multiple accounts, delegated administration or larger deployments | Introduces credential and signing-key administration, but improves account isolation and rotation workflows. |
Authentication answers who may connect. It does not encrypt the connection; use TLS when traffic can cross an untrusted network.
Configure TLS for encrypted client connections
Add a TLS block to the server configuration and listen on the address clients will use:
listen: "0.0.0.0:4222"
tls {
cert_file: "/etc/nats/certs/server-cert.pem"
key_file: "/etc/nats/certs/server-key.pem"
ca_file: "/etc/nats/certs/ca.pem"
timeout: 2
}
Before starting, check all of the following:
- The certificate’s Subject Alternative Name includes the hostname clients actually use. A certificate for an unrelated name will fail hostname verification even when the server is running.
- The NATS process can read the certificate and private key, while unrelated users cannot read the key.
- The CA file contains the issuing trust chain required by your clients.
- Firewall rules expose 4222 only where clients need it.
Validate the file before launch:
sudo nats-server -t -c /etc/nats-server.conf
When TLS is required, a plaintext client is refused during the handshake. Test with the same CA and hostname that production clients will use; a test that disables certificate verification can hide a SAN or trust-chain error. TLS protects data in transit, while authentication still controls access and JetStream encryption at rest is a separate configuration concern.
Make JetStream persistence intentional
JetStream is built into nats-server. The temporary -js flag enables it for a process, but a persistent service needs a jetstream block:
Recommended Free Tools
jetstream {
store_dir: "/var/lib/nats/jetstream"
}
The store_dir value is the directory used for file-based JetStream storage. Create it before starting the service:
sudo install -d -o nats -g nats -m 0750 /var/lib/nats/jetstream
Use fast local storage sized for the retention policy and expected workload. Persistence is not a backup: plan snapshots, replication and recovery separately when the data is important. The service account must be able to create and modify files below /var/lib/nats/jetstream, and the systemd unit must explicitly permit writes there.
Rank #4
| Mode | Delivery behavior | Storage implication |
|---|---|---|
| Core NATS | Ephemeral subject delivery while subscribers are connected | No JetStream data directory is required. |
| JetStream | Persistence, replay and retention controls | Requires intentional local storage, filesystem permissions and capacity planning. |
Run NATS as a hardened systemd service
Create /etc/systemd/system/nats-server.service. Adapt the binary path if you installed it somewhere other than /usr/local/bin/nats-server:
[Unit]
Description=NATS Server
After=network-online.target
[Service]
Type=simple
User=nats
Group=nats
ExecStart=/usr/local/bin/nats-server -c /etc/nats-server.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s SIGUSR2 $MAINPID
Restart=on-failure
RestartSec=5
LimitNOFILE=800000
NoNewPrivileges=true
ProtectSystem=strict
PrivateTmp=true
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
ReadWritePaths=/var/lib/nats
[Install]
WantedBy=multi-user.target
The important operational properties are an unprivileged user, restart-on-failure, a high file-descriptor limit for connection-heavy workloads, and an explicit writable JetStream path. ProtectSystem=strict makes the filesystem read-only to the service except for paths granted by ReadWritePaths. Keep the hardening controls from the official service material when adapting the unit; if you add another writable directory, declare it deliberately rather than weakening the entire sandbox.
Free tools Windows power users keep installed
One-click scans. No signup required.
Load the unit, enable it for boot and inspect both status and logs:
sudo systemctl daemon-reload
sudo systemctl enable --now nats-server
sudo systemctl status nats-server
sudo journalctl -u nats-server -e
For a configuration change, validate first, then reload or restart according to the setting and your maintenance plan. If the process exits repeatedly, journalctl -u nats-server usually identifies a syntax error, missing certificate, occupied port or filesystem permission problem.
| Foreground process | systemd service |
|---|---|
| Useful for a local smoke test and immediate console output | Starts at boot, records logs in the journal and restarts after failure |
| Usually runs with the shell user’s privileges | Can run as the dedicated nats user with filesystem and namespace hardening |
| Stops when the terminal or process supervisor ends | Provides explicit storage permissions and lifecycle controls |
Install and use the NATS CLI
The CLI provides publish/subscribe checks plus JetStream, key-value, object-store, service, monitoring and context-management operations. Install it with the official Linux installer and place it on the system path:
curl -sf https://binaries.nats.dev/nats-io/natscli/nats@latest | sh
sudo install -m 0755 nats /usr/local/bin/nats
Pin the CLI version for repeatable production operations. Create a named context instead of repeatedly embedding connection details:
nats context add localhost --description "Localhost"
For an authenticated server, configure the context with credentials through the CLI’s prompts or credential options. Avoid placing passwords directly in a shell command that will be saved in history.
With a local test listener, verify basic publish/subscribe behavior:
Best Value
nats sub hello &
nats pub hello "Hello NATS!"
The subscriber should print the published message. Run the same test through the authenticated or TLS-enabled context used by a real client; a successful unauthenticated local test does not prove that production access controls are correct.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Verify a production-style deployment
- Confirm the binary: run
nats-server --versionand check that it reports the intended release. - Validate configuration: run
sudo nats-server -t -c /etc/nats-server.confbefore every rollout. - Check the service: confirm
systemctl is-active nats-serverreturnsactive, then inspectjournalctl -u nats-serverfor a ready server. - Test client access: publish and subscribe through a context that uses the configured authentication and, where applicable, TLS.
- Check JetStream: use the NATS CLI to inspect the configured streams and confirm that files are created only below the selected
store_dir. - Test TLS enforcement: connect with the real CA and hostname, then verify that a plaintext connection is rejected when TLS is required.
- Review monitoring exposure: keep port 8222 limited to the administrative network, even when client authentication is enabled.
Troubleshoot common failures
The service fails immediately with a configuration error
Run the exact file through sudo nats-server -t -c /etc/nats-server.conf. Check punctuation, quoted paths and block braces. A configuration that validates under one path but is not the file named in ExecStart will not fix the service; inspect the unit and journal together.
JetStream reports a permission or write error
Check that /var/lib/nats/jetstream exists, is owned by nats:nats, and has mode 0750 or stricter as appropriate. Confirm that ReadWritePaths=/var/lib/nats is present in the hardened unit. Do not solve a single-directory problem by removing ProtectSystem=strict.
Clients cannot connect to port 4222
Use systemctl status nats-server and the journal to determine whether the listener failed to bind, the process is restarting, or a firewall blocks the port. A listener on 127.0.0.1 accepts only local clients; change it to an appropriate address only after authentication and firewall rules are in place. Also check for another process already using 4222.
TLS clients fail during the handshake
Verify that the client trusts the configured CA, that the certificate SAN matches the hostname in the client URL, and that the key and certificate paths are readable by the service account. A plaintext client is expected to fail when the listener requires TLS. Test with the real hostname rather than an IP address unless the IP is included in the certificate SAN.
Authentication fails after a configuration edit
Confirm that the client is using the intended context and credentials, not an old cached context. Check the username and password for accidental whitespace, protect the configuration file, validate it, and restart or reload the service according to your change procedure. If you have outgrown a single static user list, plan a migration to NATS credentials/JWTs rather than adding more shared passwords.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsThe monitoring endpoint is unexpectedly exposed
Search the effective configuration for http: 8222 and inspect firewall rules and listening sockets. Remove the endpoint when it is not required, or bind and firewall it so that only the administrative network can reach it. Monitoring access should be reviewed independently of client authentication.
Updates, recovery and operational choices
Pin versions and rehearse upgrades
Record the NATS Server and CLI versions deployed on each host. Test a new binary against a copy of the configuration, run the configuration validator, and review the journal after restarting the service. Do not let an unattended script replace a production binary merely because an installer still serves latest.
Protect JetStream data
Choose local storage that can handle the retention policy and throughput, monitor free space, and include /var/lib/nats/jetstream in your backup and recovery design when the data is valuable. A service restart tests process recovery; it does not test restoration from a lost disk. Replication and backups should be designed to match the durability requirement rather than assumed from the presence of a store_dir.
Choose the right process model
A foreground process is appropriate for a quick local smoke test or when another supervisor deliberately owns the lifecycle. On an Ubuntu server, the hardened systemd unit is the operational baseline because it combines boot activation, journal logging, restart behavior, privilege isolation and explicit storage permissions.
Quick Recap
Final deployment checklist
- The installed binary reports the recorded NATS release.
- The configuration passes
nats-server -tbefore rollout. - The service runs as
nats, not asroot, and starts withsystemctl enable --now nats-server. - Port 4222 is protected by authentication and, where required, TLS.
- Certificate SANs match the hostnames clients use, and private keys have restricted permissions.
- JetStream has an intentional
store_dirowned by the service account and covered by the systemd write allowance. - Client publish/subscribe tests succeed through the intended authenticated context.
- Port 8222 is disabled or limited to an administrative network.
- Logs, storage capacity, backups and version-pinned upgrade procedures are part of normal operations.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




