Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Install NATS Server 2.15.1 on Ubuntu with the official Linux installer or a matching Debian package, then run it as an unprivileged systemd service. A production-ready setup also needs a protected configuration file, authentication, TLS when traffic leaves the host, and an intentional JetStream storage directory.
Need a server to try this on? Antihost offers Linux VPS plans with NVMe storage, full root access and a 14-day free trial.
This guide walks from a local smoke test to a hardened service. NATS Server 2.15.1 was released on October 9, 2026; pin that version, or another version you have approved, rather than silently following latest in production.
As an Amazon Associate I earn from qualifying purchases.
Free tools Windows power users keep installed
One-click scans. No signup required.
Choose an installation method and architecture
The official NATS download page lists NATS Server v2.15.1 for 2026. Debian assets are available for amd64, arm64, arm6, arm7, and 386, so select the package that matches Ubuntu’s CPU architecture. Check the architecture with dpkg --print-architecture before downloading a .deb.
A Debian package fits hosts where package inventory and a versioned artifact are important. Download the asset for the architecture reported by Ubuntu, verify its checksum against the release page, and install it through your normal local-package workflow. Keep a record of the exact filename and version so a later upgrade is reproducible. The package route and the binary installer both produce a nats-server executable; choose one path and keep the systemd unit’s ExecStart path consistent with it.
#1 Best Overall
For a quick Linux installation, the official installer downloads the current binary from binaries.nats.dev:
curl -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 command ending in @latest is convenient for a lab, but it can change without a configuration review. In production, use a versioned release asset, record the selected release, and verify its checksum against the official release page before installing it. Keep the binary at a stable path such as /usr/local/bin/nats-server so the systemd unit does not change when you upgrade.
Recommended Free Tools
Confirm the binary before configuring the service
Run:
nats-server --version
Confirm that the output is the release you intended. If the command is not found, check that /usr/local/bin is in the service and administrator PATH, or invoke the full path while troubleshooting.
Run a safe local smoke test
Before adding systemd, verify that the server starts and that a client can exchange a message. A foreground server uses the default client listener on TCP port 4222:
nats-server
Leave that process running in one terminal. Install the NATS CLI from the official installer if it is not already present:
curl -sf https://binaries.nats.dev/nats-io/natscli/nats@latest | sh
sudo install -m 0755 nats /usr/local/bin/nats
nats context add localhost --description "Localhost"
In another terminal, run a subscriber and then publish a message:
nats sub hello &
nats pub hello "Hello NATS!"
The subscriber should print the published message. Stop the foreground server with Ctrl+C after the test. For a temporary JetStream test, start it with:
nats-server -js
Do not bind an unauthenticated test listener to an address reachable by untrusted clients. The default port is suitable for a local-only smoke test; network exposure requires authentication, firewall policy, and usually TLS.
Create the Ubuntu configuration file
Create a dedicated configuration at /etc/nats-server.conf. A minimal configuration can listen only on loopback and reserve a persistent JetStream directory:
listen: "127.0.0.1:4222"
# Uncomment only for controlled administrative access.
# http: 8222
jetstream {
store_dir: "/var/lib/nats/jetstream"
}
NATS configuration accepts comments, either = or : assignments, arrays, and maps. This lets you format a file for readability, but consistency matters during reviews. Keep one authoritative file for the service rather than mixing command-line flags and configuration values that can drift apart.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsRank #2
Create the storage path before starting a service account:
sudo install -d -o nats -g nats -m 0750 /var/lib/nats/jetstream
If the nats account does not exist yet, create it before running that command:
sudo useradd --system --home /nonexistent --shell /usr/sbin/nologin nats
Keep the configuration readable only by root and the service group. For example:
sudo chown root:nats /etc/nats-server.conf
sudo chmod 0640 /etc/nats-server.conf
Validate syntax before every rollout:
sudo nats-server -t -c /etc/nats-server.conf
A successful validation is necessary but does not prove that certificates, directories, ports, or credentials are usable. Those need a service-start and client test as well. Make the syntax check part of your change procedure, before replacing a running service, so a typo cannot turn a routine restart into an outage.
Enable authentication before network exposure
A bare NATS server has security disabled by default. For a small, centrally managed deployment, put users in an authorization block:
authorization {
users: [
{ user: app, password: "generated-secret-value" }
]
}
Replace the illustrative value with a long, randomly generated secret, and keep the file protected because anyone who can read it can obtain client credentials. Start the configured server with:
sudo nats-server -c /etc/nats-server.conf
Centralized users are straightforward when one team manages a small server. They become harder to operate as accounts, tenants, and rotation requirements grow. The NATS credentials/JWT model is a better fit when you need account isolation, delegated administration, or credentials that can be rotated without maintaining one large static user list.
| Authentication approach | Best fit | Operational trade-off |
|---|---|---|
Users in authorization |
Small deployment with a central administrator | Simple configuration, but every user and password is maintained in the server file |
| NATS credentials and JWTs | Multiple accounts, teams, or delegated administration | More moving parts, but stronger account separation and easier distributed credential management |
Do not put passwords directly into shell history when creating CLI contexts. Prefer a credentials file or another protected mechanism supported by your client tooling. After changing centralized credentials, validate the file, restart deliberately, and test both an authorized client and a client that should be rejected. This catches accidental spelling or context errors before an application rollout.
Add TLS for encrypted client connections
TLS protects the connection between clients and the server; it does not replace authentication. Configure the certificate, private key, certificate authority, and handshake timeout in the server configuration:
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
}
Use a certificate whose Subject Alternative Name (SAN) contains the hostname clients actually use. A certificate for an internal name will not validate when clients connect by IP or a different DNS name. Restrict the private key:
sudo chown root:nats /etc/nats/certs/server-key.pem
sudo chmod 0640 /etc/nats/certs/server-key.pem
Adjust ownership and mode to match the account that must read the key, while ensuring unrelated users cannot read it. Validate the complete configuration:
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 skips certificate verification can hide SAN or trust-chain errors. TLS encrypts data in transit. Encryption of JetStream data at rest is a separate configuration and storage decision. Plan certificate renewal as an operational task: replace the files with correct permissions, validate the configuration, and reload or restart in a maintenance window while watching the journal.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC 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 & 11Make JetStream persistence deliberate
JetStream is built into nats-server. The -js switch is useful for a temporary run, but a persistent service should declare a jetstream block with an explicit store_dir:
jetstream {
store_dir: "/var/lib/nats/jetstream"
}
The directory is where file-based JetStream storage is kept. Choose fast local storage that can support the retention and replication requirements of your streams, and monitor available capacity. The service account must own the directory and be able to write to it; the systemd unit should grant write access only to that path.
After the service is running, use the CLI’s JetStream commands to list or inspect streams, then confirm that files are created only under the selected store directory. For example:
nats stream ls
nats stream info EVENTS
Replace EVENTS with the stream name you created. Core NATS and JetStream solve different delivery problems:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
| Capability | Core NATS | JetStream |
|---|---|---|
| Delivery model | Ephemeral publish/subscribe; messages are not retained for a disconnected subscriber | Messages can be stored and delivered later |
| Replay | Not available after delivery | Supported from retained stream data |
| Retention and limits | No server-side message store | Configured by stream policy, limits, and available storage |
| Operational concern | Listener and client security | All of those concerns plus disk capacity, permissions, and recovery planning |
Persistence is not a backup. Include the JetStream directory in a tested backup and recovery plan appropriate to your retention policy, and avoid placing it on a filesystem that can fill the root volume unexpectedly. Before enabling a stream, estimate message volume and retention duration, then leave headroom for bursts and recovery operations. A service can be healthy while applications eventually fail because the storage filesystem has no free blocks or inodes.
Create a hardened systemd service
Run NATS as the unprivileged nats account rather than root. Create /etc/systemd/system/nats-server.service with the binary path and configuration path used on your host:
[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 hardened properties reduce the damage a compromised process could cause: NoNewPrivileges blocks privilege elevation, ProtectSystem=strict makes most of the filesystem read-only, PrivateTmp isolates temporary files, and RestrictAddressFamilies limits networking families. ReadWritePaths explicitly reopens only the JetStream data path for writing. Preserve these controls when adapting the unit, but verify that any additional certificate, log, or data directory is readable or writable as required.
LimitNOFILE=800000 gives the server a high file-descriptor ceiling suitable for many connections and streams; retain an intentionally chosen value rather than copying it without considering host limits. If the service cannot read a certificate or configuration after sandboxing, fix ownership or add only the narrowly required read path instead of removing ProtectSystem wholesale.
Rank #4
If you installed the binary elsewhere, change ExecStart to the actual path. Then load, enable, and start the unit:
sudo systemctl daemon-reload
sudo systemctl enable --now nats-server
sudo systemctl status nats-server
sudo journalctl -u nats-server -e
enable --now both starts the service immediately and schedules it for boot. Restart=on-failure restarts unexpected exits after five seconds, while the journal remains the first place to inspect configuration, permission, and certificate errors. When changing the unit, run daemon-reload again and check the rendered settings with systemd’s status output before restarting.
Foreground process versus systemd
| Concern | Foreground process | systemd service |
|---|---|---|
| Restart behavior | Manual restart after an exit | Automatic restart on failure |
| Privilege isolation | Depends on how the command was launched | Dedicated user, group, and sandbox controls |
| Logging | Terminal output unless redirected | Persistent inspection through journalctl |
| Boot activation | Not automatic | Enabled with systemctl enable |
| Storage permissions | Depends on the launching account | Explicit account and ReadWritePaths policy |
Configure the NATS CLI safely
The CLI supports named contexts as well as JetStream, key-value, object-store, service, monitoring, and context-management operations. Install it with the official Linux installer, pinning a version for production just as you do for the server:
curl -sf https://binaries.nats.dev/nats-io/natscli/nats@latest | sh
sudo install -m 0755 nats /usr/local/bin/nats
nats context add localhost --description "Localhost"
nats pub hello "Hello NATS!"
For an authenticated or TLS-protected server, create a context that points to the configured URL and uses protected credentials. Avoid embedding a password in a command that will be stored in shell history. Keep separate contexts for development and production so an inspection or publish command cannot accidentally target the wrong cluster. Pin the CLI as well as the server: a changing command-line client can alter automation output or behavior even when the server binary remains fixed.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Verify the complete installation
Run these checks in order after installation and after every configuration change:
- Version: run
nats-server --versionand confirm the intended release. - Syntax: run
sudo nats-server -t -c /etc/nats-server.confbefore restarting. - Service state: confirm
systemctl is-active nats-serverreturnsactive, then inspectjournalctl -u nats-server -efor a ready server. - Client authorization: use an authenticated CLI context to publish and subscribe; an unauthenticated context should not be accepted when authorization is enabled.
- JetStream: list or inspect a stream with the CLI and verify that data files appear only below the configured
store_dir. - TLS: connect with the production CA and hostname, confirm certificate validation, and verify that a plaintext connection is rejected when TLS is required.
- Monitoring exposure: if
http: 8222is enabled, confirm that port 8222 is reachable only from the administrative network.
Troubleshoot common failures
The service exits immediately
Run the syntax test manually and read the unit journal:
sudo nats-server -t -c /etc/nats-server.conf
sudo journalctl -u nats-server -b --no-pager
Typical causes are a typo in the configuration, an incorrect ExecStart path, or a port already in use. Check listeners with the operating system’s socket tools and stop the competing process or choose an intentional alternative. A foreground launch using the same configuration can expose a clearer error, but stop it before starting systemd so two processes do not compete for port 4222.
JetStream reports a storage or permission error
Check the directory, owner, mode, and the unit’s writable-path policy:
sudo ls -ld /var/lib/nats /var/lib/nats/jetstream
sudo -u nats test -w /var/lib/nats/jetstream
The directory must exist, be owned by the service account, and be included in ReadWritePaths when ProtectSystem=strict is active. Also check free space and inode availability; a full filesystem prevents new retained messages even when permissions are correct.
Clients cannot connect after enabling TLS
Confirm that clients use the TLS listener, trust the configured CA, and connect with a hostname present in the certificate SAN. A plaintext client will be refused by design. If the server cannot read the private key, correct the key’s ownership and mode without making it world-readable.
Best Value
Authentication fails
Ensure the client is using the context and credentials intended for this server, not an older context pointing elsewhere. Recheck the exact username and secret in the authorization block, then restart only after the configuration validation succeeds. If many accounts or frequent rotation are required, migrate from a static user list to the NATS credentials/JWT model rather than accumulating secrets in one file.
Monitoring is unexpectedly exposed
The monitoring endpoint is separate from the client listener. If you enabled http: 8222, bind or firewall it so only an administrative network can reach it. Do not treat monitoring access as harmless merely because client authentication is configured.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOperational baseline for Ubuntu
- Pin and record the server and CLI versions used in production; verify checksums for versioned release assets.
- Run as the dedicated
natsuser and retain systemd sandbox controls. - Keep
/etc/nats-server.confand TLS private keys restricted. - Require authentication before binding to a shared or public network.
- Use TLS for traffic that crosses host or trust boundaries, with a SAN matching the client hostname.
- Choose a dedicated JetStream store directory, monitor capacity, and test recovery.
- Restrict port 8222 to an administrative network.
- Validate configuration before every restart and confirm service, client, JetStream, and TLS behavior afterward.
Frequently Asked Questions
What is the current NATS Server version for this Ubuntu guide?
The official release listed for this guide is NATS Server v2.15.1, released October 9, 2026. Pin the version used in production and verify a versioned artifact’s checksum rather than tracking latest silently.
Which Ubuntu architecture package should I download?
Run dpkg --print-architecture and select the matching Debian asset. The release page lists amd64, arm64, arm6, arm7, and 386 packages.
Can I run NATS without a configuration file?
Yes. Running nats-server starts a foreground server on the default client port, 4222, and nats-server -js enables a temporary JetStream run. A persistent or network-exposed installation should use a protected configuration file and systemd unit.
Is NATS authenticated by default?
No. A bare server has security disabled. Add an authorization block for a small centrally managed deployment, or use the NATS credentials/JWT model when you need account isolation, delegated administration, or larger-scale credential rotation.
Recommended Free Tools
How do I enable JetStream persistence?
Add a jetstream block with an explicit store_dir, create that directory for the nats service account, and grant the systemd unit write access only to it. The -js option alone is better suited to a temporary test.
Why does a TLS client fail even though the server is running?
Check that the client trusts the configured CA and connects using a hostname listed in the certificate’s Subject Alternative Name. A plaintext client is refused when TLS is required, and a server that cannot read its private key will fail during startup or handshake.
Should I expose port 8222?
Only to a controlled administrative network. The HTTP monitoring endpoint is a separate exposure from the client listener, so client authentication does not make an unrestricted monitoring port safe.
Why does JetStream report a permission or storage error under systemd?
Verify the directory owner, mode, free space, inode availability, and the unit’s ReadWritePaths. With ProtectSystem=strict, the service can write only to paths explicitly reopened by that directive.
What is the difference between Core NATS and JetStream?
Core NATS provides ephemeral publish/subscribe delivery; a disconnected subscriber does not receive past messages. JetStream stores messages, supports later delivery and replay, and adds retention, capacity, permissions, and recovery responsibilities.
The Bottom Line
Install a pinned NATS Server release, validate /etc/nats-server.conf, and run the daemon as the unprivileged nats user under a hardened systemd unit. Require authentication before network exposure, add TLS with a correctly named certificate, and configure an intentional JetStream store_dir with monitored capacity. Finish every rollout by testing service state, authorized client traffic, persistence, TLS validation, and restricted monitoring access.
Quick Recap
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.




