···
cfg = config.services.grafana;
opt = options.services.grafana;
8
+
provisioningSettingsFormat = pkgs.formats.yaml {};
declarativePlugins = pkgs.linkFarm "grafana-plugins" (builtins.map (pkg: { name = pkg.pname; path = pkg; }) cfg.declarativePlugins);
9
-
useMysql = cfg.database.type == "mysql";
10
-
usePostgresql = cfg.database.type == "postgres";
13
-
PATHS_DATA = cfg.dataDir;
14
-
PATHS_PLUGINS = if builtins.isNull cfg.declarativePlugins then "${cfg.dataDir}/plugins" else declarativePlugins;
15
-
PATHS_LOGS = "${cfg.dataDir}/log";
17
-
SERVER_SERVE_FROM_SUBPATH = boolToString cfg.server.serveFromSubPath;
18
-
SERVER_PROTOCOL = cfg.protocol;
19
-
SERVER_HTTP_ADDR = cfg.addr;
20
-
SERVER_HTTP_PORT = cfg.port;
21
-
SERVER_SOCKET = cfg.socket;
22
-
SERVER_DOMAIN = cfg.domain;
23
-
SERVER_ROOT_URL = cfg.rootUrl;
24
-
SERVER_STATIC_ROOT_PATH = cfg.staticRootPath;
25
-
SERVER_CERT_FILE = cfg.certFile;
26
-
SERVER_CERT_KEY = cfg.certKey;
28
-
DATABASE_TYPE = cfg.database.type;
29
-
DATABASE_HOST = cfg.database.host;
30
-
DATABASE_NAME = cfg.database.name;
31
-
DATABASE_USER = cfg.database.user;
32
-
DATABASE_PASSWORD = cfg.database.password;
33
-
DATABASE_PATH = cfg.database.path;
34
-
DATABASE_CONN_MAX_LIFETIME = cfg.database.connMaxLifetime;
36
-
SECURITY_ADMIN_USER = cfg.security.adminUser;
37
-
SECURITY_ADMIN_PASSWORD = cfg.security.adminPassword;
38
-
SECURITY_SECRET_KEY = cfg.security.secretKey;
40
-
USERS_ALLOW_SIGN_UP = boolToString cfg.users.allowSignUp;
41
-
USERS_ALLOW_ORG_CREATE = boolToString cfg.users.allowOrgCreate;
42
-
USERS_AUTO_ASSIGN_ORG = boolToString cfg.users.autoAssignOrg;
43
-
USERS_AUTO_ASSIGN_ORG_ROLE = cfg.users.autoAssignOrgRole;
45
-
AUTH_DISABLE_LOGIN_FORM = boolToString cfg.auth.disableLoginForm;
10
+
useMysql = cfg.settings.database.type == "mysql";
11
+
usePostgresql = cfg.settings.database.type == "postgres";
47
-
AUTH_ANONYMOUS_ENABLED = boolToString cfg.auth.anonymous.enable;
48
-
AUTH_ANONYMOUS_ORG_NAME = cfg.auth.anonymous.org_name;
49
-
AUTH_ANONYMOUS_ORG_ROLE = cfg.auth.anonymous.org_role;
51
-
AUTH_AZUREAD_NAME = "Azure AD";
52
-
AUTH_AZUREAD_ENABLED = boolToString cfg.auth.azuread.enable;
53
-
AUTH_AZUREAD_ALLOW_SIGN_UP = boolToString cfg.auth.azuread.allowSignUp;
54
-
AUTH_AZUREAD_CLIENT_ID = cfg.auth.azuread.clientId;
55
-
AUTH_AZUREAD_SCOPES = "openid email profile";
56
-
AUTH_AZUREAD_AUTH_URL = "https://login.microsoftonline.com/${cfg.auth.azuread.tenantId}/oauth2/v2.0/authorize";
57
-
AUTH_AZUREAD_TOKEN_URL = "https://login.microsoftonline.com/${cfg.auth.azuread.tenantId}/oauth2/v2.0/token";
58
-
AUTH_AZUREAD_ALLOWED_DOMAINS = cfg.auth.azuread.allowedDomains;
59
-
AUTH_AZUREAD_ALLOWED_GROUPS = cfg.auth.azuread.allowedGroups;
60
-
AUTH_AZUREAD_ROLE_ATTRIBUTE_STRICT = false;
62
-
AUTH_GOOGLE_ENABLED = boolToString cfg.auth.google.enable;
63
-
AUTH_GOOGLE_ALLOW_SIGN_UP = boolToString cfg.auth.google.allowSignUp;
64
-
AUTH_GOOGLE_CLIENT_ID = cfg.auth.google.clientId;
66
-
ANALYTICS_REPORTING_ENABLED = boolToString cfg.analytics.reporting.enable;
68
-
SMTP_ENABLED = boolToString cfg.smtp.enable;
69
-
SMTP_HOST = cfg.smtp.host;
70
-
SMTP_USER = cfg.smtp.user;
71
-
SMTP_PASSWORD = cfg.smtp.password;
72
-
SMTP_FROM_ADDRESS = cfg.smtp.fromAddress;
73
-
} // cfg.extraOptions;
13
+
settingsFormatIni = pkgs.formats.ini {};
14
+
configFile = settingsFormatIni.generate "config.ini" cfg.settings;
datasourceConfiguration = {
datasources = cfg.provision.datasources;
80
-
datasourceFile = pkgs.writeText "datasource.yaml" (builtins.toJSON datasourceConfiguration);
21
+
datasourceFileNew = if (cfg.provision.datasources.path == null) then provisioningSettingsFormat.generate "datasource.yaml" cfg.provision.datasources.settings else cfg.provision.datasources.path;
22
+
datasourceFile = if (builtins.isList cfg.provision.datasources) then provisioningSettingsFormat.generate "datasource.yaml" datasourceConfiguration else datasourceFileNew;
dashboardConfiguration = {
providers = cfg.provision.dashboards;
87
-
dashboardFile = pkgs.writeText "dashboard.yaml" (builtins.toJSON dashboardConfiguration);
29
+
dashboardFileNew = if (cfg.provision.dashboards.path == null) then provisioningSettingsFormat.generate "dashboard.yaml" cfg.provision.dashboards.settings else cfg.provision.dashboards.path;
30
+
dashboardFile = if (builtins.isList cfg.provision.dashboards) then provisioningSettingsFormat.generate "dashboard.yaml" dashboardConfiguration else dashboardFileNew;
notifierConfiguration = {
···
notifierFile = pkgs.writeText "notifier.yaml" (builtins.toJSON notifierConfiguration);
39
+
generateAlertingProvisioningYaml = x: if (cfg.provision.alerting."${x}".path == null)
40
+
then provisioningSettingsFormat.generate "${x}.yaml" cfg.provision.alerting."${x}".settings
41
+
else cfg.provision.alerting."${x}".path;
42
+
rulesFile = generateAlertingProvisioningYaml "rules";
43
+
contactPointsFile = generateAlertingProvisioningYaml "contactPoints";
44
+
policiesFile = generateAlertingProvisioningYaml "policies";
45
+
templatesFile = generateAlertingProvisioningYaml "templates";
46
+
muteTimingsFile = generateAlertingProvisioningYaml "muteTimings";
provisionConfDir = pkgs.runCommand "grafana-provisioning" { } ''
97
-
mkdir -p $out/{datasources,dashboards,notifiers}
49
+
mkdir -p $out/{datasources,dashboards,notifiers,alerting}
ln -sf ${datasourceFile} $out/datasources/datasource.yaml
ln -sf ${dashboardFile} $out/dashboards/dashboard.yaml
ln -sf ${notifierFile} $out/notifiers/notifier.yaml
53
+
ln -sf ${rulesFile} $out/alerting/rules.yaml
54
+
ln -sf ${contactPointsFile} $out/alerting/contactPoints.yaml
55
+
ln -sf ${policiesFile} $out/alerting/policies.yaml
56
+
ln -sf ${templatesFile} $out/alerting/templates.yaml
57
+
ln -sf ${muteTimingsFile} $out/alerting/muteTimings.yaml
# Get a submodule without any embedded metadata:
···
# http://docs.grafana.org/administration/provisioning/#datasources
grafanaTypes.datasourceConfig = types.submodule {
65
+
freeformType = provisioningSettingsFormat.type;
···
description = lib.mdDoc "Access mode. proxy or direct (Server or Browser in the UI). Required.";
125
-
description = lib.mdDoc "Org id. will default to orgId 1 if not specified.";
type = types.nullOr types.str;
···
88
+
default = "localhost";
description = lib.mdDoc "Url of the datasource.";
136
-
password = mkOption {
137
-
type = types.nullOr types.str;
139
-
description = lib.mdDoc "Database password, if used.";
142
-
type = types.nullOr types.str;
144
-
description = lib.mdDoc "Database user, if used.";
146
-
database = mkOption {
147
-
type = types.nullOr types.str;
149
-
description = lib.mdDoc "Database name, if used.";
151
-
basicAuth = mkOption {
152
-
type = types.nullOr types.bool;
154
-
description = lib.mdDoc "Enable/disable basic auth.";
91
+
editable = mkOption {
94
+
description = lib.mdDoc "Allow users to edit datasources from the UI.";
156
-
basicAuthUser = mkOption {
96
+
password = mkOption {
type = types.nullOr types.str;
159
-
description = lib.mdDoc "Basic auth username.";
99
+
description = lib.mdDoc ''
100
+
Database password, if used. Please note that the contents of this option
101
+
will end up in a world-readable Nix store. Use the file provider
102
+
pointing at a reasonably secured file in the local filesystem
103
+
to work around that. Look at the documentation for details:
104
+
<https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#file-provider>
basicAuthPassword = mkOption {
type = types.nullOr types.str;
164
-
description = lib.mdDoc "Basic auth password.";
166
-
withCredentials = mkOption {
169
-
description = lib.mdDoc "Enable/disable with credentials headers.";
171
-
isDefault = mkOption {
174
-
description = lib.mdDoc "Mark as default datasource. Max one per org.";
176
-
jsonData = mkOption {
177
-
type = types.nullOr types.attrs;
179
-
description = lib.mdDoc "Datasource specific configuration.";
110
+
description = lib.mdDoc ''
111
+
Basic auth password. Please note that the contents of this option
112
+
will end up in a world-readable Nix store. Use the file provider
113
+
pointing at a reasonably secured file in the local filesystem
114
+
to work around that. Look at the documentation for details:
115
+
<https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#file-provider>
secureJsonData = mkOption {
type = types.nullOr types.attrs;
184
-
description = lib.mdDoc "Datasource specific secure configuration.";
186
-
version = mkOption {
189
-
description = lib.mdDoc "Version.";
191
-
editable = mkOption {
194
-
description = lib.mdDoc "Allow users to edit datasources from the UI.";
121
+
description = lib.mdDoc ''
122
+
Datasource specific secure configuration. Please note that the contents of this option
123
+
will end up in a world-readable Nix store. Use the file provider
124
+
pointing at a reasonably secured file in the local filesystem
125
+
to work around that. Look at the documentation for details:
126
+
<https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#file-provider>
# http://docs.grafana.org/administration/provisioning/#dashboards
grafanaTypes.dashboardConfig = types.submodule {
134
+
freeformType = provisioningSettingsFormat.type;
205
-
description = lib.mdDoc "Provider name.";
210
-
description = lib.mdDoc "Organization ID.";
212
-
folder = mkOption {
215
-
description = lib.mdDoc "Add dashboards to the specified folder.";
140
+
description = lib.mdDoc "A unique provider name.";
description = lib.mdDoc "Dashboard provider type.";
222
-
disableDeletion = mkOption {
225
-
description = lib.mdDoc "Disable deletion when JSON file is removed.";
227
-
updateIntervalSeconds = mkOption {
230
-
description = lib.mdDoc "How often Grafana will scan for changed dashboards.";
235
-
description = lib.mdDoc "Path grafana will watch for dashboards.";
237
-
foldersFromFilesStructure = mkOption {
240
-
description = lib.mdDoc "Use folder names from filesystem to create folders in Grafana.";
147
+
options.path = mkOption {
149
+
description = lib.mdDoc "Path grafana will watch for dashboards. Required when using the 'file' type.";
···
secure_settings = mkOption {
type = types.nullOr types.attrs;
299
-
description = lib.mdDoc "Secure settings for the notifier type.";
207
+
description = lib.mdDoc ''
208
+
Secure settings for the notifier type. Please note that the contents of this option
209
+
will end up in a world-readable Nix store. Use the file provider
210
+
pointing at a reasonably secured file in the local filesystem
211
+
to work around that. Look at the documentation for details:
212
+
<https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#file-provider>
304
-
options.services.grafana = {
305
-
enable = mkEnableOption (lib.mdDoc "grafana");
307
-
protocol = mkOption {
308
-
description = lib.mdDoc "Which protocol to listen.";
310
-
type = types.enum ["http" "https" "socket"];
314
-
description = lib.mdDoc "Listening address.";
315
-
default = "127.0.0.1";
320
-
description = lib.mdDoc "Listening port.";
325
-
socket = mkOption {
326
-
description = lib.mdDoc "Listening socket.";
327
-
default = "/run/grafana/grafana.sock";
331
-
domain = mkOption {
332
-
description = lib.mdDoc "The public facing domain name used to access grafana from a browser.";
333
-
default = "localhost";
337
-
rootUrl = mkOption {
338
-
description = lib.mdDoc "Full public facing url.";
339
-
default = "%(protocol)s://%(domain)s:%(http_port)s/";
343
-
certFile = mkOption {
344
-
description = lib.mdDoc "Cert file for ssl.";
219
+
(mkRenamedOptionModule [ "services" "grafana" "protocol" ] [ "services" "grafana" "settings" "server" "protocol" ])
220
+
(mkRenamedOptionModule [ "services" "grafana" "addr" ] [ "services" "grafana" "settings" "server" "http_addr" ])
221
+
(mkRenamedOptionModule [ "services" "grafana" "port" ] [ "services" "grafana" "settings" "server" "http_port" ])
222
+
(mkRenamedOptionModule [ "services" "grafana" "domain" ] [ "services" "grafana" "settings" "server" "domain" ])
223
+
(mkRenamedOptionModule [ "services" "grafana" "rootUrl" ] [ "services" "grafana" "settings" "server" "root_url" ])
224
+
(mkRenamedOptionModule [ "services" "grafana" "staticRootPath" ] [ "services" "grafana" "settings" "server" "static_root_path" ])
225
+
(mkRenamedOptionModule [ "services" "grafana" "certFile" ] [ "services" "grafana" "settings" "server" "cert_file" ])
226
+
(mkRenamedOptionModule [ "services" "grafana" "certKey" ] [ "services" "grafana" "settings" "server" "cert_key" ])
227
+
(mkRenamedOptionModule [ "services" "grafana" "socket" ] [ "services" "grafana" "settings" "server" "socket" ])
228
+
(mkRenamedOptionModule [ "services" "grafana" "database" "type" ] [ "services" "grafana" "settings" "database" "type" ])
229
+
(mkRenamedOptionModule [ "services" "grafana" "database" "host" ] [ "services" "grafana" "settings" "database" "host" ])
230
+
(mkRenamedOptionModule [ "services" "grafana" "database" "name" ] [ "services" "grafana" "settings" "database" "name" ])
231
+
(mkRenamedOptionModule [ "services" "grafana" "database" "user" ] [ "services" "grafana" "settings" "database" "user" ])
232
+
(mkRenamedOptionModule [ "services" "grafana" "database" "password" ] [ "services" "grafana" "settings" "database" "password" ])
233
+
(mkRenamedOptionModule [ "services" "grafana" "database" "path" ] [ "services" "grafana" "settings" "database" "path" ])
234
+
(mkRenamedOptionModule [ "services" "grafana" "database" "connMaxLifetime" ] [ "services" "grafana" "settings" "database" "conn_max_lifetime" ])
235
+
(mkRenamedOptionModule [ "services" "grafana" "security" "adminUser" ] [ "services" "grafana" "settings" "security" "admin_user" ])
236
+
(mkRenamedOptionModule [ "services" "grafana" "security" "adminPassword" ] [ "services" "grafana" "settings" "security" "admin_password" ])
237
+
(mkRenamedOptionModule [ "services" "grafana" "security" "secretKey" ] [ "services" "grafana" "settings" "security" "secret_key" ])
238
+
(mkRenamedOptionModule [ "services" "grafana" "server" "serveFromSubPath" ] [ "services" "grafana" "settings" "server" "serve_from_sub_path" ])
239
+
(mkRenamedOptionModule [ "services" "grafana" "smtp" "enable" ] [ "services" "grafana" "settings" "smtp" "enabled" ])
240
+
(mkRenamedOptionModule [ "services" "grafana" "smtp" "user" ] [ "services" "grafana" "settings" "smtp" "user" ])
241
+
(mkRenamedOptionModule [ "services" "grafana" "smtp" "password" ] [ "services" "grafana" "settings" "smtp" "password" ])
242
+
(mkRenamedOptionModule [ "services" "grafana" "smtp" "fromAddress" ] [ "services" "grafana" "settings" "smtp" "from_address" ])
243
+
(mkRenamedOptionModule [ "services" "grafana" "users" "allowSignUp" ] [ "services" "grafana" "settings" "users" "allow_sign_up" ])
244
+
(mkRenamedOptionModule [ "services" "grafana" "users" "allowOrgCreate" ] [ "services" "grafana" "settings" "users" "allow_org_create" ])
245
+
(mkRenamedOptionModule [ "services" "grafana" "users" "autoAssignOrg" ] [ "services" "grafana" "settings" "users" "auto_assign_org" ])
246
+
(mkRenamedOptionModule [ "services" "grafana" "users" "autoAssignOrgRole" ] [ "services" "grafana" "settings" "users" "auto_assign_org_role" ])
247
+
(mkRenamedOptionModule [ "services" "grafana" "auth" "disableLoginForm" ] [ "services" "grafana" "settings" "auth" "disable_login_form" ])
248
+
(mkRenamedOptionModule [ "services" "grafana" "auth" "anonymous" "enable" ] [ "services" "grafana" "settings" "auth" "anonymous" "enable" ])
249
+
(mkRenamedOptionModule [ "services" "grafana" "auth" "anonymous" "org_name" ] [ "services" "grafana" "settings" "auth" "anonymous" "org_name" ])
250
+
(mkRenamedOptionModule [ "services" "grafana" "auth" "anonymous" "org_role" ] [ "services" "grafana" "settings" "auth" "anonymous" "org_role" ])
251
+
(mkRenamedOptionModule [ "services" "grafana" "auth" "azuread" "enable" ] [ "services" "grafana" "settings" "auth" "azuread" "enable" ])
252
+
(mkRenamedOptionModule [ "services" "grafana" "auth" "azuread" "allowSignUp" ] [ "services" "grafana" "settings" "auth" "azuread" "allow_sign_up" ])
253
+
(mkRenamedOptionModule [ "services" "grafana" "auth" "azuread" "clientId" ] [ "services" "grafana" "settings" "auth" "azuread" "client_id" ])
254
+
(mkRenamedOptionModule [ "services" "grafana" "auth" "azuread" "allowedDomains" ] [ "services" "grafana" "settings" "auth" "azuread" "allowed_domains" ])
255
+
(mkRenamedOptionModule [ "services" "grafana" "auth" "azuread" "allowedGroups" ] [ "services" "grafana" "settings" "auth" "azuread" "allowed_groups" ])
256
+
(mkRenamedOptionModule [ "services" "grafana" "auth" "google" "enable" ] [ "services" "grafana" "settings" "auth" "google" "enable" ])
257
+
(mkRenamedOptionModule [ "services" "grafana" "auth" "google" "allowSignUp" ] [ "services" "grafana" "settings" "auth" "google" "allow_sign_up" ])
258
+
(mkRenamedOptionModule [ "services" "grafana" "auth" "google" "clientId" ] [ "services" "grafana" "settings" "auth" "google" "client_id" ])
259
+
(mkRenamedOptionModule [ "services" "grafana" "analytics" "reporting" "enable" ] [ "services" "grafana" "settings" "analytics" "reporting_enabled" ])
349
-
certKey = mkOption {
350
-
description = lib.mdDoc "Cert key for ssl.";
261
+
(mkRemovedOptionModule [ "services" "grafana" "database" "passwordFile" ] ''
262
+
This option has been removed. Use 'services.grafana.settings.database.password' with file provider instead.
264
+
(mkRemovedOptionModule [ "services" "grafana" "security" "adminPasswordFile" ] ''
265
+
This option has been removed. Use 'services.grafana.settings.security.admin_password' with file provider instead.
267
+
(mkRemovedOptionModule [ "services" "grafana" "security" "secretKeyFile" ] ''
268
+
This option has been removed. Use 'services.grafana.settings.security.secret_key' with file provider instead.
270
+
(mkRemovedOptionModule [ "services" "grafana" "smtp" "passwordFile" ] ''
271
+
This option has been removed. Use 'services.grafana.settings.smtp.password' with file provider instead.
273
+
(mkRemovedOptionModule [ "services" "grafana" "auth" "azuread" "clientSecretFile" ] ''
274
+
This option has been removed. Use 'services.grafana.settings.azuread.client_secret' with file provider instead.
276
+
(mkRemovedOptionModule [ "services" "grafana" "auth" "google" "clientSecretFile" ] ''
277
+
This option has been removed. Use 'services.grafana.settings.google.client_secret' with file provider instead.
355
-
staticRootPath = mkOption {
356
-
description = lib.mdDoc "Root path for static assets.";
357
-
default = "${cfg.package}/share/grafana/public";
358
-
defaultText = literalExpression ''"''${package}/share/grafana/public"'';
280
+
(mkRemovedOptionModule [ "services" "grafana" "auth" "azuread" "tenantId" ] "This option has been deprecated upstream.")
362
-
package = mkOption {
363
-
description = lib.mdDoc "Package to use.";
364
-
default = pkgs.grafana;
365
-
defaultText = literalExpression "pkgs.grafana";
366
-
type = types.package;
283
+
options.services.grafana = {
284
+
enable = mkEnableOption (lib.mdDoc "grafana");
declarativePlugins = mkOption {
type = with types; nullOr (listOf path);
···
apply = x: if isList x then lib.unique x else x;
297
+
package = mkOption {
298
+
description = lib.mdDoc "Package to use.";
299
+
default = pkgs.grafana;
300
+
defaultText = literalExpression "pkgs.grafana";
301
+
type = types.package;
description = lib.mdDoc "Data directory.";
default = "/var/lib/grafana";
388
-
description = lib.mdDoc "Database type.";
389
-
default = "sqlite3";
390
-
type = types.enum ["mysql" "sqlite3" "postgres"];
310
+
settings = mkOption {
311
+
description = lib.mdDoc ''
312
+
Grafana settings. See <https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/>
313
+
for available options. INI format is used.
315
+
type = types.submodule {
316
+
freeformType = settingsFormatIni.type;
320
+
plugins = mkOption {
321
+
description = lib.mdDoc "Directory where grafana will automatically scan and look for plugins";
322
+
default = if (cfg.declarativePlugins == null) then "${cfg.dataDir}/plugins" else declarativePlugins;
323
+
defaultText = literalExpression "if (cfg.declarativePlugins == null) then \"\${cfg.dataDir}/plugins\" else declarativePlugins";
327
+
provisioning = mkOption {
328
+
description = lib.mdDoc ''
329
+
Folder that contains provisioning config files that grafana will apply on startup and while running.
330
+
Don't change the value of this option if you are planning to use `services.grafana.provision` options.
332
+
default = provisionConfDir;
333
+
defaultText = literalExpression ''
334
+
pkgs.runCommand "grafana-provisioning" { } \'\'
335
+
mkdir -p $out/{datasources,dashboards,notifiers,alerting}
336
+
ln -sf ''${datasourceFile} $out/datasources/datasource.yaml
337
+
ln -sf ''${dashboardFile} $out/dashboards/dashboard.yaml
338
+
ln -sf ''${notifierFile} $out/notifiers/notifier.yaml
339
+
ln -sf ''${rulesFile} $out/alerting/rules.yaml
340
+
ln -sf ''${contactPointsFile} $out/alerting/contactPoints.yaml
341
+
ln -sf ''${policiesFile} $out/alerting/policies.yaml
342
+
ln -sf ''${templatesFile} $out/alerting/templates.yaml
343
+
ln -sf ''${muteTimingsFile} $out/alerting/muteTimings.yaml
351
+
protocol = mkOption {
352
+
description = lib.mdDoc "Which protocol to listen.";
354
+
type = types.enum ["http" "https" "socket"];
357
+
http_addr = mkOption {
358
+
description = lib.mdDoc "Listening address.";
363
+
http_port = mkOption {
364
+
description = lib.mdDoc "Listening port.";
369
+
domain = mkOption {
370
+
description = lib.mdDoc "The public facing domain name used to access grafana from a browser.";
371
+
default = "localhost";
375
+
root_url = mkOption {
376
+
description = lib.mdDoc "Full public facing url.";
377
+
default = "%(protocol)s://%(domain)s:%(http_port)s/";
381
+
static_root_path = mkOption {
382
+
description = lib.mdDoc "Root path for static assets.";
383
+
default = "${cfg.package}/share/grafana/public";
384
+
defaultText = literalExpression ''"''${package}/share/grafana/public"'';
388
+
enable_gzip = mkOption {
389
+
description = lib.mdDoc ''
390
+
Set this option to true to enable HTTP compression, this can improve transfer speed and bandwidth utilization.
391
+
It is recommended that most users set it to true. By default it is set to false for compatibility reasons.
397
+
cert_file = mkOption {
398
+
description = lib.mdDoc "Cert file for ssl.";
403
+
cert_key = mkOption {
404
+
description = lib.mdDoc "Cert key for ssl.";
409
+
socket = mkOption {
410
+
description = lib.mdDoc "Path where the socket should be created when protocol=socket. Make sure that Grafana has appropriate permissions before you change this setting.";
394
-
description = lib.mdDoc "Database host.";
395
-
default = "127.0.0.1:3306";
418
+
description = lib.mdDoc "Database type.";
419
+
default = "sqlite3";
420
+
type = types.enum ["mysql" "sqlite3" "postgres"];
400
-
description = lib.mdDoc "Database name.";
401
-
default = "grafana";
424
+
description = lib.mdDoc "Database host.";
425
+
default = "127.0.0.1:3306";
430
+
description = lib.mdDoc "Database name.";
431
+
default = "grafana";
436
+
description = lib.mdDoc "Database user.";
441
+
password = mkOption {
442
+
description = lib.mdDoc ''
443
+
Database password. Please note that the contents of this option
444
+
will end up in a world-readable Nix store. Use the file provider
445
+
pointing at a reasonably secured file in the local filesystem
446
+
to work around that. Look at the documentation for details:
447
+
<https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#file-provider>
454
+
description = lib.mdDoc "Only applicable to sqlite3 database. The file path where the database will be stored.";
455
+
default = "${cfg.dataDir}/data/grafana.db";
456
+
defaultText = literalExpression ''"''${config.${opt.dataDir}}/data/grafana.db"'';
462
+
admin_user = mkOption {
463
+
description = lib.mdDoc "Default admin username.";
468
+
admin_password = mkOption {
469
+
description = lib.mdDoc ''
470
+
Default admin password. Please note that the contents of this option
471
+
will end up in a world-readable Nix store. Use the file provider
472
+
pointing at a reasonably secured file in the local filesystem
473
+
to work around that. Look at the documentation for details:
474
+
<https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#file-provider>
480
+
secret_key = mkOption {
481
+
description = lib.mdDoc ''
482
+
Secret key used for signing. Please note that the contents of this option
483
+
will end up in a world-readable Nix store. Use the file provider
484
+
pointing at a reasonably secured file in the local filesystem
485
+
to work around that. Look at the documentation for details:
486
+
<https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#file-provider>
488
+
default = "SW2YcwTIb9zpOOhoPsMm";
494
+
enabled = mkOption {
495
+
description = lib.mdDoc "Whether to enable SMTP.";
500
+
description = lib.mdDoc "Host to connect to.";
501
+
default = "localhost:25";
505
+
description = lib.mdDoc "User used for authentication.";
509
+
password = mkOption {
510
+
description = lib.mdDoc ''
511
+
Password used for authentication. Please note that the contents of this option
512
+
will end up in a world-readable Nix store. Use the file provider
513
+
pointing at a reasonably secured file in the local filesystem
514
+
to work around that. Look at the documentation for details:
515
+
<https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#file-provider>
520
+
from_address = mkOption {
521
+
description = lib.mdDoc "Email address used for sending.";
522
+
default = "admin@grafana.localhost";
406
-
description = lib.mdDoc "Database user.";
528
+
allow_sign_up = mkOption {
529
+
description = lib.mdDoc "Disable user signup / registration.";
411
-
password = mkOption {
412
-
description = lib.mdDoc ''
414
-
This option is mutual exclusive with the passwordFile option.
534
+
allow_org_create = mkOption {
535
+
description = lib.mdDoc "Whether user is allowed to create organizations.";
420
-
passwordFile = mkOption {
421
-
description = lib.mdDoc ''
422
-
File that containts the database password.
423
-
This option is mutual exclusive with the password option.
426
-
type = types.nullOr types.path;
540
+
auto_assign_org = mkOption {
541
+
description = lib.mdDoc "Whether to automatically assign new users to default org.";
430
-
description = lib.mdDoc "Database path.";
431
-
default = "${cfg.dataDir}/data/grafana.db";
432
-
defaultText = literalExpression ''"''${config.${opt.dataDir}}/data/grafana.db"'';
546
+
auto_assign_org_role = mkOption {
547
+
description = lib.mdDoc "Default role new users will be auto assigned.";
548
+
default = "Viewer";
549
+
type = types.enum ["Viewer" "Editor"];
436
-
connMaxLifetime = mkOption {
437
-
description = lib.mdDoc ''
438
-
Sets the maximum amount of time (in seconds) a connection may be reused.
439
-
For MySQL this setting should be shorter than the `wait_timeout' variable.
441
-
default = "unlimited";
443
-
type = types.either types.int (types.enum [ "unlimited" ]);
553
+
analytics.reporting_enabled = mkOption {
554
+
description = lib.mdDoc "Whether to allow anonymous usage reporting to stats.grafana.net.";
enable = mkEnableOption (lib.mdDoc "provision");
450
-
description = lib.mdDoc "Grafana datasources configuration.";
566
+
description = lib.mdDoc ''
567
+
Deprecated option for Grafana datasource configuration. Use either
568
+
`services.grafana.provision.datasources.settings` or
569
+
`services.grafana.provision.datasources.path` instead.
452
-
type = types.listOf grafanaTypes.datasourceConfig;
453
-
apply = x: map _filter x;
572
+
apply = x: if (builtins.isList x) then map _filter x else x;
573
+
type = with types; either (listOf grafanaTypes.datasourceConfig) (submodule {
574
+
options.settings = mkOption {
575
+
description = lib.mdDoc ''
576
+
Grafana datasource configuration in Nix. Can't be used with
577
+
`services.grafana.provision.datasources.path` simultaneously. See
578
+
<https://grafana.com/docs/grafana/latest/administration/provisioning/#data-sources>
579
+
for supported options.
582
+
type = types.nullOr (types.submodule {
584
+
apiVersion = mkOption {
585
+
description = lib.mdDoc "Config file version.";
590
+
datasources = mkOption {
591
+
description = lib.mdDoc "List of datasources to insert/update.";
593
+
type = types.listOf grafanaTypes.datasourceConfig;
596
+
deleteDatasources = mkOption {
597
+
description = lib.mdDoc "List of datasources that should be deleted from the database.";
599
+
type = types.listOf (types.submodule {
600
+
options.name = mkOption {
601
+
description = lib.mdDoc "Name of the datasource to delete.";
605
+
options.orgId = mkOption {
606
+
description = lib.mdDoc "Organization ID of the datasource to delete.";
613
+
example = literalExpression ''
622
+
deleteDatasources = [{
630
+
options.path = mkOption {
631
+
description = lib.mdDoc ''
632
+
Path to YAML datasource configuration. Can't be used with
633
+
`services.grafana.provision.datasources.settings` simultaneously.
636
+
type = types.nullOr types.path;
456
-
description = lib.mdDoc "Grafana dashboard configuration.";
643
+
description = lib.mdDoc ''
644
+
Deprecated option for Grafana dashboard configuration. Use either
645
+
`services.grafana.provision.dashboards.settings` or
646
+
`services.grafana.provision.dashboards.path` instead.
458
-
type = types.listOf grafanaTypes.dashboardConfig;
459
-
apply = x: map _filter x;
649
+
apply = x: if (builtins.isList x) then map _filter x else x;
650
+
type = with types; either (listOf grafanaTypes.dashboardConfig) (submodule {
651
+
options.settings = mkOption {
652
+
description = lib.mdDoc ''
653
+
Grafana dashboard configuration in Nix. Can't be used with
654
+
`services.grafana.provision.dashboards.path` simultaneously. See
655
+
<https://grafana.com/docs/grafana/latest/administration/provisioning/#dashboards>
656
+
for supported options.
659
+
type = types.nullOr (types.submodule {
660
+
options.apiVersion = mkOption {
661
+
description = lib.mdDoc "Config file version.";
666
+
options.providers = mkOption {
667
+
description = lib.mdDoc "List of dashboards to insert/update.";
669
+
type = types.listOf grafanaTypes.dashboardConfig;
672
+
example = literalExpression ''
678
+
options.path = "/var/lib/grafana/dashboards";
684
+
options.path = mkOption {
685
+
description = lib.mdDoc ''
686
+
Path to YAML dashboard configuration. Can't be used with
687
+
`services.grafana.provision.dashboards.settings` simultaneously.
690
+
type = types.nullOr types.path;
description = lib.mdDoc "Grafana notifier configuration.";
type = types.listOf grafanaTypes.notifierConfig;
apply = x: map _filter x;
470
-
adminUser = mkOption {
471
-
description = lib.mdDoc "Default admin username.";
476
-
adminPassword = mkOption {
477
-
description = lib.mdDoc ''
478
-
Default admin password.
479
-
This option is mutual exclusive with the adminPasswordFile option.
707
+
description = lib.mdDoc ''
708
+
Path to YAML rules configuration. Can't be used with
709
+
`services.grafana.provision.alerting.rules.settings` simultaneously.
712
+
type = types.nullOr types.path;
485
-
adminPasswordFile = mkOption {
486
-
description = lib.mdDoc ''
487
-
Default admin password.
488
-
This option is mutual exclusive with the `adminPassword` option.
491
-
type = types.nullOr types.path;
715
+
settings = mkOption {
716
+
description = lib.mdDoc ''
717
+
Grafana rules configuration in Nix. Can't be used with
718
+
`services.grafana.provision.alerting.rules.path` simultaneously. See
719
+
<https://grafana.com/docs/grafana/latest/administration/provisioning/#rules>
720
+
for supported options.
723
+
type = types.nullOr (types.submodule {
725
+
apiVersion = mkOption {
726
+
description = lib.mdDoc "Config file version.";
494
-
secretKey = mkOption {
495
-
description = lib.mdDoc "Secret key used for signing.";
496
-
default = "SW2YcwTIb9zpOOhoPsMm";
731
+
groups = mkOption {
732
+
description = lib.mdDoc "List of rule groups to import or update.";
734
+
type = types.listOf (types.submodule {
735
+
freeformType = provisioningSettingsFormat.type;
500
-
secretKeyFile = mkOption {
501
-
description = lib.mdDoc "Secret key used for signing.";
503
-
type = types.nullOr types.path;
737
+
options.name = mkOption {
738
+
description = lib.mdDoc "Name of the rule group. Required.";
508
-
serveFromSubPath = mkOption {
509
-
description = lib.mdDoc "Serve Grafana from subpath specified in rootUrl setting";
742
+
options.folder = mkOption {
743
+
description = lib.mdDoc "Name of the folder the rule group will be stored in. Required.";
516
-
enable = mkEnableOption (lib.mdDoc "smtp");
518
-
description = lib.mdDoc "Host to connect to.";
519
-
default = "localhost:25";
523
-
description = lib.mdDoc "User used for authentication.";
527
-
password = mkOption {
528
-
description = lib.mdDoc ''
529
-
Password used for authentication.
530
-
This option is mutual exclusive with the passwordFile option.
535
-
passwordFile = mkOption {
536
-
description = lib.mdDoc ''
537
-
Password used for authentication.
538
-
This option is mutual exclusive with the password option.
541
-
type = types.nullOr types.path;
543
-
fromAddress = mkOption {
544
-
description = lib.mdDoc "Email address used for sending.";
545
-
default = "admin@grafana.localhost";
747
+
options.interval = mkOption {
748
+
description = lib.mdDoc "Interval that the rule group should be evaluated at. Required.";
551
-
allowSignUp = mkOption {
552
-
description = lib.mdDoc "Disable user signup / registration.";
754
+
deleteRules = mkOption {
755
+
description = lib.mdDoc "List of alert rule UIDs that should be deleted.";
757
+
type = types.listOf (types.submodule {
758
+
options.orgId = mkOption {
759
+
description = lib.mdDoc "Organization ID, default = 1";
557
-
allowOrgCreate = mkOption {
558
-
description = lib.mdDoc "Whether user is allowed to create organizations.";
764
+
options.uid = mkOption {
765
+
description = lib.mdDoc "Unique identifier for the rule. Required.";
772
+
example = literalExpression ''
563
-
autoAssignOrg = mkOption {
564
-
description = lib.mdDoc "Whether to automatically assign new users to default org.";
778
+
name = "my_rule_group";
779
+
folder = "my_first_folder";
783
+
title = "my_first_rule";
787
+
datasourceUid = "-100";
794
+
operator.type = "and";
795
+
query.params = [ "A" ];
796
+
reducer.type = "last";
803
+
expression = "1==0";
805
+
maxDataPoints = 43200;
810
+
dashboardUid = "my_dashboard";
812
+
noDataState = "Alerting";
814
+
annotations.some_key = "some_value";
815
+
labels.team = "sre_team1";
569
-
autoAssignOrgRole = mkOption {
570
-
description = lib.mdDoc "Default role new users will be auto assigned.";
571
-
default = "Viewer";
572
-
type = types.enum ["Viewer" "Editor"];
577
-
disableLoginForm = mkOption {
578
-
description = lib.mdDoc "Set to true to disable (hide) the login form, useful if you use OAuth";
830
+
description = lib.mdDoc ''
831
+
Path to YAML contact points configuration. Can't be used with
832
+
`services.grafana.provision.alerting.contactPoints.settings` simultaneously.
835
+
type = types.nullOr types.path;
584
-
enable = mkOption {
585
-
description = lib.mdDoc "Whether to allow anonymous access.";
589
-
org_name = mkOption {
590
-
description = lib.mdDoc "Which organization to allow anonymous access to.";
591
-
default = "Main Org.";
594
-
org_role = mkOption {
595
-
description = lib.mdDoc "Which role anonymous users have in the organization.";
596
-
default = "Viewer";
601
-
enable = mkOption {
602
-
description = lib.mdDoc "Whether to allow Azure AD OAuth.";
606
-
allowSignUp = mkOption {
607
-
description = lib.mdDoc "Whether to allow sign up with Azure AD OAuth.";
611
-
clientId = mkOption {
612
-
description = lib.mdDoc "Azure AD OAuth client ID.";
616
-
clientSecretFile = mkOption {
617
-
description = lib.mdDoc "Azure AD OAuth client secret.";
619
-
type = types.nullOr types.path;
621
-
tenantId = mkOption {
622
-
description = lib.mdDoc ''
623
-
Tenant id used to create auth and token url. Default to "common"
624
-
, let user sign in with any tenant.
838
+
settings = mkOption {
839
+
description = lib.mdDoc ''
840
+
Grafana contact points configuration in Nix. Can't be used with
841
+
`services.grafana.provision.alerting.contactPoints.path` simultaneously. See
842
+
<https://grafana.com/docs/grafana/latest/administration/provisioning/#contact-points>
843
+
for supported options.
626
-
default = "common";
629
-
allowedDomains = mkOption {
630
-
description = lib.mdDoc ''
631
-
Limits access to users who belong to specific domains.
632
-
Separate domains with space or comma.
637
-
allowedGroups = mkOption {
638
-
description = lib.mdDoc ''
639
-
To limit access to authenticated users who are members of one or more groups,
640
-
set allowedGroups to a comma- or space-separated list of group object IDs.
641
-
You can find object IDs for a specific group on the Azure portal.
846
+
type = types.nullOr (types.submodule {
848
+
apiVersion = mkOption {
849
+
description = lib.mdDoc "Config file version.";
854
+
contactPoints = mkOption {
855
+
description = lib.mdDoc "List of contact points to import or update.";
857
+
type = types.listOf (types.submodule {
858
+
freeformType = provisioningSettingsFormat.type;
860
+
options.name = mkOption {
861
+
description = lib.mdDoc "Name of the contact point. Required.";
867
+
deleteContactPoints = mkOption {
868
+
description = lib.mdDoc "List of receivers that should be deleted.";
870
+
type = types.listOf (types.submodule {
871
+
options.orgId = mkOption {
872
+
description = lib.mdDoc "Organization ID, default = 1.";
877
+
options.uid = mkOption {
878
+
description = lib.mdDoc "Unique identifier for the receiver. Required.";
885
+
example = literalExpression ''
894
+
type = "prometheus-alertmanager";
895
+
settings.url = "http://test:9000";
899
+
deleteContactPoints = [{
648
-
enable = mkOption {
649
-
description = lib.mdDoc "Whether to allow Google OAuth2.";
653
-
allowSignUp = mkOption {
654
-
description = lib.mdDoc "Whether to allow sign up with Google OAuth2.";
658
-
clientId = mkOption {
659
-
description = lib.mdDoc "Google OAuth2 client ID.";
910
+
description = lib.mdDoc ''
911
+
Path to YAML notification policies configuration. Can't be used with
912
+
`services.grafana.provision.alerting.policies.settings` simultaneously.
915
+
type = types.nullOr types.path;
918
+
settings = mkOption {
919
+
description = lib.mdDoc ''
920
+
Grafana notification policies configuration in Nix. Can't be used with
921
+
`services.grafana.provision.alerting.policies.path` simultaneously. See
922
+
<https://grafana.com/docs/grafana/latest/administration/provisioning/#notification-policies>
923
+
for supported options.
926
+
type = types.nullOr (types.submodule {
928
+
apiVersion = mkOption {
929
+
description = lib.mdDoc "Config file version.";
934
+
policies = mkOption {
935
+
description = lib.mdDoc "List of contact points to import or update.";
937
+
type = types.listOf (types.submodule {
938
+
freeformType = provisioningSettingsFormat.type;
942
+
resetPolicies = mkOption {
943
+
description = lib.mdDoc "List of orgIds that should be reset to the default policy.";
945
+
type = types.listOf types.int;
949
+
example = literalExpression ''
955
+
receiver = "grafana-default-email";
956
+
group_by = [ "..." ];
958
+
"alertname = Watchdog"
959
+
"severity =~ \"warning|critical\""
961
+
mute_time_intervals = [
964
+
group_wait = "30s";
965
+
group_interval = "5m";
966
+
repeat_interval = "4h";
663
-
clientSecretFile = mkOption {
664
-
description = lib.mdDoc "Google OAuth2 client secret.";
666
-
type = types.nullOr types.path;
979
+
description = lib.mdDoc ''
980
+
Path to YAML templates configuration. Can't be used with
981
+
`services.grafana.provision.alerting.templates.settings` simultaneously.
984
+
type = types.nullOr types.path;
987
+
settings = mkOption {
988
+
description = lib.mdDoc ''
989
+
Grafana templates configuration in Nix. Can't be used with
990
+
`services.grafana.provision.alerting.templates.path` simultaneously. See
991
+
<https://grafana.com/docs/grafana/latest/administration/provisioning/#templates>
992
+
for supported options.
995
+
type = types.nullOr (types.submodule {
997
+
apiVersion = mkOption {
998
+
description = lib.mdDoc "Config file version.";
1003
+
templates = mkOption {
1004
+
description = lib.mdDoc "List of templates to import or update.";
1006
+
type = types.listOf (types.submodule {
1007
+
freeformType = provisioningSettingsFormat.type;
1009
+
options.name = mkOption {
1010
+
description = lib.mdDoc "Name of the template, must be unique. Required.";
1014
+
options.template = mkOption {
1015
+
description = lib.mdDoc "Alerting with a custom text template";
1021
+
deleteTemplates = mkOption {
1022
+
description = lib.mdDoc "List of alert rule UIDs that should be deleted.";
1024
+
type = types.listOf (types.submodule {
1025
+
options.orgId = mkOption {
1026
+
description = lib.mdDoc "Organization ID, default = 1.";
1031
+
options.name = mkOption {
1032
+
description = lib.mdDoc "Name of the template, must be unique. Required.";
1039
+
example = literalExpression ''
1045
+
name = "my_first_template";
1046
+
template = "Alerting with a custom text template";
1049
+
deleteTemplates = [{
1051
+
name = "my_first_template";
1060
+
description = lib.mdDoc ''
1061
+
Path to YAML mute timings configuration. Can't be used with
1062
+
`services.grafana.provision.alerting.muteTimings.settings` simultaneously.
1065
+
type = types.nullOr types.path;
1068
+
settings = mkOption {
1069
+
description = lib.mdDoc ''
1070
+
Grafana mute timings configuration in Nix. Can't be used with
1071
+
`services.grafana.provision.alerting.muteTimings.path` simultaneously. See
1072
+
<https://grafana.com/docs/grafana/latest/administration/provisioning/#mute-timings>
1073
+
for supported options.
1076
+
type = types.nullOr (types.submodule {
1078
+
apiVersion = mkOption {
1079
+
description = lib.mdDoc "Config file version.";
1084
+
muteTimes = mkOption {
1085
+
description = lib.mdDoc "List of mute time intervals to import or update.";
1087
+
type = types.listOf (types.submodule {
1088
+
freeformType = provisioningSettingsFormat.type;
1090
+
options.name = mkOption {
1091
+
description = lib.mdDoc "Name of the mute time interval, must be unique. Required.";
1097
+
deleteMuteTimes = mkOption {
1098
+
description = lib.mdDoc "List of mute time intervals that should be deleted.";
1100
+
type = types.listOf (types.submodule {
1101
+
options.orgId = mkOption {
1102
+
description = lib.mdDoc "Organization ID, default = 1.";
1107
+
options.name = mkOption {
1108
+
description = lib.mdDoc "Name of the mute time interval, must be unique. Required.";
1115
+
example = literalExpression ''
1122
+
time_intervals = [{
1124
+
start_time = "06:00";
1125
+
end_time = "23:59";
1128
+
"monday:wednesday"
671
-
analytics.reporting = {
672
-
enable = mkOption {
673
-
description = lib.mdDoc "Whether to allow anonymous usage reporting to stats.grafana.net.";
1148
+
deleteMuteTimes = [{
679
-
extraOptions = mkOption {
680
-
description = lib.mdDoc ''
681
-
Extra configuration options passed as env variables as specified in
682
-
[documentation](http://docs.grafana.org/installation/configuration/),
683
-
but without GF_ prefix
686
-
type = with types; attrsOf (either str path);
config = mkIf cfg.enable {
693
-
cfg.database.password != opt.database.password.default ||
694
-
cfg.security.adminPassword != opt.security.adminPassword.default
695
-
) "Grafana passwords will be stored as plaintext in the Nix store!")
1163
+
cfg.settings.database.password != "" ||
1164
+
cfg.settings.security.admin_password != "admin"
1165
+
) "Grafana passwords will be stored as plaintext in the Nix store! Use file provider instead.")
697
-
any (x: x.password != null || x.basicAuthPassword != null || x.secureJsonData != null) cfg.provision.datasources
698
-
) "Datasource passwords will be stored as plaintext in the Nix store!")
1168
+
checkOpts = opt: any (x: x.password != null || x.basicAuthPassword != null || x.secureJsonData != null) opt;
1169
+
datasourcesUsed = if (cfg.provision.datasources.settings == null) then [] else cfg.provision.datasources.settings.datasources;
1170
+
in if (builtins.isList cfg.provision.datasources) then checkOpts cfg.provision.datasources else checkOpts datasourcesUsed
1171
+
) "Datasource passwords will be stored as plaintext in the Nix store! Use file provider instead.")
any (x: x.secure_settings != null) cfg.provision.notifiers
701
-
) "Notifier secure settings will be stored as plaintext in the Nix store!")
1174
+
) "Notifier secure settings will be stored as plaintext in the Nix store! Use file provider instead.")
1176
+
builtins.isList cfg.provision.datasources
1178
+
Provisioning Grafana datasources with options has been deprecated.
1179
+
Use `services.grafana.provision.datasources.settings` or
1180
+
`services.grafana.provision.datasources.path` instead.
1183
+
builtins.isList cfg.provision.dashboards
1185
+
Provisioning Grafana dashboards with options has been deprecated.
1186
+
Use `services.grafana.provision.dashboards.settings` or
1187
+
`services.grafana.provision.dashboards.path` instead.
1190
+
cfg.provision.notifiers != []
1192
+
Notifiers are deprecated upstream and will be removed in Grafana 10.
1193
+
Use `services.grafana.provision.alerting.contactPoints` instead.
environment.systemPackages = [ cfg.package ];
708
-
assertion = cfg.database.password != opt.database.password.default -> cfg.database.passwordFile == null;
709
-
message = "Cannot set both password and passwordFile";
1201
+
assertion = if (builtins.isList cfg.provision.datasources) then true else cfg.provision.datasources.settings == null || cfg.provision.datasources.path == null;
1202
+
message = "Cannot set both datasources settings and datasources path";
712
-
assertion = cfg.security.adminPassword != opt.security.adminPassword.default -> cfg.security.adminPasswordFile == null;
713
-
message = "Cannot set both adminPassword and adminPasswordFile";
1206
+
prometheusIsNotDirect = opt: all
1207
+
({ type, access, ... }: type == "prometheus" -> access != "direct")
1210
+
if (builtins.isList cfg.provision.datasources) then prometheusIsNotDirect cfg.provision.datasources
1211
+
else cfg.provision.datasources.settings == null || prometheusIsNotDirect cfg.provision.datasources.settings.datasources;
1212
+
message = "For datasources of type `prometheus`, the `direct` access mode is not supported anymore (since Grafana 9.2.0)";
716
-
assertion = cfg.security.secretKey != opt.security.secretKey.default -> cfg.security.secretKeyFile == null;
717
-
message = "Cannot set both secretKey and secretKeyFile";
1215
+
assertion = if (builtins.isList cfg.provision.dashboards) then true else cfg.provision.dashboards.settings == null || cfg.provision.dashboards.path == null;
1216
+
message = "Cannot set both dashboards settings and dashboards path";
720
-
assertion = cfg.smtp.password != opt.smtp.password.default -> cfg.smtp.passwordFile == null;
721
-
message = "Cannot set both password and passwordFile";
1219
+
assertion = cfg.provision.alerting.rules.settings == null || cfg.provision.alerting.rules.path == null;
1220
+
message = "Cannot set both rules settings and rules path";
725
-
({ type, access, ... }: type == "prometheus" -> access != "direct")
726
-
cfg.provision.datasources;
727
-
message = "For datasources of type `prometheus`, the `direct` access mode is not supported anymore (since Grafana 9.2.0)";
1223
+
assertion = cfg.provision.alerting.contactPoints.settings == null || cfg.provision.alerting.contactPoints.path == null;
1224
+
message = "Cannot set both contact points settings and contact points path";
1227
+
assertion = cfg.provision.alerting.policies.settings == null || cfg.provision.alerting.policies.path == null;
1228
+
message = "Cannot set both policies settings and policies path";
1231
+
assertion = cfg.provision.alerting.templates.settings == null || cfg.provision.alerting.templates.path == null;
1232
+
message = "Cannot set both templates settings and templates path";
1235
+
assertion = cfg.provision.alerting.muteTimings.settings == null || cfg.provision.alerting.muteTimings.path == null;
1236
+
message = "Cannot set both mute timings settings and mute timings path";
···
description = "Grafana Service Daemon";
wantedBy = ["multi-user.target"];
after = ["networking.target"] ++ lib.optional usePostgresql "postgresql.service" ++ lib.optional useMysql "mysql.service";
736
-
QT_QPA_PLATFORM = "offscreen";
737
-
} // mapAttrs' (n: v: nameValuePair "GF_${n}" (toString v)) envOptions;
set -o errexit -o pipefail -o nounset -o errtrace
742
-
${optionalString (cfg.auth.azuread.clientSecretFile != null) ''
743
-
GF_AUTH_AZUREAD_CLIENT_SECRET="$(<${escapeShellArg cfg.auth.azuread.clientSecretFile})"
744
-
export GF_AUTH_AZUREAD_CLIENT_SECRET
746
-
${optionalString (cfg.auth.google.clientSecretFile != null) ''
747
-
GF_AUTH_GOOGLE_CLIENT_SECRET="$(<${escapeShellArg cfg.auth.google.clientSecretFile})"
748
-
export GF_AUTH_GOOGLE_CLIENT_SECRET
750
-
${optionalString (cfg.database.passwordFile != null) ''
751
-
GF_DATABASE_PASSWORD="$(<${escapeShellArg cfg.database.passwordFile})"
752
-
export GF_DATABASE_PASSWORD
754
-
${optionalString (cfg.security.adminPasswordFile != null) ''
755
-
GF_SECURITY_ADMIN_PASSWORD="$(<${escapeShellArg cfg.security.adminPasswordFile})"
756
-
export GF_SECURITY_ADMIN_PASSWORD
758
-
${optionalString (cfg.security.secretKeyFile != null) ''
759
-
GF_SECURITY_SECRET_KEY="$(<${escapeShellArg cfg.security.secretKeyFile})"
760
-
export GF_SECURITY_SECRET_KEY
762
-
${optionalString (cfg.smtp.passwordFile != null) ''
763
-
GF_SMTP_PASSWORD="$(<${escapeShellArg cfg.smtp.passwordFile})"
764
-
export GF_SMTP_PASSWORD
766
-
${optionalString cfg.provision.enable ''
767
-
export GF_PATHS_PROVISIONING=${provisionConfDir};
769
-
exec ${cfg.package}/bin/grafana-server -homepath ${cfg.dataDir}
1248
+
exec ${cfg.package}/bin/grafana-server -homepath ${cfg.dataDir} -config ${configFile}
WorkingDirectory = cfg.dataDir;