How to Monitor FreeBSD Performance with Netdata
Netdata is a real-time performance monitoring agent that collects thousands of metrics per second with zero configuration. It auto-detects running services, presents interactive dashboards in your browser, and fires alerts when something goes wrong. On FreeBSD, Netdata picks up CPU, memory, disk I/O, network interfaces, ZFS pool statistics, and any running service it recognizes -- all within minutes of installation.
This guide walks through a complete Netdata deployment on FreeBSD 14.x: package installation, auto-detected collectors, ZFS-specific monitoring, custom dashboards, alert configuration, and connecting to Netdata Cloud for centralized visibility across multiple servers.
If you are evaluating monitoring options, see our comparison of FreeBSD monitoring tools. For a broader monitoring strategy, start with the FreeBSD server monitoring guide.
Why Netdata on FreeBSD
Most monitoring stacks require separate components for collection, storage, and visualization. Prometheus needs exporters plus Grafana for dashboards. Zabbix needs a database server and a web frontend. Netdata bundles everything into a single agent. Install it, start it, and open a browser. You get per-second granularity, hundreds of pre-built charts, and automatic service discovery.
For FreeBSD specifically, Netdata understands:
- ZFS ARC hit ratios, size, evictions, and demand data
- ZFS pool read/write throughput and operation counts
- GEOM disk I/O latency per device
- PF firewall state table entries, rule evaluations, and packet counters
- FreeBSD-specific sysctls for kernel metrics not available through generic Linux collectors
- Jails resource usage when running inside or alongside jail environments
The agent is written in C, consumes around 1-3% CPU on a typical server, and stores metrics in a ring buffer in RAM by default. It does not need a database.
Installing Netdata on FreeBSD
Netdata is available in the FreeBSD package repository:
shpkg install netdata
This installs the Netdata agent, its built-in web server, and all default collector plugins. The configuration lands in /usr/local/etc/netdata/ and the binary in /usr/local/sbin/netdata.
Enable Netdata to start at boot:
shsysrc netdata_enable="YES"
Start the service:
shservice netdata start
Verify it is running:
shservice netdata status
Open your browser and navigate to http://your-server-ip:19999. You should see the Netdata dashboard with charts already populating.
Initial Configuration
The main configuration file is /usr/local/etc/netdata/netdata.conf. Netdata ships with sensible defaults, but there are a few settings worth reviewing for a FreeBSD server.
Generate the full default configuration for reference:
sh/usr/local/sbin/netdata -W get-default-config > /tmp/netdata-defaults.conf
Edit the main config:
shvi /usr/local/etc/netdata/netdata.conf
Key settings to consider:
ini[global] # Bind to localhost only if you access via reverse proxy or SSH tunnel bind to = 127.0.0.1 # History retention in seconds (3600 = 1 hour at per-second granularity) history = 7200 # Memory mode: ram (default), save (persist to disk), dbengine (long-term) memory mode = dbengine # Page cache size for dbengine mode (MB) page cache size = 64 # Disk space limit for dbengine (MB) dbengine multihost disk space = 1024
The dbengine memory mode stores metrics on disk with configurable retention. With 1 GB of disk space, you can keep weeks of per-second data depending on the number of charts.
After editing, restart:
shservice netdata restart
Securing the Dashboard
By default, Netdata listens on all interfaces on port 19999 with no authentication. On a production server, you must restrict access.
Option 1: Bind to localhost and use an SSH tunnel.
In netdata.conf:
ini[global] bind to = 127.0.0.1
Access from your workstation:
shssh -L 19999:127.0.0.1:19999 user@your-server
Then open http://localhost:19999 in your browser.
Option 2: Put Netdata behind a reverse proxy with authentication.
If you run NGINX, add a location block:
shvi /usr/local/etc/nginx/conf.d/netdata.conf
nginxupstream netdata { server 127.0.0.1:19999; keepalive 64; } server { listen 443 ssl; server_name monitor.example.com; ssl_certificate /usr/local/etc/letsencrypt/live/monitor.example.com/fullchain.pem; ssl_certificate_key /usr/local/etc/letsencrypt/live/monitor.example.com/privkey.pem; auth_basic "Monitoring"; auth_basic_user_file /usr/local/etc/nginx/.htpasswd; location / { proxy_pass http://netdata; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_http_version 1.1; proxy_set_header Connection "keep-alive"; } }
Create the password file:
shpkg install apache24-utils htpasswd -c /usr/local/etc/nginx/.htpasswd admin
Option 3: Use PF to restrict access by IP.
shvi /etc/pf.conf
Add a rule allowing only your management network:
shellpass in on egress proto tcp from 10.0.0.0/24 to any port 19999 block in on egress proto tcp to any port 19999
Reload PF:
shpfctl -f /etc/pf.conf
Auto-Detected Collectors
Netdata automatically discovers running services and enables the appropriate collector. On a typical FreeBSD server, you will see collectors activate for:
- System metrics: CPU per core, load average, memory usage, swap, context switches, interrupts
- Disk I/O: per-device throughput, operations, queue depth via GEOM
- Network: per-interface bandwidth, packets, errors, drops
- ZFS: ARC size, hit ratio, pool I/O (if ZFS is in use)
- PostgreSQL: connections, queries, locks, replication lag (if running)
- NGINX: requests, connections, response codes (if stub_status is enabled)
- Redis: commands, memory, connections, keys (if running)
- Postfix: queue size, incoming/outgoing mail (if running)
Check which collectors are active:
shcurl -s http://127.0.0.1:19999/api/v1/info | python3 -m json.tool | grep -A2 "collectors"
Or view the list in the dashboard under the "Collectors" section.
ZFS Monitoring
Netdata's ZFS collector reads kernel sysctls to gather ARC and pool statistics. On FreeBSD, this works out of the box if ZFS is in use.
Verify ZFS metrics are being collected:
shcurl -s "http://127.0.0.1:19999/api/v1/charts" | python3 -m json.tool | grep zfs
You should see charts including:
zfs.arc_size-- current ARC size, target size, min/max limitszfs.arc_hit_ratio-- demand data, demand metadata, prefetch hit ratioszfs.reads-- ARC hits vs disk readszfs.pool_*-- per-pool read/write operations and bandwidth
For ZFS pool I/O, Netdata reads sysctl kstat.zfs. If you have multiple pools, each gets its own set of charts.
To get per-dataset usage monitoring, install the ZFS plugin helper:
shvi /usr/local/etc/netdata/go.d/zfspool.conf
yamljobs: - name: zpool binary_path: /sbin/zpool
Restart Netdata to pick up the new collector:
shservice netdata restart
Custom Dashboards
Netdata's default dashboard shows every collected metric. For operational use, you will want focused views. Netdata supports custom dashboards through its API and through Netdata Cloud.
Using the API to build a status page:
Create a simple HTML file that embeds specific charts:
shmkdir -p /usr/local/www/status vi /usr/local/www/status/index.html
html<!DOCTYPE html> <html> <head><title>Server Status</title></head> <body> <h1>Server Status</h1> <iframe src="http://127.0.0.1:19999/#;chart=system.cpu" width="800" height="200"></iframe> <iframe src="http://127.0.0.1:19999/#;chart=system.ram" width="800" height="200"></iframe> <iframe src="http://127.0.0.1:19999/#;chart=zfs.arc_size" width="800" height="200"></iframe> </body> </html>
Using Netdata Cloud dashboards (covered in the Cloud section below):
Netdata Cloud lets you pin charts from multiple nodes into shared "War Rooms" and custom dashboards. This is the recommended approach for multi-server environments.
Configuring Alerts
Netdata ships with hundreds of pre-configured alert rules covering CPU, memory, disk space, ZFS, network, and common services. Alert configuration files live in /usr/local/etc/netdata/health.d/.
List the default alert configurations:
shls /usr/local/etc/netdata/health.d/
View active alerts:
shcurl -s "http://127.0.0.1:19999/api/v1/alarms" | python3 -m json.tool | head -50
Create a custom alert:
Example: alert when ZFS ARC hit ratio drops below 80%:
shvi /usr/local/etc/netdata/health.d/zfs-custom.conf
yamlalarm: zfs_arc_hit_ratio_low on: zfs.arc_hit_ratio lookup: average -5m of demand_data units: % every: 1m warn: $this < 85 crit: $this < 70 info: ZFS ARC demand data hit ratio is low to: sysadmin
Configure email notifications:
Edit the alarm notification configuration:
shvi /usr/local/etc/netdata/health_alarm_notify.conf
Set the email recipient:
iniDEFAULT_RECIPIENT_EMAIL="admin@example.com" SEND_EMAIL="YES"
Netdata uses sendmail by default. If your server can send mail via the local MTA, notifications work immediately. For external SMTP, configure your MTA (Postfix, etc.) to relay.
Configure Slack notifications:
iniSEND_SLACK="YES" SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" DEFAULT_RECIPIENT_SLACK="#alerts"
Reload the health configuration:
shkillall -USR2 netdata
Test notifications:
sh/usr/local/libexec/netdata/plugins.d/alarm-notify.sh test
Netdata Cloud Integration
Netdata Cloud is a free SaaS service that connects your Netdata agents for centralized viewing, composite charts across nodes, and shared alert management. The agent streams metadata and metrics to Netdata Cloud; your data still originates from and is stored on your servers.
Claim your node to Netdata Cloud:
- Create an account at
https://app.netdata.cloud - Create a Space and a War Room
- Click "Connect Nodes" and copy the claim command
Run the claim command on your FreeBSD server:
shnetdata-claim.sh -token=YOUR_CLAIM_TOKEN -rooms=YOUR_ROOM_ID -url=https://app.netdata.cloud
If netdata-claim.sh is not in your PATH:
sh/usr/local/sbin/netdata-claim.sh -token=YOUR_CLAIM_TOKEN -rooms=YOUR_ROOM_ID -url=https://app.netdata.cloud
Verify the claim:
shcat /usr/local/var/lib/netdata/cloud.d/claimed_id
The node should appear in your Netdata Cloud War Room within seconds. From there you can:
- View composite charts that aggregate metrics across all claimed nodes
- Set up centralized alert notifications (email, Slack, PagerDuty, Opsgenie)
- Create custom dashboards with pinned charts from multiple nodes
- Share dashboards with team members without exposing individual node dashboards
Streaming Between Nodes
If you have multiple FreeBSD servers, you can stream metrics from child nodes to a parent node for centralized storage without using Netdata Cloud.
On the parent node, edit the stream configuration:
shvi /usr/local/etc/netdata/stream.conf
ini[API_KEY_GENERATED_BY_UUIDGEN] enabled = yes default history = 86400 default memory mode = dbengine health enabled by default = auto allow from = 10.0.0.*
Generate the API key:
shuuidgen
On each child node:
shvi /usr/local/etc/netdata/stream.conf
ini[stream] enabled = yes destination = 10.0.0.1:19999 api key = YOUR_GENERATED_UUID
Restart both parent and child:
shservice netdata restart
The parent node's dashboard will show all streamed child nodes in the left sidebar.
Performance Tuning
Netdata's default settings work well for most servers. For high-traffic systems or resource-constrained environments, adjust these settings.
Reduce CPU usage by increasing the update interval:
ini[global] update every = 2
This changes collection from every 1 second to every 2 seconds, roughly halving CPU usage.
Disable collectors you do not need:
shvi /usr/local/etc/netdata/netdata.conf
ini[plugins] apps = no idlejitter = no
Disabling the apps plugin saves noticeable CPU, as it tracks per-process resource usage.
Limit dbengine disk usage:
ini[global] dbengine multihost disk space = 512
Monitor Netdata's own resource usage:
Netdata monitors itself. Check the netdata.apps_cpu and netdata.apps_mem charts in the dashboard to see exactly how much CPU and memory the agent consumes.
Updating Netdata
When a new version is available in the FreeBSD package repository:
shpkg update pkg upgrade netdata service netdata restart
Check the running version:
shnetdata -V
Or via the API:
shcurl -s http://127.0.0.1:19999/api/v1/info | python3 -c "import sys,json; print(json.load(sys.stdin)['version'])"
Troubleshooting
Dashboard not loading:
Check that Netdata is running and listening:
shservice netdata status sockstat -l | grep 19999
Check the error log:
shtail -50 /var/log/netdata/error.log
Missing ZFS charts:
Ensure ZFS is loaded and pools exist:
shkldstat | grep zfs zpool list sysctl kstat.zfs.misc.arcstats.hits
If the sysctl returns a value, Netdata should detect ZFS. Restart the service if charts do not appear after a minute.
High CPU usage:
Identify which plugin is consuming CPU:
shtop -m io -S | grep netdata
Disable the apps plugin if per-process monitoring is not needed. Increase the update interval to 2 seconds.
Alerts not sending:
Test the notification system directly:
sh/usr/local/libexec/netdata/plugins.d/alarm-notify.sh test
Check that your MTA is configured and can send mail from the command line:
shecho "test" | mail -s "test" admin@example.com
FAQ
Does Netdata work inside a FreeBSD jail?
Yes, but with limitations. A jailed Netdata instance can monitor its own resource usage, running services, and network interfaces. It cannot see host-level ZFS stats, other jails, or kernel-level metrics. For full visibility, run Netdata on the host system.
How much disk space does Netdata use with dbengine?
It depends on the number of collected metrics and retention period. A typical server with 2000 metrics at per-second granularity uses roughly 50 MB per day. The dbengine multihost disk space setting caps total usage. Netdata automatically compresses and rotates old data within that limit.
Can I use Netdata alongside Prometheus?
Yes. Netdata exposes a Prometheus-compatible endpoint at /api/v1/allmetrics?format=prometheus. Configure Prometheus to scrape that endpoint and you get Netdata's auto-detected metrics in your existing Prometheus/Grafana stack.
Is Netdata Cloud required?
No. Netdata works fully standalone. The agent's built-in dashboard provides all charts, alerts, and configuration. Netdata Cloud adds centralized multi-node views, composite charts, and shared alert management, but every feature that operates on a single node works without it.
How do I monitor multiple FreeBSD servers from one dashboard?
Either use Netdata Cloud (free tier supports unlimited nodes) or configure parent-child streaming as described above. The parent node's dashboard shows all child nodes. Netdata Cloud is simpler to set up and does not require network connectivity between nodes.
Can Netdata monitor services running in jails from the host?
Netdata on the host sees host-level metrics. To monitor services inside jails (e.g., PostgreSQL running in a jail), either run a Netdata agent inside the jail or expose the service's metrics endpoint to the host network and configure a collector on the host agent.