···12061206 </listitem>
12071207 <listitem>
12081208 <para>
12091209- The <literal>services.grafana</literal> options were converted
12101210- to a
12091209+ The module <literal>services.grafana</literal> was refactored
12101210+ to be compliant with
12111211 <link xlink:href="https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md">RFC
12121212- 0042</link> configuration.
12121212+ 0042</link>. To be precise, this means that the following
12131213+ things have changed:
12131214 </para>
12141214- </listitem>
12151215- <listitem>
12161216- <para>
12171217- The <literal>services.grafana.provision.datasources</literal>
12181218- and <literal>services.grafana.provision.dashboards</literal>
12191219- options were converted to a
12201220- <link xlink:href="https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md">RFC
12211221- 0042</link> configuration. They also now support specifying
12221222- the provisioning YAML file with <literal>path</literal>
12231223- option.
12241224- </para>
12151215+ <itemizedlist>
12161216+ <listitem>
12171217+ <para>
12181218+ The newly introduced option
12191219+ <xref linkend="opt-services.grafana.settings" /> is an
12201220+ attribute-set that will be converted into Grafana’s INI
12211221+ format. This means that the configuration from
12221222+ <link xlink:href="https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/">Grafana’s
12231223+ configuration reference</link> can be directly written as
12241224+ attribute-set in Nix within this option.
12251225+ </para>
12261226+ </listitem>
12271227+ <listitem>
12281228+ <para>
12291229+ The option
12301230+ <literal>services.grafana.extraOptions</literal> has been
12311231+ removed. This option was an association of environment
12321232+ variables for Grafana. If you had an expression like
12331233+ </para>
12341234+ <programlisting language="bash">
12351235+{
12361236+ services.grafana.extraOptions.SECURITY_ADMIN_USER = "foobar";
12371237+}
12381238+</programlisting>
12391239+ <para>
12401240+ your Grafana instance was running with
12411241+ <literal>GF_SECURITY_ADMIN_USER=foobar</literal> in its
12421242+ environment.
12431243+ </para>
12441244+ <para>
12451245+ For the migration, it is recommended to turn it into the
12461246+ INI format, i.e. to declare
12471247+ </para>
12481248+ <programlisting language="bash">
12491249+{
12501250+ services.grafana.settings.security.admin_user = "foobar";
12511251+}
12521252+</programlisting>
12531253+ <para>
12541254+ instead.
12551255+ </para>
12561256+ <para>
12571257+ The keys in
12581258+ <literal>services.grafana.extraOptions</literal> have the
12591259+ format
12601260+ <literal><INI section name>_<Key Name></literal>.
12611261+ Further details are outlined in the
12621262+ <link xlink:href="https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#override-configuration-with-environment-variables">configuration
12631263+ reference</link>.
12641264+ </para>
12651265+ <para>
12661266+ Alternatively you can also set all your values from
12671267+ <literal>extraOptions</literal> to
12681268+ <literal>systemd.services.grafana.environment</literal>,
12691269+ make sure you don’t forget to add the
12701270+ <literal>GF_</literal> prefix though!
12711271+ </para>
12721272+ </listitem>
12731273+ <listitem>
12741274+ <para>
12751275+ Previously, the options
12761276+ <xref linkend="opt-services.grafana.provision.datasources" />
12771277+ and
12781278+ <xref linkend="opt-services.grafana.provision.dashboards" />
12791279+ expected lists of datasources or dashboards for the
12801280+ <link xlink:href="https://grafana.com/docs/grafana/latest/administration/provisioning/">declarative
12811281+ provisioning</link>.
12821282+ </para>
12831283+ <para>
12841284+ To declare lists of
12851285+ </para>
12861286+ <itemizedlist spacing="compact">
12871287+ <listitem>
12881288+ <para>
12891289+ <emphasis role="strong">datasources</emphasis>, please
12901290+ rename your declarations to
12911291+ <xref linkend="opt-services.grafana.provision.datasources.settings.datasources" />.
12921292+ </para>
12931293+ </listitem>
12941294+ <listitem>
12951295+ <para>
12961296+ <emphasis role="strong">dashboards</emphasis>, please
12971297+ rename your declarations to
12981298+ <xref linkend="opt-services.grafana.provision.dashboards.settings.providers" />.
12991299+ </para>
13001300+ </listitem>
13011301+ </itemizedlist>
13021302+ <para>
13031303+ This change was made to support more features for that:
13041304+ </para>
13051305+ <itemizedlist>
13061306+ <listitem>
13071307+ <para>
13081308+ It’s possible to declare the
13091309+ <literal>apiVersion</literal> of your dashboards and
13101310+ datasources by
13111311+ <xref linkend="opt-services.grafana.provision.datasources.settings.apiVersion" />
13121312+ (or
13131313+ <xref linkend="opt-services.grafana.provision.dashboards.settings.apiVersion" />).
13141314+ </para>
13151315+ </listitem>
13161316+ <listitem>
13171317+ <para>
13181318+ Instead of declaring datasources and dashboards in
13191319+ pure Nix, it’s also possible to specify configuration
13201320+ files (or directories) with YAML instead using
13211321+ <xref linkend="opt-services.grafana.provision.datasources.path" />
13221322+ (or
13231323+ <xref linkend="opt-services.grafana.provision.dashboards.path" />.
13241324+ This is useful when having provisioning files from
13251325+ non-NixOS Grafana instances that you also want to
13261326+ deploy to NixOS.
13271327+ </para>
13281328+ <para>
13291329+ <emphasis role="strong">Note:</emphasis> secrets from
13301330+ these files will be leaked into the store unless you
13311331+ use a
13321332+ <link xlink:href="https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#file-provider"><emphasis role="strong">file</emphasis>-provider
13331333+ or env-var</link> for secrets!
13341334+ </para>
13351335+ </listitem>
13361336+ <listitem>
13371337+ <para>
13381338+ <xref linkend="opt-services.grafana.provision.notifiers" />
13391339+ is not affected by this change because this feature is
13401340+ deprecated by Grafana and will probably removed in
13411341+ Grafana 10. It’s recommended to use
13421342+ <literal>services.grafana.provision.alerting.contactPoints</literal>
13431343+ instead.
13441344+ </para>
13451345+ </listitem>
13461346+ </itemizedlist>
13471347+ </listitem>
13481348+ </itemizedlist>
12251349 </listitem>
12261350 <listitem>
12271351 <para>
+59-2
nixos/doc/manual/release-notes/rl-2211.section.md
···379379380380- The `services.matrix-synapse` systemd unit has been hardened.
381381382382-- The `services.grafana` options were converted to a [RFC 0042](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md) configuration.
382382+- 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:
383383+ - The newly introduced option [](#opt-services.grafana.settings) is an attribute-set that
384384+ will be converted into Grafana's INI format. This means that the configuration from
385385+ [Grafana's configuration reference](https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/)
386386+ can be directly written as attribute-set in Nix within this option.
387387+ - The option `services.grafana.extraOptions` has been removed. This option was an association
388388+ of environment variables for Grafana. If you had an expression like
389389+390390+ ```nix
391391+ {
392392+ services.grafana.extraOptions.SECURITY_ADMIN_USER = "foobar";
393393+ }
394394+ ```
395395+396396+ your Grafana instance was running with `GF_SECURITY_ADMIN_USER=foobar` in its environment.
397397+398398+ For the migration, it is recommended to turn it into the INI format, i.e.
399399+ to declare
400400+401401+ ```nix
402402+ {
403403+ services.grafana.settings.security.admin_user = "foobar";
404404+ }
405405+ ```
406406+407407+ instead.
408408+409409+ The keys in `services.grafana.extraOptions` have the format `<INI section name>_<Key Name>`.
410410+ Further details are outlined in the [configuration reference](https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#override-configuration-with-environment-variables).
411411+412412+ Alternatively you can also set all your values from `extraOptions` to
413413+ `systemd.services.grafana.environment`, make sure you don't forget to add
414414+ the `GF_` prefix though!
415415+ - Previously, the options [](#opt-services.grafana.provision.datasources) and
416416+ [](#opt-services.grafana.provision.dashboards) expected lists of datasources
417417+ or dashboards for the [declarative provisioning](https://grafana.com/docs/grafana/latest/administration/provisioning/).
418418+419419+ To declare lists of
420420+ - **datasources**, please rename your declarations to [](#opt-services.grafana.provision.datasources.settings.datasources).
421421+ - **dashboards**, please rename your declarations to [](#opt-services.grafana.provision.dashboards.settings.providers).
422422+423423+ This change was made to support more features for that:
383424384384-- 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.
425425+ - It's possible to declare the `apiVersion` of your dashboards and datasources
426426+ by [](#opt-services.grafana.provision.datasources.settings.apiVersion) (or
427427+ [](#opt-services.grafana.provision.dashboards.settings.apiVersion)).
428428+429429+ - Instead of declaring datasources and dashboards in pure Nix, it's also possible
430430+ to specify configuration files (or directories) with YAML instead using
431431+ [](#opt-services.grafana.provision.datasources.path) (or
432432+ [](#opt-services.grafana.provision.dashboards.path). This is useful when having
433433+ provisioning files from non-NixOS Grafana instances that you also want to
434434+ deploy to NixOS.
435435+436436+ __Note:__ secrets from these files will be leaked into the store unless you use a
437437+ [**file**-provider or env-var](https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#file-provider) for secrets!
438438+439439+ - [](#opt-services.grafana.provision.notifiers) is not affected by this change because
440440+ this feature is deprecated by Grafana and will probably removed in Grafana 10.
441441+ It's recommended to use `services.grafana.provision.alerting.contactPoints` instead.
385442386443- 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.
387444
+141-133
nixos/modules/services/monitoring/grafana.nix
···1313 settingsFormatIni = pkgs.formats.ini {};
1414 configFile = settingsFormatIni.generate "config.ini" cfg.settings;
15151616- datasourceConfiguration = {
1717- apiVersion = 1;
1818- datasources = cfg.provision.datasources;
1919- };
1616+ mkProvisionCfg = name: attr: provisionCfg:
1717+ if provisionCfg.path != null
1818+ then provisionCfg.path
1919+ else
2020+ provisioningSettingsFormat.generate "${name}.yaml"
2121+ (if provisionCfg.settings != null
2222+ then provisionCfg.settings
2323+ else {
2424+ apiVersion = 1;
2525+ ${attr} = [];
2626+ });
20272121- datasourceFileNew = if (cfg.provision.datasources.path == null) then provisioningSettingsFormat.generate "datasource.yaml" cfg.provision.datasources.settings else cfg.provision.datasources.path;
2222- datasourceFile = if (builtins.isList cfg.provision.datasources) then provisioningSettingsFormat.generate "datasource.yaml" datasourceConfiguration else datasourceFileNew;
2323-2424- dashboardConfiguration = {
2525- apiVersion = 1;
2626- providers = cfg.provision.dashboards;
2727- };
2828-2929- dashboardFileNew = if (cfg.provision.dashboards.path == null) then provisioningSettingsFormat.generate "dashboard.yaml" cfg.provision.dashboards.settings else cfg.provision.dashboards.path;
3030- dashboardFile = if (builtins.isList cfg.provision.dashboards) then provisioningSettingsFormat.generate "dashboard.yaml" dashboardConfiguration else dashboardFileNew;
2828+ datasourceFileOrDir = mkProvisionCfg "datasource" "datasources" cfg.provision.datasources;
2929+ dashboardFileOrDir = mkProvisionCfg "dashboard" "providers" cfg.provision.dashboards;
31303231 notifierConfiguration = {
3332 apiVersion = 1;
3433 notifiers = cfg.provision.notifiers;
3534 };
36353737- notifierFile = pkgs.writeText "notifier.yaml" (builtins.toJSON notifierConfiguration);
3636+ notifierFileOrDir = pkgs.writeText "notifier.yaml" (builtins.toJSON notifierConfiguration);
38373938 generateAlertingProvisioningYaml = x: if (cfg.provision.alerting."${x}".path == null)
4039 then provisioningSettingsFormat.generate "${x}.yaml" cfg.provision.alerting."${x}".settings
4140 else cfg.provision.alerting."${x}".path;
4242- rulesFile = generateAlertingProvisioningYaml "rules";
4343- contactPointsFile = generateAlertingProvisioningYaml "contactPoints";
4444- policiesFile = generateAlertingProvisioningYaml "policies";
4545- templatesFile = generateAlertingProvisioningYaml "templates";
4646- muteTimingsFile = generateAlertingProvisioningYaml "muteTimings";
4141+ rulesFileOrDir = generateAlertingProvisioningYaml "rules";
4242+ contactPointsFileOrDir = generateAlertingProvisioningYaml "contactPoints";
4343+ policiesFileOrDir = generateAlertingProvisioningYaml "policies";
4444+ templatesFileOrDir = generateAlertingProvisioningYaml "templates";
4545+ muteTimingsFileOrDir = generateAlertingProvisioningYaml "muteTimings";
47464848- provisionConfDir = pkgs.runCommand "grafana-provisioning" { } ''
4747+ ln = { src, dir, filename }: ''
4848+ if [[ -d "${src}" ]]; then
4949+ pushd $out/${dir} &>/dev/null
5050+ lndir "${src}"
5151+ popd &>/dev/null
5252+ else
5353+ ln -sf ${src} $out/${dir}/${filename}.yaml
5454+ fi
5555+ '';
5656+ provisionConfDir = pkgs.runCommand "grafana-provisioning" { nativeBuildInputs = [ pkgs.xorg.lndir ]; } ''
4957 mkdir -p $out/{datasources,dashboards,notifiers,alerting}
5050- ln -sf ${datasourceFile} $out/datasources/datasource.yaml
5151- ln -sf ${dashboardFile} $out/dashboards/dashboard.yaml
5252- ln -sf ${notifierFile} $out/notifiers/notifier.yaml
5353- ln -sf ${rulesFile} $out/alerting/rules.yaml
5454- ln -sf ${contactPointsFile} $out/alerting/contactPoints.yaml
5555- ln -sf ${policiesFile} $out/alerting/policies.yaml
5656- ln -sf ${templatesFile} $out/alerting/templates.yaml
5757- ln -sf ${muteTimingsFile} $out/alerting/muteTimings.yaml
5858+ ${ln { src = datasourceFileOrDir; dir = "datasources"; filename = "datasource"; }}
5959+ ${ln { src = dashboardFileOrDir; dir = "dashboards"; filename = "dashbaord"; }}
6060+ ${ln { src = notifierFileOrDir; dir = "notifiers"; filename = "notifier"; }}
6161+ ${ln { src = rulesFileOrDir; dir = "alerting"; filename = "rules"; }}
6262+ ${ln { src = contactPointsFileOrDir; dir = "alerting"; filename = "contactPoints"; }}
6363+ ${ln { src = policiesFileOrDir; dir = "alerting"; filename = "policies"; }}
6464+ ${ln { src = templatesFileOrDir; dir = "alerting"; filename = "templates"; }}
6565+ ${ln { src = muteTimingsFileOrDir; dir = "alerting"; filename = "muteTimings"; }}
5866 '';
59676068 # Get a submodule without any embedded metadata:
6169 _filter = x: filterAttrs (k: v: k != "_module") x;
62707171+ # FIXME(@Ma27) remove before 23.05. This is just a helper-type
7272+ # because `mkRenamedOptionModule` doesn't work if `foo.bar` is renamed
7373+ # to `foo.bar.baz`.
7474+ submodule' = module: types.coercedTo
7575+ (mkOptionType {
7676+ name = "grafana-provision-submodule";
7777+ description = "Wrapper-type for backwards compat of Grafana's declarative provisioning";
7878+ check = x:
7979+ if builtins.isList x then
8080+ throw ''
8181+ Provisioning dashboards and datasources declaratively by
8282+ setting `dashboards` or `datasources` to a list is not supported
8383+ anymore. Use `services.grafana.provision.datasources.settings.datasources`
8484+ (or `services.grafana.provision.dashboards.settings.providers`) instead.
8585+ ''
8686+ else isAttrs x || isFunction x;
8787+ })
8888+ id
8989+ (types.submodule module);
9090+6391 # http://docs.grafana.org/administration/provisioning/#datasources
6492 grafanaTypes.datasourceConfig = types.submodule {
6593 freeformType = provisioningSettingsFormat.type;
66949595+ imports = [
9696+ (mkRemovedOptionModule [ "password" ] ''
9797+ `services.grafana.provision.datasources.settings.datasources.<name>.password` has been removed
9898+ in Grafana 9. Use `secureJsonData` instead.
9999+ '')
100100+ (mkRemovedOptionModule [ "basicAuthPassword" ] ''
101101+ `services.grafana.provision.datasources.settings.datasources.<name>.basicAuthPassword` has been removed
102102+ in Grafana 9. Use `secureJsonData` instead.
103103+ '')
104104+ ];
105105+67106 options = {
68107 name = mkOption {
69108 type = types.str;
···92131 type = types.bool;
93132 default = false;
94133 description = lib.mdDoc "Allow users to edit datasources from the UI.";
9595- };
9696- password = mkOption {
9797- type = types.nullOr types.str;
9898- default = null;
9999- description = lib.mdDoc ''
100100- Database password, if used. Please note that the contents of this option
101101- will end up in a world-readable Nix store. Use the file provider
102102- pointing at a reasonably secured file in the local filesystem
103103- to work around that. Look at the documentation for details:
104104- <https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#file-provider>
105105- '';
106106- };
107107- basicAuthPassword = mkOption {
108108- type = types.nullOr types.str;
109109- default = null;
110110- description = lib.mdDoc ''
111111- Basic auth password. Please note that the contents of this option
112112- will end up in a world-readable Nix store. Use the file provider
113113- pointing at a reasonably secured file in the local filesystem
114114- to work around that. Look at the documentation for details:
115115- <https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#file-provider>
116116- '';
117134 };
118135 secureJsonData = mkOption {
119136 type = types.nullOr types.attrs;
···276293 (mkRemovedOptionModule [ "services" "grafana" "auth" "google" "clientSecretFile" ] ''
277294 This option has been removed. Use 'services.grafana.settings.google.client_secret' with file provider instead.
278295 '')
296296+ (mkRemovedOptionModule [ "services" "grafana" "extraOptions" ] ''
297297+ This option has been removed. Use 'services.grafana.settings' instead. For a detailed migration guide, please
298298+ review the release notes of NixOS 22.11.
299299+ '')
279300280301 (mkRemovedOptionModule [ "services" "grafana" "auth" "azuread" "tenantId" ] "This option has been deprecated upstream.")
281302 ];
···330351 Don't change the value of this option if you are planning to use `services.grafana.provision` options.
331352 '';
332353 default = provisionConfDir;
333333- defaultText = literalExpression ''
334334- pkgs.runCommand "grafana-provisioning" { } \'\'
335335- mkdir -p $out/{datasources,dashboards,notifiers,alerting}
336336- ln -sf ''${datasourceFile} $out/datasources/datasource.yaml
337337- ln -sf ''${dashboardFile} $out/dashboards/dashboard.yaml
338338- ln -sf ''${notifierFile} $out/notifiers/notifier.yaml
339339- ln -sf ''${rulesFile} $out/alerting/rules.yaml
340340- ln -sf ''${contactPointsFile} $out/alerting/contactPoints.yaml
341341- ln -sf ''${policiesFile} $out/alerting/policies.yaml
342342- ln -sf ''${templatesFile} $out/alerting/templates.yaml
343343- ln -sf ''${muteTimingsFile} $out/alerting/muteTimings.yaml
344344- \'\'
345345- '';
354354+ defaultText = "directory with links to files generated from services.grafana.provision";
346355 type = types.path;
347356 };
348357 };
···564573565574 datasources = mkOption {
566575 description = lib.mdDoc ''
567567- Deprecated option for Grafana datasource configuration. Use either
568568- `services.grafana.provision.datasources.settings` or
569569- `services.grafana.provision.datasources.path` instead.
576576+ Declaratively provision Grafana's datasources.
570577 '';
571571- default = [];
572572- apply = x: if (builtins.isList x) then map _filter x else x;
573573- type = with types; either (listOf grafanaTypes.datasourceConfig) (submodule {
578578+ default = {};
579579+ type = submodule' {
574580 options.settings = mkOption {
575581 description = lib.mdDoc ''
576582 Grafana datasource configuration in Nix. Can't be used with
577577- `services.grafana.provision.datasources.path` simultaneously. See
583583+ [](#opt-services.grafana.provision.datasources.path) simultaneously. See
578584 <https://grafana.com/docs/grafana/latest/administration/provisioning/#data-sources>
579585 for supported options.
580586 '';
···591597 description = lib.mdDoc "List of datasources to insert/update.";
592598 default = [];
593599 type = types.listOf grafanaTypes.datasourceConfig;
600600+ apply = map (flip builtins.removeAttrs [ "password" "basicAuthPassword" ]);
594601 };
595602596603 deleteDatasources = mkOption {
···630637 options.path = mkOption {
631638 description = lib.mdDoc ''
632639 Path to YAML datasource configuration. Can't be used with
633633- `services.grafana.provision.datasources.settings` simultaneously.
640640+ [](#opt-services.grafana.provision.datasources.settings) simultaneously.
641641+ Can be either a directory or a single YAML file. Will end up in the store.
634642 '';
635643 default = null;
636644 type = types.nullOr types.path;
637645 };
638638- });
646646+ };
639647 };
640648641649642650 dashboards = mkOption {
643651 description = lib.mdDoc ''
644644- Deprecated option for Grafana dashboard configuration. Use either
645645- `services.grafana.provision.dashboards.settings` or
646646- `services.grafana.provision.dashboards.path` instead.
652652+ Declaratively provision Grafana's dashboards.
647653 '';
648648- default = [];
649649- apply = x: if (builtins.isList x) then map _filter x else x;
650650- type = with types; either (listOf grafanaTypes.dashboardConfig) (submodule {
654654+ default = {};
655655+ type = submodule' {
651656 options.settings = mkOption {
652657 description = lib.mdDoc ''
653658 Grafana dashboard configuration in Nix. Can't be used with
654654- `services.grafana.provision.dashboards.path` simultaneously. See
659659+ [](#opt-services.grafana.provision.dashboards.path) simultaneously. See
655660 <https://grafana.com/docs/grafana/latest/administration/provisioning/#dashboards>
656661 for supported options.
657662 '';
···684689 options.path = mkOption {
685690 description = lib.mdDoc ''
686691 Path to YAML dashboard configuration. Can't be used with
687687- `services.grafana.provision.dashboards.settings` simultaneously.
692692+ [](#opt-services.grafana.provision.dashboards.settings) simultaneously.
693693+ Can be either a directory or a single YAML file. Will end up in the store.
688694 '';
689695 default = null;
690696 type = types.nullOr types.path;
691697 };
692692- });
698698+ };
693699 };
694700695701···706712 path = mkOption {
707713 description = lib.mdDoc ''
708714 Path to YAML rules configuration. Can't be used with
709709- `services.grafana.provision.alerting.rules.settings` simultaneously.
715715+ [](#opt-services.grafana.provision.alerting.rules.settings) simultaneously.
716716+ Can be either a directory or a single YAML file. Will end up in the store.
710717 '';
711718 default = null;
712719 type = types.nullOr types.path;
···715722 settings = mkOption {
716723 description = lib.mdDoc ''
717724 Grafana rules configuration in Nix. Can't be used with
718718- `services.grafana.provision.alerting.rules.path` simultaneously. See
725725+ [](#opt-services.grafana.provision.alerting.rules.path) simultaneously. See
719726 <https://grafana.com/docs/grafana/latest/administration/provisioning/#rules>
720727 for supported options.
721728 '';
···829836 path = mkOption {
830837 description = lib.mdDoc ''
831838 Path to YAML contact points configuration. Can't be used with
832832- `services.grafana.provision.alerting.contactPoints.settings` simultaneously.
839839+ [](#opt-services.grafana.provision.alerting.contactPoints.settings) simultaneously.
840840+ Can be either a directory or a single YAML file. Will end up in the store.
833841 '';
834842 default = null;
835843 type = types.nullOr types.path;
···838846 settings = mkOption {
839847 description = lib.mdDoc ''
840848 Grafana contact points configuration in Nix. Can't be used with
841841- `services.grafana.provision.alerting.contactPoints.path` simultaneously. See
849849+ [](#opt-services.grafana.provision.alerting.contactPoints.path) simultaneously. See
842850 <https://grafana.com/docs/grafana/latest/administration/provisioning/#contact-points>
843851 for supported options.
844852 '';
···852860 };
853861854862 contactPoints = mkOption {
855855- description = lib.mdDoc "List of contact points to import or update. Please note that sensitive data will end up in world-readable Nix store.";
863863+ description = lib.mdDoc "List of contact points to import or update.";
856864 default = [];
857865 type = types.listOf (types.submodule {
858866 freeformType = provisioningSettingsFormat.type;
···909917 path = mkOption {
910918 description = lib.mdDoc ''
911919 Path to YAML notification policies configuration. Can't be used with
912912- `services.grafana.provision.alerting.policies.settings` simultaneously.
920920+ [](#opt-services.grafana.provision.alerting.policies.settings) simultaneously.
921921+ Can be either a directory or a single YAML file. Will end up in the store.
913922 '';
914923 default = null;
915924 type = types.nullOr types.path;
···918927 settings = mkOption {
919928 description = lib.mdDoc ''
920929 Grafana notification policies configuration in Nix. Can't be used with
921921- `services.grafana.provision.alerting.policies.path` simultaneously. See
930930+ [](#opt-services.grafana.provision.alerting.policies.path) simultaneously. See
922931 <https://grafana.com/docs/grafana/latest/administration/provisioning/#notification-policies>
923932 for supported options.
924933 '';
···978987 path = mkOption {
979988 description = lib.mdDoc ''
980989 Path to YAML templates configuration. Can't be used with
981981- `services.grafana.provision.alerting.templates.settings` simultaneously.
990990+ [](#opt-services.grafana.provision.alerting.templates.settings) simultaneously.
991991+ Can be either a directory or a single YAML file. Will end up in the store.
982992 '';
983993 default = null;
984994 type = types.nullOr types.path;
···987997 settings = mkOption {
988998 description = lib.mdDoc ''
989999 Grafana templates configuration in Nix. Can't be used with
990990- `services.grafana.provision.alerting.templates.path` simultaneously. See
10001000+ [](#opt-services.grafana.provision.alerting.templates.path) simultaneously. See
9911001 <https://grafana.com/docs/grafana/latest/administration/provisioning/#templates>
9921002 for supported options.
9931003 '';
···10591069 path = mkOption {
10601070 description = lib.mdDoc ''
10611071 Path to YAML mute timings configuration. Can't be used with
10621062- `services.grafana.provision.alerting.muteTimings.settings` simultaneously.
10721072+ [](#opt-services.grafana.provision.alerting.muteTimings.settings) simultaneously.
10731073+ Can be either a directory or a single YAML file. Will end up in the store.
10631074 '';
10641075 default = null;
10651076 type = types.nullOr types.path;
···10681079 settings = mkOption {
10691080 description = lib.mdDoc ''
10701081 Grafana mute timings configuration in Nix. Can't be used with
10711071- `services.grafana.provision.alerting.muteTimings.path` simultaneously. See
10821082+ [](#opt-services.grafana.provision.alerting.muteTimings.path) simultaneously. See
10721083 <https://grafana.com/docs/grafana/latest/administration/provisioning/#mute-timings>
10731084 for supported options.
10741085 '';
···1159117011601171 config = mkIf cfg.enable {
11611172 warnings = let
11621162- usesFileProvider = opt: defaultValue: builtins.match "^${defaultValue}$|^\\$__file\\{.*}$" opt != null;
11631163- in flatten [
11641164- (optional (
11651165- ! usesFileProvider cfg.settings.database.password "" ||
11661166- ! usesFileProvider cfg.settings.security.admin_password "admin"
11671167- ) "Grafana passwords will be stored as plaintext in the Nix store! Use file provider instead.")
11681168- (optional (
11731173+ doesntUseFileProvider = opt: defaultValue:
11691174 let
11701170- checkOpts = opt: any (x: x.password != null || x.basicAuthPassword != null || x.secureJsonData != null) opt;
11711171- datasourcesUsed = if (cfg.provision.datasources.settings == null) then [] else cfg.provision.datasources.settings.datasources;
11721172- in if (builtins.isList cfg.provision.datasources) then checkOpts cfg.provision.datasources else checkOpts datasourcesUsed
11731173- ) ''
11741174- Datasource passwords will be stored as plaintext in the Nix store!
11751175- It is not possible to use file provider in provisioning; please provision
11761176- datasources via `services.grafana.provision.datasources.path` instead.
11771177- '')
11751175+ regex = "${optionalString (defaultValue != null) "^${defaultValue}$|"}^\\$__(file|env)\\{.*}$|^\\$[^_\\$][^ ]+$";
11761176+ in builtins.match regex opt == null;
11771177+ in
11781178+ # Ensure that no custom credentials are leaked into the Nix store. Unless the default value
11791179+ # is specified, this can be achieved by using the file/env provider:
11801180+ # https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#variable-expansion
11781181 (optional (
11791179- any (x: x.secure_settings != null) cfg.provision.notifiers
11801180- ) "Notifier secure settings will be stored as plaintext in the Nix store! Use file provider instead.")
11811181- (optional (
11821182- builtins.isList cfg.provision.datasources && cfg.provision.datasources != []
11821182+ doesntUseFileProvider cfg.settings.database.password "" ||
11831183+ doesntUseFileProvider cfg.settings.security.admin_password "admin"
11831184 ) ''
11841184- Provisioning Grafana datasources with options has been deprecated.
11851185- Use `services.grafana.provision.datasources.settings` or
11861186- `services.grafana.provision.datasources.path` instead.
11871187- '')
11881188- (optional (
11891189- builtins.isList cfg.provision.datasources && cfg.provision.dashboards != []
11851185+ Grafana passwords will be stored as plaintext in the Nix store!
11861186+ Use file provider or an env-var instead.
11871187+ '')
11881188+ # Warn about deprecated notifiers.
11891189+ ++ (optional (cfg.provision.notifiers != []) ''
11901190+ Notifiers are deprecated upstream and will be removed in Grafana 10.
11911191+ Use `services.grafana.provision.alerting.contactPoints` instead.
11921192+ '')
11931193+ # Ensure that `secureJsonData` of datasources provisioned via `datasources.settings`
11941194+ # only uses file/env providers.
11951195+ ++ (optional (
11961196+ let
11971197+ datasourcesToCheck = optionals
11981198+ (cfg.provision.datasources.settings != null)
11991199+ cfg.provision.datasources.settings.datasources;
12001200+ declarationUnsafe = { secureJsonData, ... }:
12011201+ secureJsonData != null
12021202+ && any (flip doesntUseFileProvider null) (attrValues secureJsonData);
12031203+ in any declarationUnsafe datasourcesToCheck
11901204 ) ''
11911191- Provisioning Grafana dashboards with options has been deprecated.
11921192- Use `services.grafana.provision.dashboards.settings` or
11931193- `services.grafana.provision.dashboards.path` instead.
11941194- '')
11951195- (optional (
11961196- cfg.provision.notifiers != []
11971197- ) ''
11981198- Notifiers are deprecated upstream and will be removed in Grafana 10.
11991199- Use `services.grafana.provision.alerting.contactPoints` instead.
12001200- '')
12011201- ];
12051205+ Declarations in the `secureJsonData`-block of a datasource will be leaked to the
12061206+ Nix store unless a file-provider or an env-var is used!
12071207+ '')
12081208+ ++ (optional (
12091209+ any (x: x.secure_settings != null) cfg.provision.notifiers
12101210+ ) "Notifier secure settings will be stored as plaintext in the Nix store! Use file provider instead.");
1202121112031212 environment.systemPackages = [ cfg.package ];
1204121312051214 assertions = [
12061215 {
12071207- assertion = if (builtins.isList cfg.provision.datasources) then true else cfg.provision.datasources.settings == null || cfg.provision.datasources.path == null;
12161216+ assertion = cfg.provision.datasources.settings == null || cfg.provision.datasources.path == null;
12081217 message = "Cannot set both datasources settings and datasources path";
12091218 }
12101219 {
···12131222 ({ type, access, ... }: type == "prometheus" -> access != "direct")
12141223 opt;
12151224 in
12161216- if (builtins.isList cfg.provision.datasources) then prometheusIsNotDirect cfg.provision.datasources
12171217- else cfg.provision.datasources.settings == null || prometheusIsNotDirect cfg.provision.datasources.settings.datasources;
12251225+ cfg.provision.datasources.settings == null || prometheusIsNotDirect cfg.provision.datasources.settings.datasources;
12181226 message = "For datasources of type `prometheus`, the `direct` access mode is not supported anymore (since Grafana 9.2.0)";
12191227 }
12201228 {
12211221- assertion = if (builtins.isList cfg.provision.dashboards) then true else cfg.provision.dashboards.settings == null || cfg.provision.dashboards.path == null;
12291229+ assertion = cfg.provision.dashboards.settings == null || cfg.provision.dashboards.path == null;
12221230 message = "Cannot set both dashboards settings and dashboards path";
12231231 }
12241232 {