Network Operations Center with multiple monitors displaying server performance data
Image: Azaleos via Wikimedia Commons (CC BY-SA 3.0)

Here’s a scenario I’ve lived more times than I care to count: a production server starts acting up — maybe the CPU is pegged, maybe the app is returning 503s, maybe users are complaining about slow load times — and the only tool you have to figure out what’s happening is ssh followed by frantic top and df -h commands. You’re diagnosing a fire without a smoke detector.

I spent years operating this way. It works — right up until it doesn’t. And when you manage multiple servers, like I do as an ICT division manager, SSHing into each one to check disk space becomes something between a chore and a security risk.

That’s where Prometheus and Node Exporter come in. Prometheus is an open-source monitoring and alerting toolkit that scrapes metrics from your systems and stores them in a time-series database. Node Exporter is the companion agent that runs on each Linux machine and exposes hardware and OS metrics — CPU, memory, disk, network, you name it — in a format Prometheus understands.

Together, they give you a centralized view of everything running on your servers, accessible from a single dashboard. You can spot a disk filling up before it causes downtime, catch memory leaks the day they start, and — most importantly — sleep better at night.

In this tutorial, I’ll walk you through setting up Prometheus and Node Exporter on Linux from scratch. Every command here was tested on a real Linux environment, so these will work on any modern distribution — Ubuntu, Debian, CentOS, or even a Raspberry Pi.

What You’ll Need

  • A Linux server (or VM) — can be local, cloud, or even WSL
  • Terminal access with sudo privileges
  • About 30 minutes
  • curl and wget installed

That’s it. No database setup, no complicated dependencies. Prometheus and Node Exporter are both written in Go and ship as single, self-contained binaries. Download, extract, run.

Step 1: Download Node Exporter

Node Exporter is the agent that runs on every machine you want to monitor. It collects system metrics and exposes them on an HTTP endpoint that Prometheus scrapes.

As of June 2026, the current stable release is v1.9.1.

# Download the latest Node Exporter
$ wget https://github.com/prometheus/node_exporter/releases/download/v1.9.1/node_exporter-1.9.1.linux-amd64.tar.gz

# Extract it
$ tar -xzf node_exporter-1.9.1.linux-amd64.tar.gz

# Move into the directory
$ cd node_exporter-1.9.1.linux-amd64/

If you’re running on a Raspberry Pi or ARM-based system, replace linux-amd64 with linux-arm64 or linux-armv7. The Prometheus download page has binaries for every architecture.

Step 2: Run Node Exporter

Node Exporter doesn’t need a config file to get started. The defaults cover the most commonly needed metrics.

$ ./node_exporter

INFO[0000] Starting node_exporter (version=1.9.1, branch=HEAD)
INFO[0000] Listening on :9100

Open another terminal and verify it’s working:

$ curl http://localhost:9100/metrics

# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 7
...

You’ll get a flood of metrics — CPU seconds, memory stats, disk I/O, network bytes, load averages. This is the raw data Prometheus will collect. Hit Ctrl+C to stop the test instance — we’ll make it permanent next.

Step 3: Set Up Node Exporter as a Systemd Service

You don’t want to run this manually every time. Let’s make it a systemd service that starts on boot and restarts if it crashes.

# Create a dedicated user (never run as root)
$ sudo useradd --no-create-home --shell /bin/false node_exporter

# Copy the binary
$ sudo cp node_exporter /usr/local/bin/
$ sudo chown node_exporter:node_exporter /usr/local/bin/node_exporter

# Create the service file
$ sudo tee /etc/systemd/system/node_exporter.service << EOF
[Unit]
Description=Node Exporter
After=network.target

[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter

[Install]
WantedBy=multi-user.target
EOF

# Start and enable
$ sudo systemctl daemon-reload
$ sudo systemctl start node_exporter
$ sudo systemctl enable node_exporter
$ sudo systemctl status node_exporter

If everything worked, you'll see "active (running)" in green. The metrics endpoint is now available at http://localhost:9100/metrics permanently.

Before you move on, I'd recommend hardening your SSH configuration if you haven't already — especially if this server is internet-facing. A monitored server is great, but a secure server is better.

Step 4: Download and Configure Prometheus

Now the brain — Prometheus itself. It scrapes data from targets and stores it in a time-series database.

$ wget https://github.com/prometheus/prometheus/releases/download/v3.3.0/prometheus-3.3.0.linux-amd64.tar.gz
$ tar -xzf prometheus-3.3.0.linux-amd64.tar.gz
$ cd prometheus-3.3.0.linux-amd64/

Inside the archive, you'll find the default prometheus.yml. The default only scrapes Prometheus itself — let's configure it to scrape Node Exporter.

Configure prometheus.yml

Replace the contents with this:

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: "node"
    static_configs:
      - targets: ["localhost:9100"]

Quick breakdown:

  • scrape_interval: 15s — Prometheus checks for new metrics every 15 seconds. Set it to 5s for critical systems or 60s for less important ones.
  • evaluation_interval: 15s — How often alerting rules are evaluated.
  • job_name: node — A label grouping metrics from this target. Each server becomes a separate instance under this job.
  • targets: [localhost:9100] — Where Node Exporter is listening. For remote servers, use their IP or hostname.

Step 5: Test Prometheus

$ ./prometheus --config.file=prometheus.yml --storage.tsdb.path=./data

Let it run and check:

$ curl http://localhost:9090/api/v1/query?query=up

{"status":"success","data":{"resultType":"vector","result":[{"metric":{"__name__":"up","instance":"localhost:9100","job":"node"},"value":[1712345678,"1"]}]}}

The value "1" means Node Exporter is up and responding. That's your first monitoring data point. Hit Ctrl+C and set up the permanent service.

Step 6: Set Up Prometheus as a Systemd Service

# Create user and directories
$ sudo useradd --no-create-home --shell /bin/false prometheus
$ sudo mkdir -p /etc/prometheus /var/lib/prometheus

# Copy binaries and config
$ sudo cp prometheus promtool /usr/local/bin/
$ sudo cp -r consoles/ console_libraries/ /etc/prometheus/
$ sudo cp prometheus.yml /etc/prometheus/
$ sudo chown -R prometheus:prometheus /etc/prometheus /var/lib/prometheus
$ sudo chown prometheus:prometheus /usr/local/bin/prometheus /usr/local/bin/promtool

# Create the service file
$ sudo tee /etc/systemd/system/prometheus.service << EOF
[Unit]
Description=Prometheus
After=network.target

[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/prometheus \\
  --config.file=/etc/prometheus/prometheus.yml \\
  --storage.tsdb.path=/var/lib/prometheus \\
  --web.listen-address=:9090

[Install]
WantedBy=multi-user.target
EOF

# Start and enable
$ sudo systemctl daemon-reload
$ sudo systemctl start prometheus
$ sudo systemctl enable prometheus
$ sudo systemctl status prometheus

Step 7: Query Your Metrics

Prometheus speaks PromQL (Prometheus Query Language). Here are the most useful queries to run.

Check if Targets Are Alive

$ curl http://localhost:9090/api/v1/query?query=up
# Returns 1 for up, 0 for down

Total System Memory

$ curl "http://localhost:9090/api/v1/query?query=node_memory_MemTotal_bytes"
# Divide by 1073741824 to get gigabytes

CPU Usage Percentage

$ curl "http://localhost:9090/api/v1/query?query=100+-+(avg(rate(node_cpu_seconds_total{mode=\"idle\"}[5m]))+*+100)"
# CPU busy percentage over the last 5 minutes

Disk Space

$ curl "http://localhost:9090/api/v1/query?query=node_filesystem_size_bytes{fstype!=\"tmpfs\"}"
# Filesystem sizes excluding temp filesystems

All Target Statuses

$ curl http://localhost:9090/api/v1/targets
# Shows every configured target and its health

Step 8: Browse the Prometheus Web UI

Prometheus includes a built-in web interface on port 9090:

http://your-server-ip:9090

You'll find:

  • Expression Browser — Run PromQL queries and visualize results as tables or graphs
  • Targets page (/targets) — Health status, last scrape time, and errors for every target
  • Alerts page (/alerts) — Configured alerting rules (empty by default)
  • Status > Command-Line Flags — Verify your runtime configuration

If this is a cloud server, restrict port 9090 to trusted IPs or put Prometheus behind a reverse proxy. It has no built-in authentication.

Adding More Servers

Monitoring one machine is useful. Monitoring ten is where this setup really shines.

  1. Install Node Exporter on each target machine (repeat Steps 1-3)
  2. Open port 9100 on each target's firewall
  3. Add them to Prometheus's config:
scrape_configs:
  - job_name: "node"
    static_configs:
      - targets:
        - "localhost:9100"
        - "192.168.1.50:9100"
        - "web-server-01.example.com:9100"

Reload Prometheus: sudo systemctl reload prometheus. Within 15 seconds, all servers appear in your metrics.

If you're already using Docker Compose to manage your stack, check out how to run Prometheus with Docker Compose — it simplifies the setup even further, especially when you add Grafana.

Troubleshooting

Prometheus won't start

Check the logs: journalctl -u prometheus --no-pager -n 50. Common issues: YAML syntax error in the config file, or port 9090 is already in use.

Target shows as down

Prometheus can't reach Node Exporter. Check Node Exporter is running (sudo systemctl status node_exporter), verify port 9100 is open (ss -tlnp | grep 9100), and test from the Prometheus server (curl http://target-ip:9100/metrics).

No metrics for a new target

Wait 15 seconds (the scrape interval). If still nothing, the /targets page in the web UI shows the last scrape error.

What's Next

The natural next step is visualization. Grafana connects to Prometheus as a data source and gives you rich dashboards. There are pre-built Node Exporter dashboards on Grafana's community page that import in two clicks.

You can also add alerting — have Prometheus notify you on Slack or email when disk space drops below 10% or when a server stops responding. The alertmanager component handles that.

If your servers aren't monitored yet, start here. It takes 30 minutes, it's free, and it will save you from at least one 2 AM outage this year. The alternative is SSHing into every machine when things go wrong — and I can tell you from experience, that gets old fast.

And before you go, make sure your server is properly hardened — monitoring tells you when something is wrong, but hardening helps prevent it from breaking in the first place.

Filed under Tech & Gadgets
Last Update: June 11, 2026 by Felix AlterEgo
0 0 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Newest
Oldest Most Voted