Prometheus Node Exporter is the standard agent for exposing hardware and operating system metrics from Linux hosts to a Prometheus server. It collects data on CPU usage, memory, disk I/O, network throughput, filesystem utilisation, and dozens of other system-level indicators, making them available via a simple HTTP endpoint on port 9100. Installing Node Exporter on RHEL 9 is straightforward: download the binary, create a dedicated service account, write a systemd unit, and register the target in your Prometheus configuration. This tutorial covers the full setup including collector flags for enabling optional metric sources.

Prerequisites

  • RHEL 9 server with root or sudo access
  • A running Prometheus server (local or remote) to scrape the exporter
  • Port 9100 open in firewalld
  • wget or curl available for downloading the binary

Step 1 — Download Node Exporter

Download the latest Node Exporter release from the official GitHub releases page, extract it, and place the binary in /usr/local/bin.

NODE_EXPORTER_VERSION="1.8.1"

cd /tmp
curl -LO "https://github.com/prometheus/node_exporter/releases/download/v${NODE_EXPORTER_VERSION}/node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz"

tar xzf node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz
mv node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64/node_exporter /usr/local/bin/
chmod +x /usr/local/bin/node_exporter

# Verify the binary
node_exporter --version

Step 2 — Create a Dedicated Service Account

Running Node Exporter as a dedicated, unprivileged user reduces the security footprint. The account requires no home directory and no login shell.

useradd --no-create-home --shell /bin/false node_exporter

# Confirm the user was created
id node_exporter

Step 3 — Create the systemd Service Unit

Define a systemd unit file that runs Node Exporter as the dedicated service account. Optional collector flags are passed via ExecStart to enable systemd and process metrics which are disabled by default.

cat > /etc/systemd/system/node_exporter.service << 'EOF'
[Unit]
Description=Prometheus Node Exporter
Wants=network-online.target
After=network-online.target

[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter 
    --collector.systemd 
    --collector.processes 
    --web.listen-address=0.0.0.0:9100 
    --web.telemetry-path=/metrics
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now node_exporter
systemctl status node_exporter

Step 4 — Open Firewall and Verify Metrics

Allow inbound traffic on port 9100 so your Prometheus server can scrape metrics, then verify the endpoint is returning data.

firewall-cmd --permanent --add-port=9100/tcp
firewall-cmd --reload

# Check the metrics endpoint locally
curl -s http://localhost:9100/metrics | head -30

# Look for key metric families
curl -s http://localhost:9100/metrics | grep -E "^(node_cpu_seconds|node_memory_MemAvailable|node_disk_io_time|node_network_receive_bytes)" | head -10

Key metric categories exposed by Node Exporter include: CPU (node_cpu_seconds_total), memory (node_memory_MemAvailable_bytes), disk I/O (node_disk_reads_completed_total), network (node_network_receive_bytes_total), and filesystem (node_filesystem_avail_bytes).

Step 5 — Add the Node Exporter Scrape Job to Prometheus

On your Prometheus server, add a new scrape job to prometheus.yml targeting the Node Exporter endpoint. Prometheus will then collect metrics on the configured interval.

# On your Prometheus server, edit prometheus.yml
# Add the following under the scrape_configs section:

scrape_configs:
  # ... existing jobs ...

  - job_name: "node"
    static_configs:
      - targets:
          - "192.168.1.100:9100"   # Replace with your RHEL 9 server IP
        labels:
          instance: "rhel9-server"
          environment: "production"
    scrape_interval: 15s
    metrics_path: /metrics

# Reload Prometheus configuration
systemctl reload prometheus
# Or send SIGHUP: kill -HUP $(pgrep prometheus)

Step 6 — Useful PromQL Queries for Node Metrics

Once Prometheus is scraping Node Exporter, use these PromQL expressions in Grafana or the Prometheus UI to monitor system health.

# CPU usage percentage (per core, averaged over 1 minute)
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[1m])) * 100)

# Available memory in MB
node_memory_MemAvailable_bytes / 1024 / 1024

# Disk usage percentage per filesystem
(1 - node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100

# Network receive rate in KB/s
rate(node_network_receive_bytes_total[1m]) / 1024

# System load average (1 minute)
node_load1

# To disable a collector you don't need (e.g., wifi):
# Add to ExecStart: --no-collector.wifi

Conclusion

Prometheus Node Exporter is now installed, secured under a dedicated service account, and running as a systemd service on your RHEL 9 host. Your Prometheus server is scraping metrics every 15 seconds, giving you a rich dataset for dashboards and alerting rules. The optional --collector.systemd flag additionally exposes per-unit systemd state metrics, so you can alert when critical services enter a failed state. For multi-server environments, consider using Prometheus’s file-based service discovery or integrating with Ansible to deploy and configure Node Exporter at scale.

Next steps: How to Set Up Grafana Alerting and Notification Channels on RHEL 9, How to Install InfluxDB and Telegraf on RHEL 9, and How to Install Graylog for Centralised Log Management on RHEL 9.