services-flake/nix/grafana.nix
Alex Pearwin eb3bac5543
feat(grafana): add providers configuration (#211)
Addresses juspay/services-flake#210.

I've tested this by hand with configuration:

```nix
services.grafana."grafana" = {
  enable = true;
  providers = [
    {
      name = "Databases";
      type = "file";
      options = {
        path = ./dashboards;
        foldersFromFilesStructure = true;
      };
    }
  ];
};
```

I haven't looked into it, but it might be possible to extend the
existing Grafana test to check that a folder of dashboards is loaded.
2024-06-06 21:39:45 +05:30

180 lines
5.1 KiB
Nix

{ pkgs, lib, name, config, ... }:
let
inherit (lib) types;
iniFormat = pkgs.formats.ini { };
yamlFormat = pkgs.formats.yaml { };
in
{
options = {
description = ''
Configure grafana.
'';
enable = lib.mkEnableOption name;
package = lib.mkPackageOption pkgs "grafana" { };
http_port = lib.mkOption {
type = types.int;
description = "Which port to run grafana on.";
default = 3000;
};
domain = lib.mkOption {
type = types.str;
description = "The public facing domain name used to access grafana from a browser.";
default = "localhost";
};
protocol = lib.mkOption {
type = types.str;
description = "Protocol (http, https, h2, socket).";
default = "http";
};
dataDir = lib.mkOption {
type = types.str;
description = "Directory where grafana stores its logs and data.";
default = "./data/${name}";
};
extraConf = lib.mkOption {
type = iniFormat.type;
description = "Extra configuration for grafana.";
default = { };
example = ''
{
security.admin_user = "patato";
security.admin_password = "potato";
}
'';
};
datasources = lib.mkOption {
type = types.listOf yamlFormat.type;
description = ''
List of data sources to configure.
See https://grafana.com/docs/grafana/latest/administration/provisioning/#data-sources for the schema.
'';
default = [ ];
example = ''
[
{
name = "Tempo";
type = "tempo";
access = "proxy";
}
]
'';
};
deleteDatasources = lib.mkOption {
type = types.listOf yamlFormat.type;
description = "List of data sources to remove.";
default = [ ];
example = ''
[
{ name = "Tempo"; }
]
'';
};
providers = lib.mkOption {
type = types.listOf yamlFormat.type;
description = ''
List of dashboard providers to configure.
See https://grafana.com/docs/grafana/latest/administration/provisioning/#dashboards for the schema.
'';
default = [ ];
example = ''
[
{
name = "Databases";
type = "file";
options = {
path = ./dashboards;
foldersFromFilesStructure = true;
};
}
]
'';
};
outputs.settings = lib.mkOption {
type = types.deferredModule;
internal = true;
readOnly = true;
default = {
processes."${name}" =
let
grafanaConfig = lib.recursiveUpdate
{
server = {
inherit (config) protocol http_port domain;
};
}
config.extraConf;
grafanaConfigIni = iniFormat.generate "defaults.ini" grafanaConfig;
provisioningConfig = pkgs.stdenv.mkDerivation {
name = "grafana-provisioning";
datasourcesYaml = yamlFormat.generate "datasources.yaml" {
apiVersion = 1;
deleteDatasources = config.deleteDatasources;
datasources = config.datasources;
};
providersYaml = yamlFormat.generate "providers.yaml" {
apiVersion = 1;
providers = config.providers;
};
buildCommand = ''
mkdir -p $out
mkdir -p $out/alerting
mkdir -p $out/dashboards
ln -s "$providersYaml" "$out/dashboards/providers.yaml"
mkdir -p $out/datasources
ln -s "$datasourcesYaml" "$out/datasources/datasources.yaml"
mkdir -p $out/notifiers
mkdir -p $out/plugins
'';
};
startScript = pkgs.writeShellApplication {
name = "start-grafana";
runtimeInputs =
[ config.package ] ++
(lib.lists.optionals pkgs.stdenv.isDarwin [
pkgs.coreutils
]);
text = ''
grafana server --config ${grafanaConfigIni} \
--homepath ${config.package}/share/grafana \
cfg:paths.data="$(readlink -m ${config.dataDir})" \
cfg:paths.provisioning="${provisioningConfig}"
'';
};
in
{
command = startScript;
readiness_probe = {
http_get = {
host = config.domain;
scheme = config.protocol;
port = config.http_port;
path = "/api/health";
};
initial_delay_seconds = 15;
period_seconds = 10;
timeout_seconds = 2;
success_threshold = 1;
failure_threshold = 5;
};
namespace = name;
# https://github.com/F1bonacc1/process-compose#-auto-restart-if-not-healthy
availability.restart = "on_failure";
};
};
};
};
}