What to Measure Before Picking a Tool
Before installing anything, run `vmstat 1 5` and `iostat -x 1 5` on your target server. If you are already seeing wait times above 5% or disk utilization above 80% at idle, your monitoring agent will add noise. A heavyweight agent like Zabbix with full SNMP polling can consume 150-200MB of RAM on its own. On a 1GB VPS that matters.
Define your requirements in three columns: what metrics you need (CPU, memory, disk I/O, network, application-level), how long you need to retain them, and whether you need alerting or just visibility. A startup running three servers needs something different from a team managing 200 nodes. Most engineers skip this step and end up running two or three overlapping tools. We did too, until we had Prometheus, Netdata, and Datadog all writing to the same host.
vmstat 1 5
iostat -x 1 5
free -h
Prometheus + Grafana: The Production Standard
Prometheus 2.52 (current as of mid-2026) is the de facto standard for metrics collection in Linux and Kubernetes environments. It scrapes HTTP endpoints called exporters, stores time-series data in its own TSDB, and supports PromQL for querying. Grafana 11 connects to Prometheus as a data source and handles dashboards and alerting.
The minimum viable stack is `prometheus`, `node_exporter`, and `grafana`. Node exporter exposes 1,000+ metrics from the host kernel including CPU frequency scaling, per-disk I/O, network saturation, and filesystem inodes. Install node_exporter as a systemd service and point Prometheus at it.
On our 2-core/4GB test node, the full Prometheus + Grafana stack with 15-day retention consumed 380MB RAM and averaged 1.2% CPU. That is acceptable. With 90-day retention and 20 scraped targets, expect 800MB-1.2GB of disk per target per month depending on scrape interval.
The main operational cost is YAML. Prometheus configuration is entirely file-based, which is good for version control but requires a reload (`kill -HUP $(pidof prometheus)`) or `promtool check config prometheus.yml` before every change in production.
# Install node_exporter
wget https://github.com/prometheus/node_exporter/releases/download/v1.8.1/node_exporter-1.8.1.linux-amd64.tar.gz
tar xvf node_exporter-1.8.1.linux-amd64.tar.gz
sudo mv node_exporter-1.8.1.linux-amd64/node_exporter /usr/local/bin/
# Minimal prometheus.yml scrape config
scrape_configs:
- job_name: 'node'
static_configs:
- targets: ['localhost:9100']
Netdata: Real-Time at 1-Second Granularity
Netdata v1.46 is the only tool in this list that collects metrics at 1-second resolution out of the box and ships a usable UI with zero configuration. Install takes under two minutes and the agent auto-detects Nginx, MySQL, PostgreSQL, Redis, Docker containers, and around 80 other services.
The tradeoff: Netdata's default retention is 14 days in its database engine (dbengine), and long-term storage requires either Netdata Cloud (their SaaS) or configuring streaming to a parent node. For ephemeral infrastructure this is fine. For compliance or capacity planning that needs 12 months of data, it is not.
Memory consumption on our test server was 120-180MB with the full suite of collectors active. CPU was under 0.5% average. That is better than Prometheus plus Grafana on the same host, and the default dashboards are production-ready without any Grafana panel building.
Netdata's alerting works via `health.d/*.conf` files. You can trigger notifications to Slack, PagerDuty, or any webhook. For teams already using DevOps automation platforms, Netdata's alert webhooks integrate directly - tools like taskbotshub.ai can receive these webhook events and trigger runbooks or remediation scripts automatically without human intervention.
# One-line install
wget -O /tmp/netdata-kickstart.sh https://get.netdata.cloud/kickstart.sh
bash /tmp/netdata-kickstart.sh --stable-channel --disable-cloud
# Check status
systemctl status netdata
# UI available at http://localhost:19999
Zabbix 7: Enterprise-Grade With the Config Overhead to Match
Zabbix 7.0 LTS (released late 2024, supported through 2029) is the right answer when you need agentless SNMP monitoring, network device polling, or a single pane of glass across 500+ mixed-OS hosts. It uses a PostgreSQL or MySQL backend, a Java gateway for JMX, and an active/passive agent protocol that works through firewalls better than Prometheus's pull model.
Installation is non-trivial. Plan 30-60 minutes for a clean server setup including the database schema import. Zabbix's web interface is PHP-based and requires Apache or Nginx plus PHP-FPM. On a dedicated monitoring server with 4GB RAM, the full stack runs comfortably. On a 1GB shared host it will swap.
Where Zabbix earns its complexity: auto-discovery rules that can onboard a new host and apply templates within minutes of it appearing on the network, built-in escalation policies with maintenance windows, and SLA reporting. The template library covers most major applications and hardware vendors out of the box.
The PromQL vs Zabbix expression language comparison is not close - PromQL wins for ad hoc queries. But Zabbix's trigger system is more expressive for multi-condition alerting. You can write triggers like 'CPU above 90% for 5 minutes AND disk I/O wait above 30% AND not in maintenance window' in a single expression.
# Add Zabbix 7.0 repo on Ubuntu 24.04
wget https://repo.zabbix.com/zabbix/7.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_7.0-1+ubuntu24.04_all.deb
dpkg -i zabbix-release_7.0-1+ubuntu24.04_all.deb
apt update
apt install zabbix-server-pgsql zabbix-frontend-php zabbix-nginx-conf zabbix-agent2
Checkmk 2.3: The Zabbix Alternative With Better UX
Checkmk 2.3 Free Edition supports up to 25 hosts and is worth serious consideration if Zabbix's interface frustrates your team. The agent auto-registers services using a discovery mechanism that is faster than Zabbix templates - a fresh Linux host with Checkmk agent installed will have 50-100 services detected and graphed within 60 seconds of first contact.
Checkmk uses RRDtool for metrics storage, which gives you indefinite retention in compressed form without a separate time-series database. The commercial editions (Standard, Managed Services) add distributed monitoring, SLA reports, and official support.
For shops that need monitoring but cannot dedicate engineering time to maintaining a complex stack, Checkmk 2.3 Free is the least painful path to production-quality monitoring. We used it for a 20-node setup on Vultr (https://vultr.com/?ref=PLACEHOLDER) and had dashboards, alerts, and email notifications running inside two hours from a fresh Debian 12 image.
# Install Checkmk 2.3 Raw Edition on Debian 12
wget https://download.checkmk.com/checkmk/2.3.0p1/check-mk-raw-2.3.0p1_0.bookworm_amd64.deb
apt install ./check-mk-raw-2.3.0p1_0.bookworm_amd64.deb
omd create mysite
omd start mysite
# Web UI at http://yourserver/mysite/
Glances and Htop: Lightweight Local Inspection
Glances 4.x and htop 3.3 are not long-term monitoring solutions, but they belong in every sysadmin's toolkit for triage. Glances runs in terminal or as an HTTP server (`glances -w`) exposing a REST API and a browser-based view on port 61208. Install with `pip install glances` or `apt install glances`.
The practical use case: you SSH into a server that is behaving strangely and you want a full picture of CPU, memory, disk I/O, network, open connections, and top processes in one screen. Glances does this better than any combination of individual commands. It also exports to InfluxDB, Prometheus, Graphite, and Cassandra if you want to feed it into a central stack.
Htop 3.3 added IO wait percentage and network I/O columns to the default view. If you are not using the newer version, install it: `apt install htop` on Debian/Ubuntu gives you 3.3 as of Bookworm. Configure it with F2 to add columns for IO read/write, and save that configuration - it persists per user in `~/.config/htop/htoprc`.
# Glances as a metrics API server
glances -w --port 61208
# Query the API
curl http://localhost:61208/api/3/cpu
curl http://localhost:61208/api/3/diskio
# Export to Prometheus
glances --export prometheus --export-prometheus-port 9091
Alertmanager and Notification Routing
Prometheus's Alertmanager v0.27 handles deduplication, grouping, silencing, and routing of alerts to receivers. This is separate from Prometheus itself and worth configuring properly before you go to production. A common mistake is pointing all alerts at a single Slack channel. Within a week the team learns to ignore it.
Route critical alerts (disk full, host down, OOM kill) to PagerDuty with a 5-minute repeat interval. Route warning-level alerts to Slack with a 30-minute group wait. Use inhibition rules so that a 'host down' alert suppresses all the derivative alerts from that same host (PostgreSQL down, Nginx down, etc.).
Alertmanager configuration is a single YAML file. The `amtool` CLI lets you check config, list active alerts, and create silences from the command line without touching the UI - useful for scripted maintenance windows.
For teams building out named monitoring infrastructure, getting your hostnames and project names right from the start matters more than it seems. A consistent naming scheme across your servers, dashboards, and alert routing trees prevents the configuration drift that makes large monitoring setups unmaintainable. Services like nicename.me can help when you need to register project or service names as domains to keep naming consistent across infrastructure.
# alertmanager.yml - minimal routing example
route:
group_by: ['alertname', 'cluster']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: 'slack-warnings'
routes:
- match:
severity: critical
receiver: 'pagerduty-critical'
repeat_interval: 5m
# Check config
amtool check-config alertmanager.yml
# Create a 2-hour silence for host maintenance
amtool silence add alertname=~'.+' instance='web01:9100' \
--duration=2h --comment='Scheduled maintenance'
Choosing the Right Stack by Team Size
For a single developer or small team managing under 10 servers: install Netdata on each host, enable the free Netdata Cloud account for a central view, and add a Slack webhook for critical alerts. Total setup time is under an hour. You get 1-second resolution, 14-day history, and a good enough alert system without maintaining a database or writing PromQL.
For a team managing 10-100 hosts: run Prometheus plus Grafana on a dedicated monitoring server (a 2-core/4GB node is sufficient for up to 50 targets at 15s scrape interval with 30-day retention). Add Alertmanager with PagerDuty or Opsgenie routing. Use node_exporter as the base and add application-specific exporters: `postgres_exporter`, `redis_exporter`, `nginx-prometheus-exporter`. Label your targets with environment, region, and tier from day one.
For large environments (100+ hosts, mixed OS, network devices, SLA requirements): Zabbix 7.0 LTS or Checkmk Standard with a dedicated PostgreSQL backend. The configuration overhead pays off at scale because both tools have auto-discovery that handles host churn without manual YAML editing. Prometheus at this scale requires service discovery via Consul, Kubernetes, or EC2 tags - doable but an additional system to maintain.
For teams using AI-assisted operations and automated remediation workflows, integrating monitoring alerts into platforms like taskbotshub.ai means you can close the loop between detection and response without writing custom integration code for every alert type.
# Prometheus with file_sd for 50+ targets
# /etc/prometheus/targets/web.yml
- targets:
- 'web01.prod:9100'
- 'web02.prod:9100'
labels:
env: 'production'
tier: 'web'
region: 'us-east'
# Reference in prometheus.yml
scrape_configs:
- job_name: 'nodes'
file_sd_configs:
- files:
- '/etc/prometheus/targets/*.yml'
refresh_interval: 30s