Netdata is an open source monitoring agent that collects thousands of per-second metrics (CPU, memory, disks, network, processes, containers and services such as Nginx or MySQL) with almost no configuration and shows them on a live web dashboard. In this tutorial you will install Netdata on Ubuntu 24.04, restrict access to its dashboard, enable an Nginx collector, create a custom health alert that notifies a Slack channel, and optionally stream metrics from several servers to one parent node.

Prerequisites

To follow this guide you need:

  • A server running Ubuntu 24.04 LTS, for example a CubePath VPS, with at least 1 GB of RAM.
  • A non-root user with sudo privileges.
  • UFW enabled with SSH allowed (sudo ufw allow OpenSSH and sudo ufw enable).
  • The public IP address of the computer you will use to open the dashboard, referred to as your_ip.
  • Optional: Nginx installed (sudo apt install nginx) to follow the collector step, and a Slack incoming webhook URL for the notification step.

Step 1 - Installing Netdata

Netdata's supported installation method is its kickstart.sh script. On Ubuntu it detects the release and installs Netdata's native .deb packages from the official repository, so later updates arrive through apt. Download the script first so you can review it:

wget -O /tmp/netdata-kickstart.sh https://get.netdata.cloud/kickstart.sh
less /tmp/netdata-kickstart.sh

Run it with the stable release channel and anonymous telemetry disabled:

sh /tmp/netdata-kickstart.sh --stable-channel --disable-telemetry

The script asks for your sudo password and confirmation before it adds the repository and installs the netdata package. When it finishes, the service is already enabled and running. Check it:

sudo systemctl status netdata --no-pager
● netdata.service - Netdata, X-Ray Vision for your infrastructure!
     Loaded: loaded (/usr/lib/systemd/system/netdata.service; enabled; preset: enabled)
     Active: active (running) since Thu 2026-09-24 10:12:41 UTC; 25s ago

Netdata serves its dashboard and API on TCP port 19999. Query the API locally to confirm the agent answers:

curl -s http://localhost:19999/api/v1/info | grep -m1 '"version"'
	"version": "v2.6.3",

Your version number will differ.

Step 2 - Restricting access to the dashboard

By default Netdata listens on all interfaces and the dashboard has no password. Anyone who can reach port 19999 can see process names, users and service details, so only allow your own IP address through the firewall:

sudo ufw allow from your_ip to any port 19999 proto tcp

Check the rule:

sudo ufw status
To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
19999/tcp                  ALLOW       your_ip
OpenSSH (v6)               ALLOW       Anywhere (v6)

Now open http://your_server_ip:19999 in your browser. The dashboard may offer to sign in to Netdata Cloud; you can skip that and keep using the local agent dashboard. You should see charts for CPU, load, memory, disks and network updating every second.

Step 3 - Understanding the configuration layout

Netdata keeps its stock configuration under /usr/lib/netdata/conf.d/ and reads your overrides from /etc/netdata/. Never edit the stock files: use the edit-config helper, which copies the stock file into /etc/netdata/ the first time and opens it in your editor.

cd /etc/netdata
sudo ./edit-config netdata.conf

Most settings work out of the box, so close the file without changes for now. The paths you will use in this guide are:

PathPurpose
/etc/netdata/netdata.confMain agent settings (web server, database, plugins)
/etc/netdata/go.d/<module>.confCollector jobs for services (Nginx, MySQL, Redis...)
/etc/netdata/health.d/*.confHealth alert definitions
/etc/netdata/health_alarm_notify.confNotification methods (email, Slack, Discord...)
/etc/netdata/stream.confParent and child streaming

Logs go to the systemd journal, so sudo journalctl -u netdata is the first place to look when something fails.

Step 4 - Monitoring Nginx with a collector

Netdata's go.d plugin auto-detects many local services by probing their usual endpoints. For Nginx it needs the stub_status page, which is not enabled by default. Create a small server block that exposes it only on localhost:

sudo nano /etc/nginx/conf.d/stub_status.conf
server {
    listen 127.0.0.1:80;
    server_name 127.0.0.1;

    location = /nginx_status {
        stub_status;
        allow 127.0.0.1;
        deny all;
    }
}

Test the configuration and reload Nginx:

sudo nginx -t && sudo systemctl reload nginx
curl -s http://127.0.0.1/nginx_status
Active connections: 1
server accepts handled requests
 3 3 3
Reading: 0 Writing: 1 Waiting: 0

Now tell Netdata where the page is. Open the Nginx collector configuration:

cd /etc/netdata
sudo ./edit-config go.d/nginx.conf

Replace the jobs section at the end of the file with:

jobs:
  - name: local
    url: http://127.0.0.1/nginx_status

Restart Netdata so the collector picks up the job:

sudo systemctl restart netdata

After a few seconds, check that Nginx charts exist:

curl -s http://localhost:19999/api/v1/charts | grep -o '"nginx_local[^"]*"' | sort -u | head -n 3
"nginx_local.connections"
"nginx_local.connections_status"
"nginx_local.requests"

The dashboard now shows an Nginx section with active connections and requests per second. The same pattern (enable the service's status endpoint, then add a job in go.d/<module>.conf) applies to MySQL, PostgreSQL, Redis and the other supported collectors.

Step 5 - Creating a custom health alert

Netdata ships with hundreds of preconfigured alerts (disk space, RAM, network errors and more). You can add your own in a new file under health.d. This one raises a warning when average CPU utilization over five minutes exceeds 80% and a critical alert above 95%:

sudo nano /etc/netdata/health.d/cpu_custom.conf
 alarm: cpu_usage_high
    on: system.cpu
lookup: average -5m unaligned of user,system,softirq,irq,guest
 units: %
 every: 1m
  warn: $this > 80
  crit: $this > 95
  info: average CPU utilization over the last 5 minutes
    to: sysadmin

Here on is the chart the alert watches, lookup computes the value ($this) from the chosen dimensions, and to is the recipient role used by the notification settings. Reload the health configuration without restarting the agent:

sudo netdatacli reload-health

Verify that the new alert is loaded:

curl -s 'http://localhost:19999/api/v1/alarms?all' | grep -o '"cpu_usage_high[^"]*"' | head -n 1
"cpu_usage_high"

The alert also appears in the Alerts tab of the dashboard, with its current status (normally CLEAR).

Step 6 - Sending notifications to Slack

Alert notifications are handled by the alarm-notify.sh script and configured in health_alarm_notify.conf. Open it:

cd /etc/netdata
sudo ./edit-config health_alarm_notify.conf

Find the Slack section and set these three values, using your own webhook URL and channel:

SEND_SLACK="YES"
SLACK_WEBHOOK_URL="https://hooks.slack.com/services/XXXXXXXX/XXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX"
DEFAULT_RECIPIENT_SLACK="#alerts"

Save the file and send a test notification as the netdata user:

sudo -u netdata /usr/libexec/netdata/plugins.d/alarm-notify.sh test

The script sends a WARNING, a CRITICAL and a CLEAR test message, and prints OK for each method that succeeded:

# SENDING TEST WARNING ALARM TO ROLE: sysadmin
2026-09-24 10:31:02: alarm-notify.sh: INFO: sent slack notification to '#alerts' for notification to 'sysadmin'
# OK

Three messages should arrive in your Slack channel. Email works the same way (SEND_EMAIL="YES" and DEFAULT_RECIPIENT_EMAIL), but it requires a working mail transfer agent on the server, such as Postfix configured to relay through your SMTP provider.

Step 7 - Streaming metrics to a parent node (optional)

With several servers you can stream every agent (child) to one Netdata parent, which stores all the metrics and shows them from a single dashboard. Streaming is authenticated with an API key, which is simply a UUID. Generate one on the parent:

cat /proc/sys/kernel/random/uuid
3c8f5e0a-7a39-4b8e-9d1c-2f6a7b8c9d10

On the parent, open stream.conf:

cd /etc/netdata
sudo ./edit-config stream.conf

Add a section named after the key at the end of the file, allowing only your child servers' addresses:

[3c8f5e0a-7a39-4b8e-9d1c-2f6a7b8c9d10]
    enabled = yes
    allow from = child_ip_1 child_ip_2

Open port 19999 on the parent for each child and restart Netdata:

sudo ufw allow from child_ip_1 to any port 19999 proto tcp
sudo systemctl restart netdata

On each child, edit its own stream.conf and fill in the [stream] section at the top:

[stream]
    enabled = yes
    destination = parent_ip:19999
    api key = 3c8f5e0a-7a39-4b8e-9d1c-2f6a7b8c9d10

Restart Netdata on the child:

sudo systemctl restart netdata

Back on the parent, the child should appear in the list of mirrored hosts:

curl -s http://localhost:19999/api/v1/info | grep -A3 '"mirrored_hosts"'
	"mirrored_hosts": [
		"parent-hostname",
		"child-hostname"
	],

In the parent dashboard you can now switch between nodes. The traffic between child and parent is unencrypted, so use it over a private network or a VPN.

Troubleshooting

  • The dashboard does not load from your browser: check sudo ss -tlnp | grep 19999 to confirm Netdata is listening, and sudo ufw status to confirm your current public IP is the one allowed.
  • A collector shows no charts: look for errors from the plugin with sudo journalctl -u netdata | grep -i nginx. The most common cause is a URL that returns 404 or 403 to Netdata.
  • The test notification fails: run the test command again and read the error line; a 403 or 404 from Slack means the webhook URL is wrong or was revoked.
  • The child does not connect: on the child, sudo journalctl -u netdata | grep -i stream shows whether the connection is refused (firewall) or the key is rejected (allow from or API key mismatch).

Conclusion

You now have Netdata collecting per-second metrics on Ubuntu 24.04, with a dashboard limited to your IP, an Nginx collector, a custom CPU alert delivered to Slack and, optionally, a parent node that centralizes several servers. From here you can enable more go.d collectors for your databases, tune the stock alerts in health.d to your workloads, or put the dashboard behind an Nginx reverse proxy with HTTPS and basic authentication.