Jump to content

Grafana

From NixOS Wiki
Revision as of 05:59, 3 August 2025 by Axka (talk | contribs) (Add intra-wiki links and document code example)

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 serve 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 (data sources, users, dashboards, ...) can be configured either in the Web UI or provisioned as code using Nix.

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

Grafana supports provisioning data sources, dashboards and alerting using services.grafana.provision. Note that removing a provision and switching to the new NixOS configuration does not currently remove the provisioned items; you have to define them, for example, in deleteDatasources.

services.grafana = {
  declarativePlugins = with pkgs.grafanaPlugins; [ ... ];

  provision = {
    enable = true;

    # Creates a *mutable* dashboard provider, pulling from /etc/grafana-dashboards.
    # With this, you can manually provision dashboards from JSON with `environment.etc` like below.
    dashboards.settings.providers = [{
      name = "my dashboards";
      disableDeletion = true;
      options = {
        path = "/etc/grafana-dashboards";
        foldersFromFilesStructure = true;
      };
    }];

    datasources.settings.datasources = [
      # Provisioning a built-in data source
      {
        name = "Prometheus";
        type = "prometheus";
        url = "http://${config.services.prometheus.listenAddress}:${toString config.services.prometheus.port}";
        isDefault = true;
        editable = false;
      }
      # All plugins can be provisioned but it's not always documented: https://github.com/fr-ser/grafana-sqlite-datasource/blob/main/docs/faq.md#can-i-use-provisioning-with-this-plugin
      # Compare below with https://grafana.com/docs/plugins/yesoreyeram-infinity-datasource/latest/setup/provisioning/
      {
        name = "Infinity";
        type = "yesoreyeram-infinity-datasource";
        editable = false;
      }
    ];

    # Note: removing attributes from the above `datasources.settings.datasources` is not currently enough for them to be deleted;
    # One needs to use the following option:
    # datasources.settings.deleteDatasources = [ { name = "foo"; orgId = 1; } { name = "bar"; orgId = 1; } ];
  };
};

# see `dashboards.settings.providers` above
environment.etc."grafana-dashboards/some-dashboard.json".source = ./some-dashboard.json;