Grafana
Grafana is an open-source, general purpose dashboarding tool, which runs as a web application. It can be used to create a variety of time-series graphs and also for displaying logs. It supports Prometheus, graphite, InfluxDB, opentsdb, Grafana Loki, PostgreSQL and many other data sources.
See Grafana options
Installation
Grafana is available as NixOS module, it can be enabled using the following config:
services.grafana = {
enable = true;
settings = {
server = {
http_addr = "127.0.0.1";
http_port = 3000;
enforce_domain = true;
enable_gzip = true;
domain = "grafana.your.domain";
# Alternatively, if you want to server Grafana from a subpath:
# domain = "your.domain";
# root_url = "https://your.domain/grafana/";
# serve_from_sub_path = true;
};
# Prevents Grafana from phoning home
#analytics.reporting_enabled = false;
};
};
Read Grafana's documentation for the options in settings
.
Usage
Grafana can be used through tunnels, like a SSH tunnel, or a VPN tunnel like Wireguard or Headscale. This way, Grafana can be completely shielded from the outside.
Another way is to make it publicly available, usually behind a reverse proxy.
Nginx
Here is how to setup Nginx such that it proxies your.domain/grafana
to your Grafana instance:
services.nginx.virtualHosts."your.domain" = {
addSSL = true;
enableACME = true;
locations."/grafana/" = {
proxyPass = "http://${toString config.services.grafana.settings.server.http_addr}:${toString config.services.grafana.settings.server.http_port}";
proxyWebsockets = true;
recommendedProxySettings = true;
};
};
Traefik
Traefik is another common reverse proxy, for which the configuration relevant to Grafana would like this:
services.traefik = {
# ...
dynamicConfigOptions = {
http.routers."your.domain" = {
rule = "Host(`your.domain`) && PathPrefix(`/grafana`)";
service = "grafana";
}
http.services."grafana" = {
loadBalancer.servers = [ {
url = "http://${toString config.services.grafana.settings.server.http_addr}:${toString config.services.grafana.settings.server.http_port}";
} ]
};
# ...
};
Alternatively, to use Grafana on grafana.your.domain
instead of your.domain/grafana
, you could change line 5 above to:
-rule = "Host(`your.domain`) && PathPrefix(`/grafana`)";
+rule = "Host(`grafana.your.domain`)";
Configuration
Everything else (data sources, users, dashboards, ...) can be configured either in the Web UI, or as code.
Via Web UI
Log into the Grafana web application (using default user: admin, password: admin). Refer to the official documentation on how to do it:
Declarative configuration
services.grafana = {
declarativePlugins = with pkgs.grafanaPlugins; [ ... ];
provision = {
enable = true;
dashboards.settings.providers = [{
name = "my dashboards";
options.path = "/etc/grafana-dashboards";
}];
datasources.settings.datasources = [
# "Built-in" datasources can be provisioned - c.f. https://grafana.com/docs/grafana/latest/administration/provisioning/#data-sources
{
name = "Prometheus";
type = "prometheus";
url = "http://${config.services.prometheus.listenAddress}:${toString config.services.prometheus.port}";
}
# Some plugins also can - c.f. https://grafana.com/docs/plugins/yesoreyeram-infinity-datasource/latest/setup/provisioning/
{
name = "Infinity";
type = "yesoreyeram-infinity-datasource";
}
# But not all - c.f. https://github.com/fr-ser/grafana-sqlite-datasource/issues/141
];
# Note: removing attributes from the above `datasources.settings.datasources` is not enough for them to be deleted on `grafana`;
# One needs to use the following option:
# datasources.settings.deleteDatasources = [ { name = "foo"; orgId = 1; } { name = "bar"; orgId = 1; } ];
};
};
environment.etc = [{
source = ./. + "/grafana-dashboards/some-dashboard.json";
group = "grafana";
user = "grafana";
}];