···1206 </listitem>
1207 <listitem>
1208 <para>
1209- The <literal>services.grafana</literal> options were converted
1210- to a
1211 <link xlink:href="https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md">RFC
1212- 0042</link> configuration.
01213 </para>
1214- </listitem>
1215- <listitem>
1216- <para>
1217- The <literal>services.grafana.provision.datasources</literal>
1218- and <literal>services.grafana.provision.dashboards</literal>
1219- options were converted to a
1220- <link xlink:href="https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md">RFC
1221- 0042</link> configuration. They also now support specifying
1222- the provisioning YAML file with <literal>path</literal>
1223- option.
1224- </para>
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001225 </listitem>
1226 <listitem>
1227 <para>
···1206 </listitem>
1207 <listitem>
1208 <para>
1209+ The module <literal>services.grafana</literal> was refactored
1210+ to be compliant with
1211 <link xlink:href="https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md">RFC
1212+ 0042</link>. To be precise, this means that the following
1213+ things have changed:
1214 </para>
1215+ <itemizedlist>
1216+ <listitem>
1217+ <para>
1218+ The newly introduced option
1219+ <xref linkend="opt-services.grafana.settings" /> is an
1220+ attribute-set that will be converted into Grafana’s INI
1221+ format. This means that the configuration from
1222+ <link xlink:href="https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/">Grafana’s
1223+ configuration reference</link> can be directly written as
1224+ attribute-set in Nix within this option.
1225+ </para>
1226+ </listitem>
1227+ <listitem>
1228+ <para>
1229+ The option
1230+ <literal>services.grafana.extraOptions</literal> has been
1231+ removed. This option was an association of environment
1232+ variables for Grafana. If you had an expression like
1233+ </para>
1234+ <programlisting language="bash">
1235+{
1236+ services.grafana.extraOptions.SECURITY_ADMIN_USER = "foobar";
1237+}
1238+</programlisting>
1239+ <para>
1240+ your Grafana instance was running with
1241+ <literal>GF_SECURITY_ADMIN_USER=foobar</literal> in its
1242+ environment.
1243+ </para>
1244+ <para>
1245+ For the migration, it is recommended to turn it into the
1246+ INI format, i.e. to declare
1247+ </para>
1248+ <programlisting language="bash">
1249+{
1250+ services.grafana.settings.security.admin_user = "foobar";
1251+}
1252+</programlisting>
1253+ <para>
1254+ instead.
1255+ </para>
1256+ <para>
1257+ The keys in
1258+ <literal>services.grafana.extraOptions</literal> have the
1259+ format
1260+ <literal><INI section name>_<Key Name></literal>.
1261+ Further details are outlined in the
1262+ <link xlink:href="https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#override-configuration-with-environment-variables">configuration
1263+ reference</link>.
1264+ </para>
1265+ <para>
1266+ Alternatively you can also set all your values from
1267+ <literal>extraOptions</literal> to
1268+ <literal>systemd.services.grafana.environment</literal>,
1269+ make sure you don’t forget to add the
1270+ <literal>GF_</literal> prefix though!
1271+ </para>
1272+ </listitem>
1273+ <listitem>
1274+ <para>
1275+ Previously, the options
1276+ <xref linkend="opt-services.grafana.provision.datasources" />
1277+ and
1278+ <xref linkend="opt-services.grafana.provision.dashboards" />
1279+ expected lists of datasources or dashboards for the
1280+ <link xlink:href="https://grafana.com/docs/grafana/latest/administration/provisioning/">declarative
1281+ provisioning</link>.
1282+ </para>
1283+ <para>
1284+ To declare lists of
1285+ </para>
1286+ <itemizedlist spacing="compact">
1287+ <listitem>
1288+ <para>
1289+ <emphasis role="strong">datasources</emphasis>, please
1290+ rename your declarations to
1291+ <xref linkend="opt-services.grafana.provision.datasources.settings.datasources" />.
1292+ </para>
1293+ </listitem>
1294+ <listitem>
1295+ <para>
1296+ <emphasis role="strong">dashboards</emphasis>, please
1297+ rename your declarations to
1298+ <xref linkend="opt-services.grafana.provision.dashboards.settings.providers" />.
1299+ </para>
1300+ </listitem>
1301+ </itemizedlist>
1302+ <para>
1303+ This change was made to support more features for that:
1304+ </para>
1305+ <itemizedlist>
1306+ <listitem>
1307+ <para>
1308+ It’s possible to declare the
1309+ <literal>apiVersion</literal> of your dashboards and
1310+ datasources by
1311+ <xref linkend="opt-services.grafana.provision.datasources.settings.apiVersion" />
1312+ (or
1313+ <xref linkend="opt-services.grafana.provision.dashboards.settings.apiVersion" />).
1314+ </para>
1315+ </listitem>
1316+ <listitem>
1317+ <para>
1318+ Instead of declaring datasources and dashboards in
1319+ pure Nix, it’s also possible to specify configuration
1320+ files (or directories) with YAML instead using
1321+ <xref linkend="opt-services.grafana.provision.datasources.path" />
1322+ (or
1323+ <xref linkend="opt-services.grafana.provision.dashboards.path" />.
1324+ This is useful when having provisioning files from
1325+ non-NixOS Grafana instances that you also want to
1326+ deploy to NixOS.
1327+ </para>
1328+ <para>
1329+ <emphasis role="strong">Note:</emphasis> secrets from
1330+ these files will be leaked into the store unless you
1331+ use a
1332+ <link xlink:href="https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#file-provider"><emphasis role="strong">file</emphasis>-provider
1333+ or env-var</link> for secrets!
1334+ </para>
1335+ </listitem>
1336+ <listitem>
1337+ <para>
1338+ <xref linkend="opt-services.grafana.provision.notifiers" />
1339+ is not affected by this change because this feature is
1340+ deprecated by Grafana and will probably removed in
1341+ Grafana 10. It’s recommended to use
1342+ <literal>services.grafana.provision.alerting.contactPoints</literal>
1343+ instead.
1344+ </para>
1345+ </listitem>
1346+ </itemizedlist>
1347+ </listitem>
1348+ </itemizedlist>
1349 </listitem>
1350 <listitem>
1351 <para>
+59-2
nixos/doc/manual/release-notes/rl-2211.section.md
···379380- The `services.matrix-synapse` systemd unit has been hardened.
381382-- The `services.grafana` options were converted to a [RFC 0042](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md) configuration.
00000000000000000000000000000000000000000383384-- The `services.grafana.provision.datasources` and `services.grafana.provision.dashboards` options were converted to a [RFC 0042](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md) configuration. They also now support specifying the provisioning YAML file with `path` option.
0000000000000000385386- The `services.grafana.provision.alerting` option was added. It includes suboptions for every alerting-related objects (with the exception of `notifiers`), which means it's now possible to configure modern Grafana alerting declaratively.
387
···379380- The `services.matrix-synapse` systemd unit has been hardened.
381382+- The module `services.grafana` was refactored to be compliant with [RFC 0042](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md). To be precise, this means that the following things have changed:
383+ - The newly introduced option [](#opt-services.grafana.settings) is an attribute-set that
384+ will be converted into Grafana's INI format. This means that the configuration from
385+ [Grafana's configuration reference](https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/)
386+ can be directly written as attribute-set in Nix within this option.
387+ - The option `services.grafana.extraOptions` has been removed. This option was an association
388+ of environment variables for Grafana. If you had an expression like
389+390+ ```nix
391+ {
392+ services.grafana.extraOptions.SECURITY_ADMIN_USER = "foobar";
393+ }
394+ ```
395+396+ your Grafana instance was running with `GF_SECURITY_ADMIN_USER=foobar` in its environment.
397+398+ For the migration, it is recommended to turn it into the INI format, i.e.
399+ to declare
400+401+ ```nix
402+ {
403+ services.grafana.settings.security.admin_user = "foobar";
404+ }
405+ ```
406+407+ instead.
408+409+ The keys in `services.grafana.extraOptions` have the format `<INI section name>_<Key Name>`.
410+ Further details are outlined in the [configuration reference](https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#override-configuration-with-environment-variables).
411+412+ Alternatively you can also set all your values from `extraOptions` to
413+ `systemd.services.grafana.environment`, make sure you don't forget to add
414+ the `GF_` prefix though!
415+ - Previously, the options [](#opt-services.grafana.provision.datasources) and
416+ [](#opt-services.grafana.provision.dashboards) expected lists of datasources
417+ or dashboards for the [declarative provisioning](https://grafana.com/docs/grafana/latest/administration/provisioning/).
418+419+ To declare lists of
420+ - **datasources**, please rename your declarations to [](#opt-services.grafana.provision.datasources.settings.datasources).
421+ - **dashboards**, please rename your declarations to [](#opt-services.grafana.provision.dashboards.settings.providers).
422+423+ This change was made to support more features for that:
424425+ - It's possible to declare the `apiVersion` of your dashboards and datasources
426+ by [](#opt-services.grafana.provision.datasources.settings.apiVersion) (or
427+ [](#opt-services.grafana.provision.dashboards.settings.apiVersion)).
428+429+ - Instead of declaring datasources and dashboards in pure Nix, it's also possible
430+ to specify configuration files (or directories) with YAML instead using
431+ [](#opt-services.grafana.provision.datasources.path) (or
432+ [](#opt-services.grafana.provision.dashboards.path). This is useful when having
433+ provisioning files from non-NixOS Grafana instances that you also want to
434+ deploy to NixOS.
435+436+ __Note:__ secrets from these files will be leaked into the store unless you use a
437+ [**file**-provider or env-var](https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#file-provider) for secrets!
438+439+ - [](#opt-services.grafana.provision.notifiers) is not affected by this change because
440+ this feature is deprecated by Grafana and will probably removed in Grafana 10.
441+ It's recommended to use `services.grafana.provision.alerting.contactPoints` instead.
442443- The `services.grafana.provision.alerting` option was added. It includes suboptions for every alerting-related objects (with the exception of `notifiers`), which means it's now possible to configure modern Grafana alerting declaratively.
444
+141-133
nixos/modules/services/monitoring/grafana.nix
···13 settingsFormatIni = pkgs.formats.ini {};
14 configFile = settingsFormatIni.generate "config.ini" cfg.settings;
1516- datasourceConfiguration = {
17- apiVersion = 1;
18- datasources = cfg.provision.datasources;
19- };
00000002021- 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;
23-24- dashboardConfiguration = {
25- apiVersion = 1;
26- providers = cfg.provision.dashboards;
27- };
28-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;
3132 notifierConfiguration = {
33 apiVersion = 1;
34 notifiers = cfg.provision.notifiers;
35 };
3637- notifierFile = pkgs.writeText "notifier.yaml" (builtins.toJSON notifierConfiguration);
3839 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";
4748- provisionConfDir = pkgs.runCommand "grafana-provisioning" { } ''
00000000049 mkdir -p $out/{datasources,dashboards,notifiers,alerting}
50- ln -sf ${datasourceFile} $out/datasources/datasource.yaml
51- ln -sf ${dashboardFile} $out/dashboards/dashboard.yaml
52- 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
58 '';
5960 # Get a submodule without any embedded metadata:
61 _filter = x: filterAttrs (k: v: k != "_module") x;
620000000000000000000063 # http://docs.grafana.org/administration/provisioning/#datasources
64 grafanaTypes.datasourceConfig = types.submodule {
65 freeformType = provisioningSettingsFormat.type;
660000000000067 options = {
68 name = mkOption {
69 type = types.str;
···92 type = types.bool;
93 default = false;
94 description = lib.mdDoc "Allow users to edit datasources from the UI.";
95- };
96- password = mkOption {
97- type = types.nullOr types.str;
98- default = null;
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>
105- '';
106- };
107- basicAuthPassword = mkOption {
108- type = types.nullOr types.str;
109- default = null;
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>
116- '';
117 };
118 secureJsonData = mkOption {
119 type = types.nullOr types.attrs;
···276 (mkRemovedOptionModule [ "services" "grafana" "auth" "google" "clientSecretFile" ] ''
277 This option has been removed. Use 'services.grafana.settings.google.client_secret' with file provider instead.
278 '')
0000279280 (mkRemovedOptionModule [ "services" "grafana" "auth" "azuread" "tenantId" ] "This option has been deprecated upstream.")
281 ];
···330 Don't change the value of this option if you are planning to use `services.grafana.provision` options.
331 '';
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
344- \'\'
345- '';
346 type = types.path;
347 };
348 };
···564565 datasources = mkOption {
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.
570 '';
571- default = [];
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.
580 '';
···591 description = lib.mdDoc "List of datasources to insert/update.";
592 default = [];
593 type = types.listOf grafanaTypes.datasourceConfig;
0594 };
595596 deleteDatasources = mkOption {
···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.
0634 '';
635 default = null;
636 type = types.nullOr types.path;
637 };
638- });
639 };
640641642 dashboards = mkOption {
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.
647 '';
648- default = [];
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.
657 '';
···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.
0688 '';
689 default = null;
690 type = types.nullOr types.path;
691 };
692- });
693 };
694695···706 path = mkOption {
707 description = lib.mdDoc ''
708 Path to YAML rules configuration. Can't be used with
709- `services.grafana.provision.alerting.rules.settings` simultaneously.
0710 '';
711 default = null;
712 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.
721 '';
···829 path = mkOption {
830 description = lib.mdDoc ''
831 Path to YAML contact points configuration. Can't be used with
832- `services.grafana.provision.alerting.contactPoints.settings` simultaneously.
0833 '';
834 default = null;
835 type = types.nullOr types.path;
···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.
844 '';
···852 };
853854 contactPoints = mkOption {
855- description = lib.mdDoc "List of contact points to import or update. Please note that sensitive data will end up in world-readable Nix store.";
856 default = [];
857 type = types.listOf (types.submodule {
858 freeformType = provisioningSettingsFormat.type;
···909 path = mkOption {
910 description = lib.mdDoc ''
911 Path to YAML notification policies configuration. Can't be used with
912- `services.grafana.provision.alerting.policies.settings` simultaneously.
0913 '';
914 default = null;
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.
924 '';
···978 path = mkOption {
979 description = lib.mdDoc ''
980 Path to YAML templates configuration. Can't be used with
981- `services.grafana.provision.alerting.templates.settings` simultaneously.
0982 '';
983 default = null;
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.
993 '';
···1059 path = mkOption {
1060 description = lib.mdDoc ''
1061 Path to YAML mute timings configuration. Can't be used with
1062- `services.grafana.provision.alerting.muteTimings.settings` simultaneously.
01063 '';
1064 default = null;
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.
1074 '';
···11591160 config = mkIf cfg.enable {
1161 warnings = let
1162- usesFileProvider = opt: defaultValue: builtins.match "^${defaultValue}$|^\\$__file\\{.*}$" opt != null;
1163- in flatten [
1164- (optional (
1165- ! usesFileProvider cfg.settings.database.password "" ||
1166- ! usesFileProvider cfg.settings.security.admin_password "admin"
1167- ) "Grafana passwords will be stored as plaintext in the Nix store! Use file provider instead.")
1168- (optional (
1169 let
1170- checkOpts = opt: any (x: x.password != null || x.basicAuthPassword != null || x.secureJsonData != null) opt;
1171- datasourcesUsed = if (cfg.provision.datasources.settings == null) then [] else cfg.provision.datasources.settings.datasources;
1172- in if (builtins.isList cfg.provision.datasources) then checkOpts cfg.provision.datasources else checkOpts datasourcesUsed
1173- ) ''
1174- Datasource passwords will be stored as plaintext in the Nix store!
1175- It is not possible to use file provider in provisioning; please provision
1176- datasources via `services.grafana.provision.datasources.path` instead.
1177- '')
1178 (optional (
1179- any (x: x.secure_settings != null) cfg.provision.notifiers
1180- ) "Notifier secure settings will be stored as plaintext in the Nix store! Use file provider instead.")
1181- (optional (
1182- builtins.isList cfg.provision.datasources && cfg.provision.datasources != []
1183 ) ''
1184- Provisioning Grafana datasources with options has been deprecated.
1185- Use `services.grafana.provision.datasources.settings` or
1186- `services.grafana.provision.datasources.path` instead.
1187- '')
1188- (optional (
1189- builtins.isList cfg.provision.datasources && cfg.provision.dashboards != []
00000000000001190 ) ''
1191- Provisioning Grafana dashboards with options has been deprecated.
1192- Use `services.grafana.provision.dashboards.settings` or
1193- `services.grafana.provision.dashboards.path` instead.
1194- '')
1195- (optional (
1196- cfg.provision.notifiers != []
1197- ) ''
1198- Notifiers are deprecated upstream and will be removed in Grafana 10.
1199- Use `services.grafana.provision.alerting.contactPoints` instead.
1200- '')
1201- ];
12021203 environment.systemPackages = [ cfg.package ];
12041205 assertions = [
1206 {
1207- assertion = if (builtins.isList cfg.provision.datasources) then true else cfg.provision.datasources.settings == null || cfg.provision.datasources.path == null;
1208 message = "Cannot set both datasources settings and datasources path";
1209 }
1210 {
···1213 ({ type, access, ... }: type == "prometheus" -> access != "direct")
1214 opt;
1215 in
1216- if (builtins.isList cfg.provision.datasources) then prometheusIsNotDirect cfg.provision.datasources
1217- else cfg.provision.datasources.settings == null || prometheusIsNotDirect cfg.provision.datasources.settings.datasources;
1218 message = "For datasources of type `prometheus`, the `direct` access mode is not supported anymore (since Grafana 9.2.0)";
1219 }
1220 {
1221- assertion = if (builtins.isList cfg.provision.dashboards) then true else cfg.provision.dashboards.settings == null || cfg.provision.dashboards.path == null;
1222 message = "Cannot set both dashboards settings and dashboards path";
1223 }
1224 {
···13 settingsFormatIni = pkgs.formats.ini {};
14 configFile = settingsFormatIni.generate "config.ini" cfg.settings;
1516+ mkProvisionCfg = name: attr: provisionCfg:
17+ if provisionCfg.path != null
18+ then provisionCfg.path
19+ else
20+ provisioningSettingsFormat.generate "${name}.yaml"
21+ (if provisionCfg.settings != null
22+ then provisionCfg.settings
23+ else {
24+ apiVersion = 1;
25+ ${attr} = [];
26+ });
2728+ datasourceFileOrDir = mkProvisionCfg "datasource" "datasources" cfg.provision.datasources;
29+ dashboardFileOrDir = mkProvisionCfg "dashboard" "providers" cfg.provision.dashboards;
000000003031 notifierConfiguration = {
32 apiVersion = 1;
33 notifiers = cfg.provision.notifiers;
34 };
3536+ notifierFileOrDir = pkgs.writeText "notifier.yaml" (builtins.toJSON notifierConfiguration);
3738 generateAlertingProvisioningYaml = x: if (cfg.provision.alerting."${x}".path == null)
39 then provisioningSettingsFormat.generate "${x}.yaml" cfg.provision.alerting."${x}".settings
40 else cfg.provision.alerting."${x}".path;
41+ rulesFileOrDir = generateAlertingProvisioningYaml "rules";
42+ contactPointsFileOrDir = generateAlertingProvisioningYaml "contactPoints";
43+ policiesFileOrDir = generateAlertingProvisioningYaml "policies";
44+ templatesFileOrDir = generateAlertingProvisioningYaml "templates";
45+ muteTimingsFileOrDir = generateAlertingProvisioningYaml "muteTimings";
4647+ ln = { src, dir, filename }: ''
48+ if [[ -d "${src}" ]]; then
49+ pushd $out/${dir} &>/dev/null
50+ lndir "${src}"
51+ popd &>/dev/null
52+ else
53+ ln -sf ${src} $out/${dir}/${filename}.yaml
54+ fi
55+ '';
56+ provisionConfDir = pkgs.runCommand "grafana-provisioning" { nativeBuildInputs = [ pkgs.xorg.lndir ]; } ''
57 mkdir -p $out/{datasources,dashboards,notifiers,alerting}
58+ ${ln { src = datasourceFileOrDir; dir = "datasources"; filename = "datasource"; }}
59+ ${ln { src = dashboardFileOrDir; dir = "dashboards"; filename = "dashbaord"; }}
60+ ${ln { src = notifierFileOrDir; dir = "notifiers"; filename = "notifier"; }}
61+ ${ln { src = rulesFileOrDir; dir = "alerting"; filename = "rules"; }}
62+ ${ln { src = contactPointsFileOrDir; dir = "alerting"; filename = "contactPoints"; }}
63+ ${ln { src = policiesFileOrDir; dir = "alerting"; filename = "policies"; }}
64+ ${ln { src = templatesFileOrDir; dir = "alerting"; filename = "templates"; }}
65+ ${ln { src = muteTimingsFileOrDir; dir = "alerting"; filename = "muteTimings"; }}
66 '';
6768 # Get a submodule without any embedded metadata:
69 _filter = x: filterAttrs (k: v: k != "_module") x;
7071+ # FIXME(@Ma27) remove before 23.05. This is just a helper-type
72+ # because `mkRenamedOptionModule` doesn't work if `foo.bar` is renamed
73+ # to `foo.bar.baz`.
74+ submodule' = module: types.coercedTo
75+ (mkOptionType {
76+ name = "grafana-provision-submodule";
77+ description = "Wrapper-type for backwards compat of Grafana's declarative provisioning";
78+ check = x:
79+ if builtins.isList x then
80+ throw ''
81+ Provisioning dashboards and datasources declaratively by
82+ setting `dashboards` or `datasources` to a list is not supported
83+ anymore. Use `services.grafana.provision.datasources.settings.datasources`
84+ (or `services.grafana.provision.dashboards.settings.providers`) instead.
85+ ''
86+ else isAttrs x || isFunction x;
87+ })
88+ id
89+ (types.submodule module);
90+91 # http://docs.grafana.org/administration/provisioning/#datasources
92 grafanaTypes.datasourceConfig = types.submodule {
93 freeformType = provisioningSettingsFormat.type;
9495+ imports = [
96+ (mkRemovedOptionModule [ "password" ] ''
97+ `services.grafana.provision.datasources.settings.datasources.<name>.password` has been removed
98+ in Grafana 9. Use `secureJsonData` instead.
99+ '')
100+ (mkRemovedOptionModule [ "basicAuthPassword" ] ''
101+ `services.grafana.provision.datasources.settings.datasources.<name>.basicAuthPassword` has been removed
102+ in Grafana 9. Use `secureJsonData` instead.
103+ '')
104+ ];
105+106 options = {
107 name = mkOption {
108 type = types.str;
···131 type = types.bool;
132 default = false;
133 description = lib.mdDoc "Allow users to edit datasources from the UI.";
0000000000000000000000134 };
135 secureJsonData = mkOption {
136 type = types.nullOr types.attrs;
···293 (mkRemovedOptionModule [ "services" "grafana" "auth" "google" "clientSecretFile" ] ''
294 This option has been removed. Use 'services.grafana.settings.google.client_secret' with file provider instead.
295 '')
296+ (mkRemovedOptionModule [ "services" "grafana" "extraOptions" ] ''
297+ This option has been removed. Use 'services.grafana.settings' instead. For a detailed migration guide, please
298+ review the release notes of NixOS 22.11.
299+ '')
300301 (mkRemovedOptionModule [ "services" "grafana" "auth" "azuread" "tenantId" ] "This option has been deprecated upstream.")
302 ];
···351 Don't change the value of this option if you are planning to use `services.grafana.provision` options.
352 '';
353 default = provisionConfDir;
354+ defaultText = "directory with links to files generated from services.grafana.provision";
000000000000355 type = types.path;
356 };
357 };
···573574 datasources = mkOption {
575 description = lib.mdDoc ''
576+ Declaratively provision Grafana's datasources.
00577 '';
578+ default = {};
579+ type = submodule' {
0580 options.settings = mkOption {
581 description = lib.mdDoc ''
582 Grafana datasource configuration in Nix. Can't be used with
583+ [](#opt-services.grafana.provision.datasources.path) simultaneously. See
584 <https://grafana.com/docs/grafana/latest/administration/provisioning/#data-sources>
585 for supported options.
586 '';
···597 description = lib.mdDoc "List of datasources to insert/update.";
598 default = [];
599 type = types.listOf grafanaTypes.datasourceConfig;
600+ apply = map (flip builtins.removeAttrs [ "password" "basicAuthPassword" ]);
601 };
602603 deleteDatasources = mkOption {
···637 options.path = mkOption {
638 description = lib.mdDoc ''
639 Path to YAML datasource configuration. Can't be used with
640+ [](#opt-services.grafana.provision.datasources.settings) simultaneously.
641+ Can be either a directory or a single YAML file. Will end up in the store.
642 '';
643 default = null;
644 type = types.nullOr types.path;
645 };
646+ };
647 };
648649650 dashboards = mkOption {
651 description = lib.mdDoc ''
652+ Declaratively provision Grafana's dashboards.
00653 '';
654+ default = {};
655+ type = submodule' {
0656 options.settings = mkOption {
657 description = lib.mdDoc ''
658 Grafana dashboard configuration in Nix. Can't be used with
659+ [](#opt-services.grafana.provision.dashboards.path) simultaneously. See
660 <https://grafana.com/docs/grafana/latest/administration/provisioning/#dashboards>
661 for supported options.
662 '';
···689 options.path = mkOption {
690 description = lib.mdDoc ''
691 Path to YAML dashboard configuration. Can't be used with
692+ [](#opt-services.grafana.provision.dashboards.settings) simultaneously.
693+ Can be either a directory or a single YAML file. Will end up in the store.
694 '';
695 default = null;
696 type = types.nullOr types.path;
697 };
698+ };
699 };
700701···712 path = mkOption {
713 description = lib.mdDoc ''
714 Path to YAML rules configuration. Can't be used with
715+ [](#opt-services.grafana.provision.alerting.rules.settings) simultaneously.
716+ Can be either a directory or a single YAML file. Will end up in the store.
717 '';
718 default = null;
719 type = types.nullOr types.path;
···722 settings = mkOption {
723 description = lib.mdDoc ''
724 Grafana rules configuration in Nix. Can't be used with
725+ [](#opt-services.grafana.provision.alerting.rules.path) simultaneously. See
726 <https://grafana.com/docs/grafana/latest/administration/provisioning/#rules>
727 for supported options.
728 '';
···836 path = mkOption {
837 description = lib.mdDoc ''
838 Path to YAML contact points configuration. Can't be used with
839+ [](#opt-services.grafana.provision.alerting.contactPoints.settings) simultaneously.
840+ Can be either a directory or a single YAML file. Will end up in the store.
841 '';
842 default = null;
843 type = types.nullOr types.path;
···846 settings = mkOption {
847 description = lib.mdDoc ''
848 Grafana contact points configuration in Nix. Can't be used with
849+ [](#opt-services.grafana.provision.alerting.contactPoints.path) simultaneously. See
850 <https://grafana.com/docs/grafana/latest/administration/provisioning/#contact-points>
851 for supported options.
852 '';
···860 };
861862 contactPoints = mkOption {
863+ description = lib.mdDoc "List of contact points to import or update.";
864 default = [];
865 type = types.listOf (types.submodule {
866 freeformType = provisioningSettingsFormat.type;
···917 path = mkOption {
918 description = lib.mdDoc ''
919 Path to YAML notification policies configuration. Can't be used with
920+ [](#opt-services.grafana.provision.alerting.policies.settings) simultaneously.
921+ Can be either a directory or a single YAML file. Will end up in the store.
922 '';
923 default = null;
924 type = types.nullOr types.path;
···927 settings = mkOption {
928 description = lib.mdDoc ''
929 Grafana notification policies configuration in Nix. Can't be used with
930+ [](#opt-services.grafana.provision.alerting.policies.path) simultaneously. See
931 <https://grafana.com/docs/grafana/latest/administration/provisioning/#notification-policies>
932 for supported options.
933 '';
···987 path = mkOption {
988 description = lib.mdDoc ''
989 Path to YAML templates configuration. Can't be used with
990+ [](#opt-services.grafana.provision.alerting.templates.settings) simultaneously.
991+ Can be either a directory or a single YAML file. Will end up in the store.
992 '';
993 default = null;
994 type = types.nullOr types.path;
···997 settings = mkOption {
998 description = lib.mdDoc ''
999 Grafana templates configuration in Nix. Can't be used with
1000+ [](#opt-services.grafana.provision.alerting.templates.path) simultaneously. See
1001 <https://grafana.com/docs/grafana/latest/administration/provisioning/#templates>
1002 for supported options.
1003 '';
···1069 path = mkOption {
1070 description = lib.mdDoc ''
1071 Path to YAML mute timings configuration. Can't be used with
1072+ [](#opt-services.grafana.provision.alerting.muteTimings.settings) simultaneously.
1073+ Can be either a directory or a single YAML file. Will end up in the store.
1074 '';
1075 default = null;
1076 type = types.nullOr types.path;
···1079 settings = mkOption {
1080 description = lib.mdDoc ''
1081 Grafana mute timings configuration in Nix. Can't be used with
1082+ [](#opt-services.grafana.provision.alerting.muteTimings.path) simultaneously. See
1083 <https://grafana.com/docs/grafana/latest/administration/provisioning/#mute-timings>
1084 for supported options.
1085 '';
···11701171 config = mkIf cfg.enable {
1172 warnings = let
1173+ doesntUseFileProvider = opt: defaultValue:
0000001174 let
1175+ regex = "${optionalString (defaultValue != null) "^${defaultValue}$|"}^\\$__(file|env)\\{.*}$|^\\$[^_\\$][^ ]+$";
1176+ in builtins.match regex opt == null;
1177+ in
1178+ # Ensure that no custom credentials are leaked into the Nix store. Unless the default value
1179+ # is specified, this can be achieved by using the file/env provider:
1180+ # https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#variable-expansion
001181 (optional (
1182+ doesntUseFileProvider cfg.settings.database.password "" ||
1183+ doesntUseFileProvider cfg.settings.security.admin_password "admin"
001184 ) ''
1185+ Grafana passwords will be stored as plaintext in the Nix store!
1186+ Use file provider or an env-var instead.
1187+ '')
1188+ # Warn about deprecated notifiers.
1189+ ++ (optional (cfg.provision.notifiers != []) ''
1190+ Notifiers are deprecated upstream and will be removed in Grafana 10.
1191+ Use `services.grafana.provision.alerting.contactPoints` instead.
1192+ '')
1193+ # Ensure that `secureJsonData` of datasources provisioned via `datasources.settings`
1194+ # only uses file/env providers.
1195+ ++ (optional (
1196+ let
1197+ datasourcesToCheck = optionals
1198+ (cfg.provision.datasources.settings != null)
1199+ cfg.provision.datasources.settings.datasources;
1200+ declarationUnsafe = { secureJsonData, ... }:
1201+ secureJsonData != null
1202+ && any (flip doesntUseFileProvider null) (attrValues secureJsonData);
1203+ in any declarationUnsafe datasourcesToCheck
1204 ) ''
1205+ Declarations in the `secureJsonData`-block of a datasource will be leaked to the
1206+ Nix store unless a file-provider or an env-var is used!
1207+ '')
1208+ ++ (optional (
1209+ any (x: x.secure_settings != null) cfg.provision.notifiers
1210+ ) "Notifier secure settings will be stored as plaintext in the Nix store! Use file provider instead.");
0000012111212 environment.systemPackages = [ cfg.package ];
12131214 assertions = [
1215 {
1216+ assertion = cfg.provision.datasources.settings == null || cfg.provision.datasources.path == null;
1217 message = "Cannot set both datasources settings and datasources path";
1218 }
1219 {
···1222 ({ type, access, ... }: type == "prometheus" -> access != "direct")
1223 opt;
1224 in
1225+ cfg.provision.datasources.settings == null || prometheusIsNotDirect cfg.provision.datasources.settings.datasources;
01226 message = "For datasources of type `prometheus`, the `direct` access mode is not supported anymore (since Grafana 9.2.0)";
1227 }
1228 {
1229+ assertion = cfg.provision.dashboards.settings == null || cfg.provision.dashboards.path == null;
1230 message = "Cannot set both dashboards settings and dashboards path";
1231 }
1232 {