How to Install Prometheus and Node Exporter on CentOS Stream 9

If you are managing enterprise hardware or dedicated servers, having real-time visibility into your infrastructure is non-negotiable. Prometheus is an industry-standard, open-source monitoring and alerting toolkit. When paired with Node Exporter, it becomes a powerhouse for collecting Linux host metrics like CPU usage, memory consumption, load averages, and network interface statistics.

In this guide, we will show you exactly how to install Prometheus and Node Exporter on CentOS Stream 9. Instead of relying on outdated third-party RPMs, we will use the official upstream binaries. This SysAdmin-approved approach is cleaner, easy to audit, and simple to keep updated.

Prerequisites

Before diving into the installation, ensure you have the following:

  • A CentOS Stream 9 server
  • root or sudo privileges.
  • Firewalld enabled.
  • Server Architecture Knowledge: Know whether you are running x86_64 (Intel/AMD) or aarch64 (Ampere ARM).
✅ Why this matters: Monitoring many devices creates heavy disk writes. NVMe reduces I/O wait and improves database performance.

Step 1 Update the System and Install Dependencies

First, ensure your system is up to date and that you have the necessary base packages to download, extract, and verify our files.

Bash

dnf -y update
dnf -y install curl tar coreutils
    

Step 2 Create Dedicated Service Users

For security purposes, services should never run as root. We will create dedicated system users and directories for Prometheus and Node Exporter.

Bash

useradd --system --no-create-home --shell /sbin/nologin prometheus
useradd --system --no-create-home --shell /sbin/nologin node_exporter

install -d -o prometheus -g prometheus -m 0755 /etc/prometheus
install -d -o prometheus -g prometheus -m 0755 /var/lib/prometheus

    

Step 3 Download and Verify Official Binaries

Next, we will pull the official precompiled binaries. As of April 10, 2026, the latest stable versions are Prometheus 3.11.1 and Node Exporter 1.11.1.

⚠️ Note: Prometheus 3.5.1 is the current LTS if your environment requires strict Long Term Support

We will also download the SHA256 checksums to verify the integrity of the downloaded archives.

Bash

cd /tmp

case "$(uname -m)" in
  x86_64) ARCH="amd64" ;;
  aarch64|arm64) ARCH="arm64" ;;
  *)
    echo "Unsupported architecture: $(uname -m)"
    exit 1
    ;;
esac

PROM_VERSION="3.11.1"
NODE_EXPORTER_VERSION="1.11.1"

# Download Prometheus and Checksum
curl -LO "https://github.com/prometheus/prometheus/releases/download/v${PROM_VERSION}/prometheus-${PROM_VERSION}.linux-${ARCH}.tar.gz"
curl -LO "https://github.com/prometheus/prometheus/releases/download/v${PROM_VERSION}/sha256sums.txt"


# Verify Prometheus Checksum
grep "prometheus-${PROM_VERSION}.linux-${ARCH}.tar.gz" sha256sums.txt | sha256sum -c -


# Download Node Exporter and Checksum (Rename sha256sums.txt to avoid overwrite)
curl -LO "https://github.com/prometheus/node_exporter/releases/download/v${NODE_EXPORTER_VERSION}/node_exporter-${NODE_EXPORTER_VERSION}.linux-${ARCH}.tar.gz"
curl -L "https://github.com/prometheus/node_exporter/releases/download/v${NODE_EXPORTER_VERSION}/sha256sums.txt" -o sha256sums_node.txt


# Verify Node Exporter Checksum
grep "node_exporter-${NODE_EXPORTER_VERSION}.linux-${ARCH}.tar.gz" sha256sums_node.txt | sha256sum -c -


# Extract if checksums pass
tar -xzf "prometheus-${PROM_VERSION}.linux-${ARCH}.tar.gz"
tar -xzf "node_exporter-${NODE_EXPORTER_VERSION}.linux-${ARCH}.tar.gz"


    
⚠️ Note: Only proceed if the sha256sum commands output OK. This guarantees your binaries are authentic and uncorrupted.

Step 4 Install Binaries and Console Files

Move the extracted binaries to /usr/local/bin and copy the necessary console templates to the Prometheus configuration directory.

Bash

install -m 0755 "/tmp/prometheus-${PROM_VERSION}.linux-${ARCH}/prometheus" /usr/local/bin/prometheus
install -m 0755 "/tmp/prometheus-${PROM_VERSION}.linux-${ARCH}/promtool" /usr/local/bin/promtool
install -m 0755 "/tmp/node_exporter-${NODE_EXPORTER_VERSION}.linux-${ARCH}/node_exporter" /usr/local/bin/node_exporter

cp -r "/tmp/prometheus-${PROM_VERSION}.linux-${ARCH}/consoles" /etc/prometheus/
cp -r "/tmp/prometheus-${PROM_VERSION}.linux-${ARCH}/console_libraries" /etc/prometheus/

chown -R prometheus:prometheus /etc/prometheus /var/lib/prometheus
    

Step 5 Configure Prometheus

Prometheus needs to know what to monitor. We define these targets in a configuration file using scrape_configs. Create the configuration file:

Bash

cat > /etc/prometheus/prometheus.yml <<'EOF'
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['127.0.0.1:9090']

  - job_name: 'node'
    static_configs:
      - targets: ['127.0.0.1:9100']
EOF

chown prometheus:prometheus /etc/prometheus/prometheus.yml
chmod 0644 /etc/prometheus/prometheus.yml
    
❓ What this does: Prometheus will scrape its own internal metrics on port 9090, and scrape the local Node Exporter metrics on port 9100.

Step 6 Create Systemd Services

To ensure Prometheus and Node Exporter run in the background and start automatically on boot, we need to create systemd unit files.

Create the Prometheus Service

Bash

cat > /etc/systemd/system/prometheus.service <<'EOF'
[Unit]
Description=Prometheus Monitoring Server
Wants=network-online.target
After=network-online.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.console.templates=/etc/prometheus/consoles \
  --web.console.libraries=/etc/prometheus/console_libraries \
  --web.listen-address=0.0.0.0:9090 \
  --storage.tsdb.retention.time=15d
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

    
⚠️ Note: We explicitly defined --storage.tsdb.retention.time=15d. Prometheus defaults to 15 days of data retention. You can increase or decrease this based on your available disk space

Create the Node Exporter Service

For a local setup, we bind Node Exporter specifically to 127.0.0.1 (localhost) to prevent unauthorized external access.

Bash

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 \
  --web.listen-address=127.0.0.1:9100
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF
    

Step 7 Start and Validate Services

Verify your Prometheus configuration syntax before starting the services:

Bash

/usr/local/bin/promtool check config /etc/prometheus/prometheus.yml
    

If it checks out, reload systemd and start the services:

Bash

systemctl daemon-reload
systemctl enable --now prometheus
systemctl enable --now node_exporter
    

Check the status and listening ports:

Bash

systemctl status prometheus --no-pager
systemctl status node_exporter --no-pager
ss -lntp | egrep '9090|9100'
    

Step 8 Verify Metrics Locally

Let's ensure the services are responding to HTTP requests using Prometheus's official health check endpoints:

Bash

curl -fsS http://127.0.0.1:9090/-/healthy
curl -fsS http://127.0.0.1:9100/metrics | head
    

If these commands return output without errors, your base installation is successful!

Step 9 Configure the Firewall & Security Warning

If you want to access the Prometheus web UI from your browser, you can open port 9090 in Firewalld.

Bash

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

If these commands return output without errors, your base installation is successful!

⚠️ CRITICAL SECURITY WARNING: Exposing port 9090 directly to the public internet is highly discouraged for production environments. The default Prometheus UI does not have authentication enabled out of the box. Do not leave this open publicly. Instead, secure your setup using a Reverse Proxy (like Nginx/Apache), a VPN (like WireGuard/Tailscale), or by configuring Prometheus's native Basic Auth and TLS via its web configuration file.
🚨 Never open port 9100 (Node Exporter) to the public internet.

Step 10 Access the Web UI and Run PromQL Queries

If you are accessing via a secure tunnel or local network, open your web browser and navigate to:

http://YOUR_SERVER_IP:9090/graph

Here, you can use PromQL (Prometheus Query Language) to visualize your data. Try running these initial queries in the expression browser:

  • up - Checks if your scrape targets are online
  • node_load1 - Shows the 1-minute load average.
  • node_memory_MemAvailable_bytes / 1024 / 1024 - Displays available memory in MB.
  • rate(node_network_receive_bytes_total[5m]) - Shows inbound traffic rates.
  • rate(node_network_transmit_bytes_total[5m]) - Shows outbound traffic rates.

Expanding Your Monitoring Stack

Adding Remote Linux Servers

In a true dedicated server environment, one central Prometheus server monitors multiple remote machines. To add a remote server:

  1. Install Node Exporter on the remote machine.
  2. Bind it to 0.0.0.0:9100.
  3. Use Firewalld on the remote machine to only allow traffic from your Prometheus server's IP.
Bash

firewall-cmd --permanent \
  --add-rich-rule='rule family="ipv4" source address="YOUR_PROMETHEUS_IP/32" port port="9100" protocol="tcp" accept'
firewall-cmd --reload
    

Then, update your central prometheus.yml file to scrape the new targets:

YAML

  - job_name: 'linux-servers'
    static_configs:
      - targets:
          - '10.0.0.11:9100'
          - '10.0.0.12:9100'
    

Restart Prometheus to apply the changes.

Enterprise Production Notes

  • Data Retention: As noted in Step 6, the default retention is 15d. Plan your disk space accordingly or adjust the --storage.tsdb.retention.time flag.
  • Private Networks: Always use a private monitoring network/VLAN when connecting scrape targets.
  • TLS / Web Configs: Node Exporter does support TLS endpoints via a web configuration file, though the official README often notes this as an experimental/evolving feature. Rely on private networking or tunnels first.
  • LTS Releases: For enterprise change-control environments, consider pinning a Long Term Support (LTS) release of Prometheus (like v3.5) instead of tracking the bleeding edge.

Troubleshooting Quick Reference

Prometheus failing to start?

Bash

journalctl -u prometheus -xe
/usr/local/bin/promtool check config /etc/prometheus/prometheus.yml
    

Node Exporter missing metrics?

Bash

journalctl -u node_exporter -xe
curl -fsS http://127.0.0.1:9100/metrics | head
    
📢 Targets showing "DOWN" in the UI? Check firewall rules, verify the target IP/port, ensure Node Exporter is bound to the correct network interface, and confirm the monitored server is reachable.

Conclusion

Setting up a robust monitoring solution doesn't have to be overly complicated. By installing Prometheus and Node Exporter on CentOS Stream 9 using official binaries, you have built a clean, secure, and highly scalable foundation for dedicated server monitoring. Whether you are tracking simple CPU loads or complex bandwidth usage across an entire fleet of Linux servers, this stack gives you the exact visibility you need.

What to Read Next

Ready to take your monitoring stack to the next level? Check out our related guides:

╰┈➤ How to Install Prometheus and Node Exporter

Ready to Deploy Your Monitoring Stack?

You have the knowledge, now get the hardware. Run Prometheus and Node Exporter seamlessly on our high-performance Bare Metal Dedicated Servers. Engineered for 24/7 uptime and real-time data processing.

Deploy Your Dedicated Server Today

Common Mistakes to Avoid When Installing Prometheus on CentOS Stream 9

Using outdated or unofficial packages Relying on old third-party RPMs or unofficial repositories can introduce version mismatches, missing features, and security issues. Stick to one installation method and avoid mixing repository packages with manual binary installs.
Skipping configuration validation A small YAML formatting error in prometheus.yml can prevent Prometheus from starting. Always validate the configuration before restarting the service.
Bash promtool check config /etc/prometheus/prometheus.yml
Exposing Node Exporter to the public internet Binding Node Exporter to 0.0.0.0:9100 without firewall restrictions can expose host-level metrics unnecessarily. For single-server setups, bind it to localhost. For remote scraping, only allow access from the Prometheus server.
Opening firewall ports without source restrictions Opening port 9100 or 9090 is not enough on its own. You should also control which source IP addresses are allowed to connect, especially in production environments.
Using the wrong bind address Prometheus and Node Exporter should listen on interfaces that match your deployment model. A local-only exporter should use 127.0.0.1:9100, while remotely scraped exporters should bind to a private IP or controlled interface.
Ignoring data directory permissions If /var/lib/prometheus has incorrect ownership, Prometheus may fail to write data properly even if the service appears to start.
Bash chown -R prometheus:prometheus /var/lib/prometheus
Assuming up == 1 means everything is working A target showing up == 1 only confirms that Prometheus can scrape it. It does not guarantee that all expected metrics are present or complete.
Failing to plan retention and storage Prometheus uses local time-series storage. If you do not plan disk usage in advance, long retention periods can lead to storage pressure and operational issues.
Forgetting time synchronization If the Prometheus server and monitored nodes are out of sync, graphs, rate calculations, and alerts can become inaccurate. Make sure time synchronization is enabled across all monitored systems.
Updating systemd unit files without reloading systemd After editing a unit file, running restart alone is not enough. You need to reload the systemd daemon first.
Bash systemctl daemon-reload
systemctl restart prometheus
systemctl restart node_exporter
Deploying monitoring without planning alerting ollecting metrics is useful, but production monitoring also needs actionable alerts. At a minimum, plan alerts for host downtime, high CPU load, low available memory, and high filesystem usage..