A useful Grafana dashboard is not a collection of every metric your system exposes. It is a small set of visual questions that help an operator understand what the system is doing. With Prometheus and Node Exporter already collecting Linux host metrics, Grafana can turn those time series into panels for CPU, memory, and filesystem utilization.
This tutorial intentionally builds a small dashboard instead of importing a large community dashboard. That makes the PromQL, units, labels, and failure modes visible rather than hiding them behind someone else's JSON.
Last verified: September 10, 2026. Grafana's current documentation identifies Grafana v13.2 as the latest documentation view. UI labels can change, so use the current /latest/ documentation if your interface differs.
What You'll Accomplish
You will:
- confirm that Prometheus contains Node Exporter data;
- configure or select a Prometheus data source in Grafana;
- validate the connection before building panels;
- create CPU, memory, and root-filesystem utilization panels;
- choose appropriate units and legends;
- diagnose common "No data" and label problems; and
- save a dashboard that can later become the basis for server alerting.
Prerequisites
You need:
- a running Grafana instance;
- a Prometheus server reachable from Grafana;
- Node Exporter metrics already scraped by Prometheus;
- Grafana permission to create/edit data sources and dashboards as required;
- familiarity with the Prometheus
instanceandjoblabels in your environment.
This tutorial does not install Prometheus or Node Exporter. If Prometheus does not already show the host target as healthy, fix collection first. Grafana cannot visualize metrics that Prometheus never received.
Quick Answer
First, confirm Prometheus has Node Exporter metrics such as node_cpu_seconds_total. In Grafana, configure a Prometheus data source pointing at the correct Prometheus endpoint and use the connection test. Then create a new dashboard and add three panels. A practical CPU query is 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[$__rate_interval])) * 100). Memory utilization can use (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100. For the root filesystem, use 100 * (1 - node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}), adjusting labels for your environment. Set percentage units, use clear panel titles, and verify each query in Explore or the panel editor before saving.
Step 1: Verify Prometheus Has the Metrics First
Before opening a dashboard editor, prove the data exists.
Prometheus Node Exporter metrics are commonly prefixed with node_. Official Prometheus documentation lists examples including:
node_cpu_seconds_total;node_filesystem_avail_bytes; andnode_exporter_build_info.
Grafana's own Prometheus getting-started material also uses Node Exporter as its Linux host example.
Open Prometheus or Grafana Explore and query:
node_exporter_build_info
If you receive a time series for the target host, Node Exporter data is arriving.
Then check:
node_cpu_seconds_total
If this is empty, do not continue to dashboard design. Check the Prometheus target and scrape configuration.
Why start here?
"Grafana shows no data" is often not a visualization problem. The real cause may be:
- Prometheus is not scraping the host;
- the job or instance label differs from your assumption;
- Grafana points at the wrong Prometheus server; or
- the selected dashboard time range does not include recent samples.
Separating ingestion from visualization prevents unnecessary dashboard troubleshooting.
Step 2: Configure the Prometheus Data Source
Grafana treats Prometheus as a data source: a connection to a backend that stores/queryable metrics.
In current Grafana, add or open the Prometheus data source from the data-source configuration area. The exact navigation can vary between Grafana editions and releases, but the important settings are:
- the Prometheus server URL;
- authentication/TLS options if your server requires them;
- access permissions; and
- any organization-specific connection settings.
Use the data-source connection test before moving on.
Use the URL Grafana can actually reach
A common mistake is entering:
http://localhost:9090
when Grafana runs in a separate container or host.
Inside a Grafana container, localhost means the Grafana container itself, not automatically the Prometheus container.
Use a service hostname, private DNS name, or network address appropriate to the deployment.
Do not expose an unauthenticated Prometheus server publicly just so Grafana can reach it. Prefer private networking or documented authentication/TLS controls.
Step 3: Validate Prometheus in Grafana Explore
Before making a dashboard, open Grafana Explore or the Prometheus query editor and run:
node_cpu_seconds_total
Filter to one host if necessary:
node_cpu_seconds_total{instance="<YOUR_INSTANCE>"}
Replace <YOUR_INSTANCE> with an actual label value visible in your data.
Confirm:
- samples are recent;
- the expected
instancelabel exists; - the expected
joblabel exists; and - you understand whether multiple CPU/core/mode series are present.
This matters because CPU metrics are not one scalar per server. node_cpu_seconds_total is a counter broken down by labels such as CPU and mode. The dashboard query must aggregate intentionally.
Step 4: Create a New Dashboard
Create a dashboard and add a visualization/panel using the Prometheus data source.
Grafana's current dashboard documentation requires each panel to have at least one query.
Start with three panels:
- CPU utilization;
- memory utilization;
- filesystem utilization.
Do not add twenty panels yet. The goal is to understand each query and presentation choice.
A dashboard is more maintainable when every panel has an obvious operational question.
Step 5: Add a CPU Utilization Panel
Grafana's current Prometheus query documentation provides this CPU utilization pattern:
100 - (
avg by (instance) (
rate(node_cpu_seconds_total{mode="idle"}[$__rate_interval])
) * 100
)
What the query does
node_cpu_seconds_total{mode="idle"} is a cumulative counter of idle CPU time.
rate(...[$__rate_interval]) estimates how quickly that counter increases over the selected interval.
avg by (instance) averages the idle proportion across CPU cores for each instance.
Subtracting the result from 100 converts idle percentage into utilization percentage.
Grafana's $__rate_interval is useful in dashboard queries because Grafana chooses an interval based on the query/display context.
Configure the panel
Use a title such as:
CPU utilization
Set the field unit to a percentage. A time-series visualization is useful because the operational value is not just the latest CPU number but how it behaves over time.
Use {{instance}} or an equivalent concise legend if multiple hosts appear.
If the panel contains more hosts than intended, add an explicit label filter after verifying your labels:
100 - (
avg by (instance) (
rate(node_cpu_seconds_total{job="node", mode="idle"}[$__rate_interval])
) * 100
)
Do not copy job="node" unless your actual scrape job is named node.
Step 6: Add a Memory Utilization Panel
Grafana's current Prometheus alerting documentation uses this memory-utilization expression:
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100
This estimates the percentage of memory that is not currently available.
Use a panel title such as:
Memory utilization
Set the unit to percentage.
Why use MemAvailable?
Linux memory accounting can be misleading if you treat every byte outside MemFree as unavailable. MemAvailable is generally a better signal for memory that can be used by applications without swapping/reclaiming more aggressively.
If the query returns multiple hosts, use clear legends and filters just as you did for CPU.
Do not hide label mismatches with Grafana transformations if the PromQL itself should identify the intended host. Query logic should remain understandable.
Step 7: Add a Filesystem Utilization Panel
For a specific filesystem, the relationship is:
100 * (
1 -
node_filesystem_avail_bytes{mountpoint="/"}
/
node_filesystem_size_bytes{mountpoint="/"}
)
Grafana documentation uses the same 1 - available / size relationship for disk utilization in current Prometheus rule examples.
This query measures used capacity for the root mount from the perspective of space available to non-root users.
Filter filesystems deliberately
Node Exporter can expose many mounts, including temporary, container, or virtual filesystems. Do not assume a filter copied from another server is correct for yours.
For a first panel, explicitly targeting:
{mountpoint="/"}
is easier to understand.
Later, if you build a panel across all persistent filesystems, inspect the actual fstype, device, and mountpoint labels first and exclude only the virtual filesystems you have confirmed.
Use a title such as:
Root filesystem utilization
and a percentage unit.
Step 8: Choose Units and Legends That Explain the Data
Correct PromQL with poor presentation can still mislead readers.
For percentage queries:
- set the unit to percent;
- keep the visible range sensible;
- avoid unnecessary decimals;
- label series by the host identifier operators actually recognize.
For raw byte metrics, use a byte unit instead of manually dividing by arbitrary constants unless there is a reason.
For counters, do not chart the raw cumulative value when the operational question is a rate. Use rate() or another appropriate PromQL function.
Avoid red/yellow/green decoration without meaning
Threshold colors can help when they correspond to an operational boundary. They are not a substitute for an alert or an SLO.
A dashboard threshold of 80% should not be copied into an alert simply because the panel looks good. Alerting requires separate reasoning about duration, actionability, and failure impact.
Step 9: Verify Each Panel Before Saving
For every panel, verify three things.
1. The query returns expected series
Use the panel query editor or Explore.
2. The labels identify the intended host
Do not accidentally aggregate two servers into one line because they share a job label.
3. The value is plausible
Compare CPU/memory/filesystem values with host tools or another trusted telemetry source if available.
If Grafana says memory usage is 99% while the host is clearly healthy, inspect the formula and labels before assuming there is an incident.
This guide provides documented queries but does not claim PerfMonitoring executed them in your environment.
Verify the Setup
The dashboard is complete when:
- the Prometheus data source connection is healthy;
node_*metrics are visible in Grafana;- CPU utilization renders for the intended instance(s);
- memory utilization renders for the intended instance(s);
- root filesystem utilization renders for the intended instance(s);
- units are percentages rather than raw ratios;
- panel legends identify hosts unambiguously; and
- the dashboard has been saved with a clear name.
A useful dashboard name might be:
Linux host baseline
rather than New dashboard.
Common Problems and Fixes
Problem: The data source test fails
Cause: Grafana cannot reach the Prometheus URL, authentication/TLS is wrong, or localhost refers to the wrong runtime.
Fix: test network reachability from the Grafana environment. Use the correct service name or private address and validate the Prometheus endpoint securely.
Problem: Prometheus has data but Grafana shows No data
Cause: Grafana points to a different Prometheus server, the dashboard time range is wrong, or the query filters labels that do not exist.
Fix: run the raw metric in Grafana Explore. Remove filters, inspect labels, and add constraints back one at a time.
Problem: CPU has many lines per host
Cause: node_cpu_seconds_total has dimensions for CPU cores and modes.
Fix: use the documented aggregation/rate expression instead of charting the raw counter.
Problem: Memory is shown as a number between 0 and 1
Cause: the expression returns a ratio and was not multiplied by 100, or the Grafana unit expects a different scale.
Fix: keep the query/unit consistent. This tutorial uses * 100 and a 0–100 percentage display.
Problem: The filesystem panel shows dozens of mounts
Cause: Node Exporter exposes each filesystem/mount.
Fix: start with a specific mountpoint="/" filter. Build a broader panel only after understanding which filesystem labels represent real persistent storage.
Problem: A query copied from the dashboard fails in an alert
Cause: dashboard queries can use template variables and Grafana macros that may not be valid in the alerting context. Current Grafana docs explicitly note that alert queries do not support dashboard template variables.
Fix: write alert-specific PromQL with concrete label values and a fixed range where required. The sibling alerting tutorial demonstrates that separation.
Best Practices
Build the first dashboard yourself
Importing a community dashboard can be useful later, but building three panels teaches you the metric names, labels, units, and queries that your alerts will depend on.
Keep PromQL readable
Prefer a few lines with meaningful aggregation over deeply nested expressions that nobody on the team can explain.
Put operational context in panel descriptions
A short note about the metric, scope, or expected interpretation can save time during an incident.
Use dashboard variables only when they add navigation value
A host variable can make a shared dashboard reusable, but it also increases complexity. Start without variables if the dashboard is for one server.
Do not use dashboards as the only alert mechanism
Dashboards are for exploration and situational awareness. Humans do not watch them continuously. Use an alert rule for conditions that require notification.
When This Setup Makes Sense
This dashboard is appropriate when:
- Prometheus already collects Node Exporter metrics;
- operators need a small Linux host overview;
- you want to learn/own the PromQL rather than depend on an opaque imported dashboard; and
- CPU, memory, and filesystem pressure are useful first signals.
For dozens or hundreds of hosts, you will likely add variables, recording rules, fleet-oriented dashboards, and more deliberate query/cardinality design.
For notification, continue with the sibling tutorial on Grafana-managed alerts.
FAQ
Should I import a Node Exporter dashboard or build my own?
For learning and a small production baseline, building a few panels yourself makes the metric and query semantics explicit. Import a community/vendor dashboard later when you have reviewed what its queries assume.
Why does Grafana show No data when Prometheus has metrics?
Common causes are the wrong data source, time range, or label filter. Test the raw metric in Grafana Explore and inspect the actual labels before debugging visualization settings.
What does $__rate_interval do?
Grafana uses $__rate_interval to provide a query range appropriate for rate calculations in dashboard queries. It reduces the need to hard-code one range for every zoom level.
Why use MemAvailable instead of MemFree?
Available memory is generally a more useful Linux capacity signal because it includes memory the kernel can reclaim for applications, not just bytes currently classified as completely free.
Conclusion
A good first Grafana Prometheus dashboard can be only three panels. What matters is that each query is understood and verified.
Start by proving Prometheus has fresh Node Exporter data, verify the Grafana data source, then create CPU, memory, and filesystem panels with clear units and labels. Troubleshoot data and label problems at the query layer before adding visualization complexity.
Once the dashboard reliably describes the host, use How to Create Grafana Alerts for Server Metrics to turn selected symptoms into actionable notifications.
References
- Grafana Labs Documentation — "Get started with Grafana and Prometheus" — https://grafana.com/docs/grafana/latest/fundamentals/getting-started/first-dashboards/get-started-grafana-prometheus/ — accessed September 10, 2026.
- Grafana Labs Documentation — "Create dashboards" — https://grafana.com/docs/grafana/latest/visualizations/dashboards/build-dashboards/create-dashboard/ — accessed September 10, 2026.
- Grafana Labs Documentation — "Prometheus query editor" — https://grafana.com/docs/grafana/latest/datasources/prometheus/query-editor/ — accessed September 10, 2026.
- Grafana Labs Documentation — "Prometheus alerting" — https://grafana.com/docs/grafana/latest/datasources/prometheus/alerting/ — accessed September 10, 2026.
- Prometheus Documentation — "Monitoring Linux host metrics with the Node Exporter" — https://prometheus.io/docs/guides/node-exporter/ — accessed September 10, 2026.