
Grafana: the single pane of glass for your whole infrastructure
A server is dragging at 3 AM. Which one, and why? With nowhere to look, the answer is a frantic ssh across five machines, a top that shows you one second of the system’s life, and a vague feeling that “it was fine yesterday”. With a wall of dashboards in front of you, the answer is a glance away: node 3 climbed on I/O forty minutes ago, exactly when a backup kicked off, and the CPU is actually normal. That is the difference Grafana makes.
Grafana , the open-source visualization layer from Grafana Labs , is effectively the de facto standard for the “single pane of glass” that infrastructure teams stare at. As of version 13.0 (released April 2026) it is licensed under AGPLv3, has tens of thousands of stars on GitHub, and runs on anything from a home Raspberry Pi to fleets of thousands of servers. We have been running it in front of our own infrastructure, in our Bucharest datacenter, for years. This post is the field report.
What Grafana actually is
First confusion to clear up: Grafana is not a complete monitoring system, it is the visualization and alerting layer on top of one. It does not collect metrics itself, it does not store time series, and it has no agent crawling your servers. Grafana connects to a data source that already holds the numbers, queries it, and draws it into dashboards.
That is the single most important thing to understand before anything else: Grafana needs a data backend behind it. The most common pairing is Grafana plus Prometheus
or, as we run it, VictoriaMetrics
(a drop-in Prometheus-compatible store that is several times more disk-efficient). Prometheus/VictoriaMetrics scrape metrics from exporters (node_exporter for hosts, cadvisor for containers, SNMP exporters for switches), store them, and Grafana reads them back through PromQL and turns them into graphs.
Architecturally, Grafana is a service written in Go with a TypeScript/React frontend, and it keeps its own configuration (dashboards, users, data sources, alert rules) in a database (SQLite by default, or PostgreSQL/MySQL for large setups). Do not confuse that database with your monitoring data: the Grafana database only holds metadata, the time series live in the data source.
Why the data-source model matters
Grafana’s real power is that it decouples visualization from storage. The same dashboard can combine, on one screen, panels that pull from three different sources: metrics from VictoriaMetrics, logs from Loki , and a direct query into an application PostgreSQL. You are not locked to a single data vendor. When someone tells you “the app was slow at 14:32”, you put a latency panel next to an error-log panel next to a CPU panel, all lined up on the same time axis, and you see the correlation at a glance.
Grafana supports dozens of native data sources: Prometheus, VictoriaMetrics, Loki, Tempo (traces), InfluxDB, Graphite, Elasticsearch, PostgreSQL, MySQL, CloudWatch and many more via plugins. In practice you pick the metrics backend by scale, and Grafana stays constant on top.
What you get out of the box
The open-source edition (Grafana OSS, which is what we are talking about; there is also a commercial Enterprise edition, more on it below) ships with everything you need for serious observability:
- Dashboards and panels of every kind: time-series, gauge, stat, table, heatmap, bar chart, state timeline. Each panel is a query plus a visual representation.
- Unified alerting: alert rules that evaluate a query on an interval and fire when a threshold is crossed, with contact points (email, Slack, Telegram, webhook, PagerDuty) and notification policies that route the alerts.
- Explore, an ad-hoc query mode for when you want to dig into PromQL or LogQL without building a dashboard, exactly what you need in the middle of an incident.
- Provisioning as-code: data sources, dashboards and alert rules can be defined in YAML/JSON files version-controlled in Git, not just clicked into the UI (more on this below, it is the single best thing to do).
- Variables and templating: one dashboard with a
$hostdropdown that shows any server in the fleet, instead of one dashboard per machine. - Transformations: joins, calculations and filters on query results, right in the panel, without touching the data source.
- Flexible authentication: native login, OAuth (Google, GitHub, generic OIDC), LDAP, or reverse-proxy auth (how we do it, with a header injected by an SSO layer in front).
- Annotations: markers on the time axis for deploys, incidents or maintenance windows, so you immediately see “aha, the graph jumped exactly when we shipped”.
What it does not do: Grafana does not collect metrics (that is the exporters plus Prometheus/VictoriaMetrics), does not aggregate logs itself (that is Loki or Elasticsearch), and does not replace an ITIL system with ticketing and acknowledgement. It is the visualization and alerting layer, and it is the best at it.
Installing Grafana on a VPS
Grafana is a single Go binary, so installing it is easy. The cleanest way on a modern server is via Docker, alongside a metrics backend. A minimal docker compose example, Grafana plus VictoriaMetrics:
services:
victoriametrics:
image: victoriametrics/victoria-metrics:latest
command: ["--retentionPeriod=12", "--storageDataPath=/vmdata"]
volumes:
- ./vmdata:/vmdata
grafana:
image: grafana/grafana-oss:13.0.0
ports:
- "3000:3000"
volumes:
- ./grafana:/var/lib/grafana
- ./provisioning:/etc/grafana/provisioning
environment:
GF_SECURITY_ADMIN_PASSWORD: "change-me"
Bring the stack up with docker compose up -d, then the UI is at http://<your-server-ip>:3000/ with user admin and the password you set. The first thing you do: wire up the data source. Not by clicking, but through provisioning (see below) so it is reproducible.
As with any management interface, port 3000 should not be exposed to the whole world without a protection layer. Either put it behind a reverse proxy with TLS and authentication, or restrict it to your IPs with a firewall rule:
ufw allow from YOUR_OFFICE_IP to any port 3000 proto tcp
ufw deny 3000
If you are running this on a DreamServer VPS , put the same rule in your provider’s network firewall too, do not rely on host-level rules alone for management interfaces.
Dashboards-as-code: the single best thing you can do
The temptation at first is to build everything in the UI: add the data source with clicks, make dashboards by hand, set alerts from the interface. It works, but you have built a black box you cannot recreate if the server dies. The clean solution is provisioning, where everything about the configuration lives in files version-controlled in Git.
The data source, a YAML file:
# /etc/grafana/provisioning/datasources/vm.yaml
apiVersion: 1
datasources:
- name: VictoriaMetrics
type: prometheus
access: proxy
url: http://victoriametrics:8428
isDefault: true
A dashboard provider that auto-loads any JSON from a folder:
# /etc/grafana/provisioning/dashboards/default.yaml
apiVersion: 1
providers:
- name: DreamServer
folder: DreamServer
type: file
options:
path: /var/lib/grafana/dashboards
And the dashboards themselves are JSON files in that folder. You do not have to write them from scratch: the Grafana community has thousands of ready-made dashboards at grafana.com/dashboards . A few we use and recommend:
- Node Exporter Full (ID
1860): everything you could want about a Linux host, CPU/RAM/disk/network, at an absurd level of detail. - Ceph Cluster: the health of a Ceph storage cluster.
- A container dashboard via cAdvisor, so you see which container is eating the CPU, not just that the host is loaded.
You import them once, save them as JSON in the provisioned folder, and from there they are in Git. On the next deploy, a fresh Grafana comes up with all the dashboards already there. That is the difference between “I have a Grafana” and “I have an observability platform I can rebuild in a minute”.
Configuration patterns worth knowing
A few things we found genuinely useful beyond the defaults.
Reverse-proxy authentication
Grafana’s native login is fine for a single person, but if you already run company SSO, disable it and let a reverse proxy do the authentication, injecting the user into a header:
[auth.proxy]
enabled = true
header_name = X-WEBAUTH-USER
auto_sign_up = true
That way people log in once, through the company identity, and Grafana creates them automatically on first access. When someone leaves, you disable them in the SSO and their access to the dashboards vanishes.
One dashboard with variables, not fifty dashboards
Do not build one dashboard per server. Build a single one with a $host variable populated from a query (label_values(node_uname_info, instance)) and a dropdown that swaps the whole page between machines. Add a new server to the fleet and it shows up in the dropdown on its own. Less to maintain, easier to compare two nodes.
Alert on symptoms, not causes
The temptation is to put an alert on every metric. The result is noise and alerts you learn to ignore. Alert on what hurts the user: a disk nearly full, a service that stopped responding, latency that jumped, an error rate that is climbing. CPU at 90% is not a problem if the app responds fine. Keep the number of alerts small enough that you wake up for every one.
Send alerts somewhere you actually see them
An email contact point is the minimum; a dedicated Slack/Telegram channel is better, because alerts do not drown in an inbox. Configure failure with a threshold of a few consecutive evaluations so it does not scream at the first transient spike, and enable the resolved notification so you know when it settled on its own.
Read Explore mode before building panels
When you investigate something new, do not build a dashboard. Open Explore, write ad-hoc PromQL queries, see which metrics exist and what they look like. Only after you have found the query that says something do you put it in a panel. Explore is where you understand the data; the dashboard is where you present it.
Where Grafana is not the right answer
It is worth being honest about the limits.
- Not a database. Without a metrics backend (Prometheus, VictoriaMetrics, InfluxDB) there is nothing to visualize. Grafana alone monitors nothing; it is the top half of the stack.
- Does not collect logs itself. For logs you need Loki or Elasticsearch behind it. Grafana draws them, but something else gathers them.
- Not a replacement for a classic auto-discovery monitoring system. Tools like Checkmk or Zabbix discover services on their own, keep hardware/software inventory, and have an ITIL acknowledgement workflow. Grafana is complementary: graphs and correlation, not ticketing. We run it in parallel with Checkmk without them stepping on each other.
- AGPLv3 matters if you modify and offer it as a service. For internal use, the license does not touch you. But if you modify Grafana and offer it as a network service, you are obligated to publish your changes. For the vast majority of cases, irrelevant.
- Enterprise features are closed. Scheduled PDF reports, granular RBAC, LDAP team sync and a few enterprise data-source plugins (Splunk, Oracle, ServiceNow) are in the commercial edition. The OSS edition is generous, but if you need reports emailed automatically to management, plan accordingly.
Alternatives we considered
For completeness: we also looked at Kibana (excellent if you live in the Elasticsearch ecosystem, weaker outside it), Netdata (sensational for instant per-node visibility with zero configuration, but less suited as a centralized fleet pane), Zabbix and Checkmk (complete monitoring systems with auto-discovery and alerting, but with more rigid graphing), and Perses (a newer, fully open-source, dashboard-as-code-first project, worth watching).
Grafana ended up being the cleanest fit for “I want a single pane over which I can put any data source and correlate everything, without locking into a vendor”. Your weights might be different.
So, should you run it?
If you manage more than a few servers and you are tired of ssh-ing into each one when something goes wrong, Grafana plus a metrics backend (VictoriaMetrics is our pick) is worth a Sunday afternoon. The install is fast, community dashboards give you value in five minutes, and the first time a graph shows you the cause of an incident before you even manage to panic, you will know it has earned a permanent place in your stack.
If you run it in production, keep the configuration in Git through provisioning, put it behind SSO, and treat its database (SQLite or Postgres) as infrastructure with backups. Dashboards rebuild from JSON in a minute; what you would actually lose are the users, the alerts and the annotation history.
We run Grafana over VictoriaMetrics for our entire fleet, with dashboards provisioned from Git and alerts on email, and we recommend it to any customer who asks how to see their infrastructure. If you want to try it on infrastructure you do not have to build first, our VPS plans start at small enough sizes to make the experiment cheap, and our server administration service covers the install, the metrics backend and tuning if you would rather skip the learning curve.
Either way, putting a dashboard in front of yourself is a better way to spend an evening than another top on another server. The code is on GitHub, a docker compose stack has you running in five minutes, and you will know within an hour whether it earns a spot in front of your infrastructure.