WIUNIX ACADEMY
Build a Prometheus + Grafana monitoring stack
Page 3 of 5. Review the earlier steps and prerequisites before continuing.
YOUR SYSTEM. YOUR STEPS.
Where are you working?
Choose your OS and version. The prerequisites, commands and troubleshooting follow your environment.
USE YOUR OWN VALUES
Configure this tutorial
Set the example values for your environment; related explanations and copy panels update together. Never enter passwords, private keys or tokens. Values stay in this tab and are not sent to the server or share links. Check actual DNS, certificates and network policy before running commands.
Different IP addresses, domains or ports? Open the settings below, change the values and select “Apply to tutorial”, then copy the updated commands.
Set values for my environment2 editable values
LET’S BUILD
Query Prometheus directly before you open Grafana
Initial scrapes take time. Retry the API a bounded 12 times, with five seconds between attempts. Require HTTP 200, API status success and up=1 for the exact local Prometheus and node_exporter instances.
Monitoring server terminal.
(
set -euo pipefail
response=$(mktemp)
trap 'rm -f "$response"' EXIT
ok=0
for attempt in $(seq 1 12); do
if code=$(curl -sS --connect-timeout 2 --max-time 5 -G \
--data-urlencode 'query=up' -o "$response" -w '%{http_code}' \
http://127.0.0.1:9090/api/v1/query); then
if [ "$code" = 200 ] && jq -e '.status == "success" and .data.resultType == "vector" and any(.data.result[]; .metric.job == "prometheus" and .metric.instance == "127.0.0.1:9090" and .value[1] == "1") and any(.data.result[]; .metric.job == "node-exporter" and .metric.instance == "127.0.0.1:9100" and .value[1] == "1")' "$response" >/dev/null; then
ok=1; break
fi
fi
sleep 5
done
[ "$ok" = 1 ] || { cat "$response" >&2; echo 'Both local targets must have up=1' >&2; exit 1; }
jq . "$response"
)Illustrative result excerpt; actual timestamps vary:
{"status":"success","data":{"resultType":"vector","result":[{"metric":{"job":"prometheus","instance":"127.0.0.1:9090"},"value":[1792444800,"1"]},{"metric":{"job":"node-exporter","instance":"127.0.0.1:9100"},"value":[1792444800,"1"]}]}}The response status is success and the result contains value 1 for both the prometheus and node-exporter jobs.
The query returns an empty result
Review the discovered targets to see whether Prometheus can scrape each job and whether any target is marked down.
curl -fsS --connect-timeout 2 --max-time 5 http://127.0.0.1:9090/api/v1/targets | jq .Prepare private Grafana binding before installation
Create this systemd override before installing the package, so even a package-triggered start binds only to loopback.
Monitoring server terminal.
(
set -euo pipefail
sudo install -d -m 0755 /etc/systemd/system/grafana-server.service.d
sudo nano /etc/systemd/system/grafana-server.service.d/academy-local.conf
)The command completes successfully; stop and inspect any error before continuing.
Grafana private binding override
Paste this file, save and exit. The environment override takes precedence over grafana.ini. An approved TLS reverse proxy can later use this same local listener.
File contents; save in the named file, not in the shell.
[Service]
Environment="GF_SERVER_HTTP_ADDR=127.0.0.1"
Only a loopback bind is configured.
LET’S BUILD
Install Grafana from the official APT repository
Grafana documents the Debian and Ubuntu APT repository as the standard installation path. This guide installs the OSS package named grafana. If your environment requires the free Enterprise build instead, switch only the package name and keep the same repository steps.
The repository key is stored under /etc/apt/keyrings and the package source list is written under /etc/apt/sources.list.d.
Monitoring server terminal.
(
set -euo pipefail
sudo systemctl daemon-reload
sudo install -d -m 0755 /etc/apt/keyrings
key=$(mktemp)
trap 'rm -f "$key"' EXIT
curl -fL --connect-timeout 10 --max-time 60 https://apt.grafana.com/gpg-full.key -o "$key"
gpg --show-keys "$key"
sudo install -m 0644 "$key" /etc/apt/keyrings/grafana.asc
printf '%s\n' 'deb [signed-by=/etc/apt/keyrings/grafana.asc] https://apt.grafana.com stable main' | sudo tee /etc/apt/sources.list.d/grafana.list >/dev/null
sudo apt-get update
sudo apt-get install -y grafana
dpkg-query -W -f='${Version}\n' grafana
)APT can read the Grafana repository and installs the grafana package without signature or dependency errors.
APT cannot validate or find the Grafana package
Check the repository file, key file and APT policy output to confirm that the official repository is visible to the package manager.
sudo cat /etc/apt/sources.list.d/grafana.list
sudo ls -l /etc/apt/keyrings/grafana.asc
sudo apt-cache policy grafanaOpen the next configuration file
Open the file, paste the contents in the following panel, then save and exit (nano: Ctrl+O, Enter, Ctrl+X). Do not run file contents as shell commands.
Monitoring server terminal.
sudo nano /etc/grafana/provisioning/datasources/prometheus.yamlThe command completes successfully; stop and inspect any error before continuing.
LET’S BUILD
Provision the Prometheus data source for Grafana
Grafana supports data source provisioning from declarative files. Using provisioning keeps the first setup reproducible and avoids a manual click path for a basic local Prometheus source.
Create the file below so Grafana loads Prometheus as the default data source at startup.
File contents; save in the named file, not in the shell.
apiVersion: 1
datasources:
- name: Prometheus
uid: prometheus-local
type: prometheus
access: proxy
url: http://127.0.0.1:9090
isDefault: true
editable: true
The provisioning file exists and points Grafana to the local Prometheus API.