Grafana is an open-source analytics and visualization platform that turns time-series data into actionable dashboards. Prometheus is a CNCF-graduated monitoring system that collects metrics from targets using a pull model and stores them in a time-series database. Together, they form the standard monitoring stack for Linux servers, containers, and applications.

This guide walks through installing Grafana with Prometheus on Oracle Linux 9 and Oracle Linux 10. We cover Prometheus binary installation with systemd, node_exporter for host metrics, Grafana OSS from the official RPM repository, dashboard imports, alerting rules, YAML-based provisioning, and an Nginx reverse proxy with Let’s Encrypt SSL.

Prerequisites

Before starting, confirm the following are in place.

  • A server running Oracle Linux 9 or Oracle Linux 10 with at least 2 GB RAM and 2 CPU cores
  • Root or sudo access
  • A registered domain name pointing to the server IP (for Nginx SSL section)
  • Ports 3000/tcp (Grafana), 9090/tcp (Prometheus), 9100/tcp (node_exporter), 80/tcp, and 443/tcp open
  • Internet connectivity to download packages and binaries

Update your system packages before proceeding.

sudo dnf update -y

Step 1: Install Prometheus on Oracle Linux 9/10

Prometheus is distributed as a standalone binary. We download the latest release, create a dedicated system user, and configure systemd to manage the process.

Create Prometheus System User and Directories

Create a dedicated user with no login shell and the required directory structure.

sudo useradd --no-create-home --shell /bin/false prometheus
sudo mkdir -p /etc/prometheus /var/lib/prometheus
sudo chown prometheus:prometheus /etc/prometheus /var/lib/prometheus

Download and Extract Prometheus Binary

Fetch the latest Prometheus release from GitHub and extract it.

VER=$(curl -s https://api.github.com/repos/prometheus/prometheus/releases/latest | grep tag_name | cut -d '"' -f 4 | sed 's/v//')
echo "Downloading Prometheus version ${VER}"
wget https://github.com/prometheus/prometheus/releases/download/v${VER}/prometheus-${VER}.linux-amd64.tar.gz
tar -xvzf prometheus-${VER}.linux-amd64.tar.gz

Copy the binaries and supporting files into the correct locations.

sudo cp prometheus-${VER}.linux-amd64/prometheus /usr/local/bin/
sudo cp prometheus-${VER}.linux-amd64/promtool /usr/local/bin/
sudo cp -r prometheus-${VER}.linux-amd64/consoles /etc/prometheus/
sudo cp -r prometheus-${VER}.linux-amd64/console_libraries /etc/prometheus/
sudo chown -R prometheus:prometheus /usr/local/bin/prometheus /usr/local/bin/promtool
sudo chown -R prometheus:prometheus /etc/prometheus

Verify the installed version.

$ prometheus --version
prometheus, version 3.2.1 (branch: HEAD, revision: xxxxxxx)
  build user:       root@builder
  build date:       2025-xx-xx
  go version:       go1.23.x
  platform:         linux/amd64

Create Prometheus Configuration File

Write a base configuration that scrapes Prometheus itself. We will add more scrape targets later.

echo 'global:
  scrape_interval: 15s
  evaluation_interval: 15s

rule_files:
  - "alert_rules.yml"

scrape_configs:
  - job_name: "prometheus"
    static_configs:
      - targets: ["localhost:9090"]' | sudo tee /etc/prometheus/prometheus.yml

Set ownership on the configuration file.

sudo chown prometheus:prometheus /etc/prometheus/prometheus.yml

Create the Prometheus Systemd Service

Create the unit file so systemd manages Prometheus startup, restarts, and logging.

echo '[Unit]
Description=Prometheus Monitoring System
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 \
  --storage.tsdb.retention.time=30d
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure

[Install]
WantedBy=multi-user.target' | sudo tee /etc/systemd/system/prometheus.service

Reload systemd, enable, and start Prometheus.

sudo systemctl daemon-reload
sudo systemctl enable --now prometheus

Confirm Prometheus is running.

$ systemctl status prometheus
● prometheus.service - Prometheus Monitoring System
     Loaded: loaded (/etc/systemd/system/prometheus.service; enabled; preset: disabled)
     Active: active (running)
   Main PID: 4521 (prometheus)
      Tasks: 10
     Memory: 85.2M
     CGroup: /system.slice/prometheus.service

Open port 9090/tcp in firewalld so you can reach the Prometheus web UI.

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

Browse to http://192.168.1.10:9090 (replace with your server IP) and confirm the Prometheus expression browser loads.

Step 2: Install Node Exporter for Host Metrics

Node Exporter exposes hardware and kernel metrics (CPU, memory, disk, network) that Prometheus scrapes. Install it on every host you want to monitor with Prometheus and Grafana.

Download and Install Node Exporter

NE_VER=$(curl -s https://api.github.com/repos/prometheus/node_exporter/releases/latest | grep tag_name | cut -d '"' -f 4 | sed 's/v//')
wget https://github.com/prometheus/node_exporter/releases/download/v${NE_VER}/node_exporter-${NE_VER}.linux-amd64.tar.gz
tar -xvzf node_exporter-${NE_VER}.linux-amd64.tar.gz
sudo cp node_exporter-${NE_VER}.linux-amd64/node_exporter /usr/local/bin/
sudo useradd --no-create-home --shell /bin/false node_exporter
sudo chown node_exporter:node_exporter /usr/local/bin/node_exporter

Create Systemd Service for Node Exporter

echo '[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
Restart=on-failure

[Install]
WantedBy=multi-user.target' | sudo tee /etc/systemd/system/node_exporter.service

Enable and start node_exporter.

sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter

Check that the service is running and metrics are exposed on port 9100.

$ systemctl status node_exporter
● node_exporter.service - Prometheus Node Exporter
     Active: active (running)
$ curl -s http://localhost:9100/metrics | head -5
# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 2.3456e-05
go_gc_duration_seconds{quantile="0.25"} 3.1234e-05
go_gc_duration_seconds{quantile="0.5"} 4.5678e-05

Allow port 9100/tcp in the firewall if you scrape this node from a remote Prometheus server.

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

Add Node Exporter Target to Prometheus

Edit the Prometheus configuration to add the node_exporter job.

sudo vi /etc/prometheus/prometheus.yml

Append this block under scrape_configs.

  - job_name: "node_exporter"
    static_configs:
      - targets: ["localhost:9100"]
        labels:
          instance: "oracle-linux-server"

The full /etc/prometheus/prometheus.yml should now look like this.

global:
  scrape_interval: 15s
  evaluation_interval: 15s

rule_files:
  - "alert_rules.yml"

scrape_configs:
  - job_name: "prometheus"
    static_configs:
      - targets: ["localhost:9090"]

  - job_name: "node_exporter"
    static_configs:
      - targets: ["localhost:9100"]
        labels:
          instance: "oracle-linux-server"

Reload Prometheus to pick up the changes without restarting the service.

sudo systemctl reload prometheus

Go to http://192.168.1.10:9090/targets in your browser and verify both targets show a State of UP.

Step 3: Install Grafana OSS on Oracle Linux 9/10

Grafana OSS (Open Source) is available from the official Grafana RPM repository. Installing from the repo ensures future updates come through dnf update.

Add the Grafana RPM Repository

Create the repo file.

echo '[grafana]
name=grafana
baseurl=https://rpm.grafana.com
repo_gpgcheck=1
enabled=1
gpgcheck=1
gpgkey=https://rpm.grafana.com/gpg.key
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt' | sudo tee /etc/yum.repos.d/grafana.repo

Install Grafana

Install the grafana package from the newly added repository.

sudo dnf install -y grafana

Verify the installed version.

$ rpm -qi grafana | grep -E "^(Name|Version)"
Name        : grafana
Version     : 11.5.2

Start and Enable Grafana

Enable the service and start it immediately.

sudo systemctl enable --now grafana-server

Check the service status.

$ systemctl status grafana-server
● grafana-server.service - Grafana instance
     Loaded: loaded (/usr/lib/systemd/system/grafana-server.service; enabled; preset: disabled)
     Active: active (running)
   Main PID: 5612 (grafana)
     Memory: 48.3M
     CGroup: /system.slice/grafana-server.service

Key file locations for the Grafana RPM install:

  • Binary: /usr/sbin/grafana-server
  • Configuration: /etc/grafana/grafana.ini
  • Provisioning: /etc/grafana/provisioning/
  • Logs: /var/log/grafana/grafana.log
  • SQLite database: /var/lib/grafana/grafana.db
  • Plugins: /var/lib/grafana/plugins

Open port 3000/tcp in the firewall for initial access.

sudo firewall-cmd --add-port=3000/tcp --permanent
sudo firewall-cmd --reload

Browse to http://192.168.1.10:3000. Log in with the default credentials – username admin and password admin. Grafana prompts you to set a new password on first login.

Step 4: Configure Prometheus Data Source in Grafana

With both Prometheus and Grafana running, connect them by adding Prometheus as a data source.

  1. In the Grafana sidebar, go to Connections > Data sources
  2. Click Add data source and select Prometheus
  3. Set the Prometheus server URL to http://localhost:9090
  4. Scroll down and click Save & test

You should see the message “Successfully queried the Prometheus API.” If it fails, confirm Prometheus is running and that port 9090 is accessible from the Grafana host.

Step 5: Import Node Exporter Full Dashboard (ID 1860)

The Node Exporter Full dashboard (ID 1860) is a community-maintained Grafana dashboard that shows CPU, memory, disk, network, and dozens of other metrics from node_exporter.

  1. In Grafana, go to Dashboards > New > Import
  2. Enter dashboard ID 1860 and click Load
  3. Select the Prometheus data source from the dropdown
  4. Click Import

The dashboard loads with panels for CPU utilization, memory usage, disk I/O, network traffic, filesystem usage, and system load. Give node_exporter a few minutes to collect enough data points before the graphs start populating.

Step 6: Create Custom Grafana Panels

While imported dashboards are useful, production setups usually need custom panels tailored to your environment. Here is how to create a new dashboard with a few practical panels.

Create a New Dashboard

Go to Dashboards > New > New Dashboard, then click Add visualization. Select the Prometheus data source.

CPU Usage Panel

In the query editor, enter this PromQL expression to show overall CPU usage as a percentage.

100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

Set the panel title to “CPU Usage %” and choose Time series as the visualization type. Under the Axes settings, set the Y-axis unit to Percent (0-100).

Memory Usage Panel

Add another panel with this PromQL query.

(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100

Title it “Memory Usage %” and use the same time series visualization with a percent Y-axis.

Disk Usage Panel

This query shows filesystem usage for the root partition.

(1 - (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"})) * 100

Use a Gauge visualization for this one, with thresholds set to green below 70%, yellow from 70-85%, and red above 85%. Click Apply on each panel, then save the dashboard.

Step 7: Configure Prometheus Alerting Rules

Prometheus evaluates alerting rules at the interval defined in evaluation_interval. When a rule fires, Prometheus marks the alert as pending and then firing. Create a rules file with common alerts.

echo 'groups:
  - name: node_alerts
    rules:
      - alert: HighCPUUsage
        expr: 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "High CPU usage on {{ $labels.instance }}"
          description: "CPU usage is above 85% for more than 5 minutes."

      - alert: HighMemoryUsage
        expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 90
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "High memory usage on {{ $labels.instance }}"
          description: "Memory usage is above 90% for more than 5 minutes."

      - alert: DiskSpaceLow
        expr: (1 - (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"})) * 100 > 85
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Disk space low on {{ $labels.instance }}"
          description: "Root filesystem usage is above 85%."

      - alert: InstanceDown
        expr: up == 0
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Instance {{ $labels.instance }} is down"
          description: "Target has been unreachable for more than 2 minutes."' | sudo tee /etc/prometheus/alert_rules.yml

Set ownership and validate the rules file with promtool.

sudo chown prometheus:prometheus /etc/prometheus/alert_rules.yml
promtool check rules /etc/prometheus/alert_rules.yml

Expected output:

Checking /etc/prometheus/alert_rules.yml
  SUCCESS: 4 rules found

Reload Prometheus to apply the rules.

sudo systemctl reload prometheus

Navigate to http://192.168.1.10:9090/alerts to see all configured alert rules and their current state.

Step 8: Grafana Provisioning via YAML

Grafana supports file-based provisioning for data sources and dashboards. This is useful when deploying Grafana across multiple servers or in infrastructure-as-code workflows – you define everything in YAML and Grafana picks it up on startup.

Provision the Prometheus Data Source

Create a provisioning file for the data source.

echo 'apiVersion: 1

datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://localhost:9090
    isDefault: true
    editable: false' | sudo tee /etc/grafana/provisioning/datasources/prometheus.yml

Provision a Dashboard

Create the dashboard provider configuration.

echo 'apiVersion: 1

providers:
  - name: "default"
    orgId: 1
    folder: "Provisioned"
    type: file
    disableDeletion: false
    updateIntervalSeconds: 60
    options:
      path: /var/lib/grafana/dashboards
      foldersFromFilesStructure: false' | sudo tee /etc/grafana/provisioning/dashboards/default.yml

Create the dashboards directory.

sudo mkdir -p /var/lib/grafana/dashboards
sudo chown grafana:grafana /var/lib/grafana/dashboards

You can export any dashboard as JSON from the Grafana UI (Dashboard > Share > Export) and place the JSON file in /var/lib/grafana/dashboards/. Grafana loads it automatically within 60 seconds.

Restart Grafana to apply the provisioning configuration.

sudo systemctl restart grafana-server

Log back into Grafana and confirm the Prometheus data source appears under Connections without needing manual setup.

Step 9: Set Up Nginx Reverse Proxy with SSL for Grafana

Running Grafana behind Nginx with TLS is the recommended production setup. It allows access over HTTPS on port 443 instead of exposing Grafana directly on port 3000.

Install Nginx and Certbot

sudo dnf install -y nginx
sudo dnf install -y certbot python3-certbot-nginx

Enable and start Nginx.

sudo systemctl enable --now nginx

Open HTTP and HTTPS ports in the firewall.

sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --add-service=https --permanent
sudo firewall-cmd --reload

Configure Nginx Virtual Host

Create an Nginx configuration file for Grafana. Replace grafana.example.com with your actual domain.

echo 'server {
    listen 80;
    server_name grafana.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # WebSocket support for Grafana Live
    location /api/live/ {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }
}' | sudo tee /etc/nginx/conf.d/grafana.conf

Test the Nginx configuration and reload.

sudo nginx -t
sudo systemctl reload nginx

Obtain Let’s Encrypt SSL Certificate

Run Certbot to obtain and configure the SSL certificate automatically. Replace the domain and email with your own values.

sudo certbot --nginx -d grafana.example.com --non-interactive --agree-tos -m [email protected]

Certbot modifies the Nginx config to redirect HTTP to HTTPS and sets up the certificate paths. Verify the auto-renewal timer is active.

$ sudo certbot renew --dry-run
Congratulations, all simulated renewals succeeded

Update Grafana Configuration for Reverse Proxy

Edit the Grafana configuration to recognize the proxy.

sudo vi /etc/grafana/grafana.ini

Find and update the [server] section with these values.

[server]
domain = grafana.example.com
root_url = https://grafana.example.com/
serve_from_sub_path = false

Restart Grafana to apply the changes.

sudo systemctl restart grafana-server

Open https://grafana.example.com in your browser. You should see the Grafana login page served over HTTPS with a valid certificate. At this point, remove the direct port 3000 access from the firewall since all traffic should go through Nginx.

sudo firewall-cmd --remove-port=3000/tcp --permanent
sudo firewall-cmd --reload

Step 10: SELinux Configuration

Oracle Linux 9 and 10 ship with SELinux in enforcing mode. If Nginx cannot connect to Grafana’s backend port, SELinux is likely blocking it. Allow Nginx to make network connections.

sudo setsebool -P httpd_can_network_connect 1

Verify the boolean is set.

$ getsebool httpd_can_network_connect
httpd_can_network_connect --> on

This allows Nginx to proxy requests to Grafana and Prometheus without setting SELinux to permissive mode.

Conclusion

We now have a full Prometheus and Grafana monitoring stack running on Oracle Linux. Prometheus collects metrics from node_exporter and itself, alerting rules catch common failure conditions, and Grafana provides dashboards for visualization – all served through Nginx with TLS encryption.

For production environments, consider adding MySQL/MariaDB monitoring with Prometheus exporters, configuring Alertmanager for email or Slack notifications, enabling Grafana authentication via LDAP or OAuth, and setting up regular backups of /var/lib/prometheus and /var/lib/grafana.

Related Guides

LEAVE A REPLY

Please enter your comment!
Please enter your name here