nixos-modules/modules/grafana.nix

129 lines
4.6 KiB
Nix
Raw Permalink Normal View History

2023-06-28 14:46:52 +02:00
{ config, lib, libS, ... }:
2022-12-23 05:53:53 +01:00
let
cfg = config.services.grafana;
in
{
2023-01-03 02:05:36 +01:00
options = {
2023-12-03 21:46:41 +01:00
services.grafana = {
2023-12-03 21:59:40 +01:00
configureNginx = lib.mkOption {
type = lib.types.bool;
default = false;
description = lib.mdDoc "Wether to configure Nginx.";
};
2023-12-03 21:46:41 +01:00
oauth = {
enable = lib.mkEnableOption (lib.mdDoc ''login only via OAuth2'');
enableViewerRole = lib.mkOption {
type = lib.types.bool;
default = false;
2023-12-03 21:46:41 +01:00
description = lib.mdDoc "Wether to enable the fallback Viewer role when users do not have the user- or adminGroup.";
};
adminGroup = libS.ldap.mkUserGroupOption;
userGroup = libS.ldap.mkUserGroupOption;
};
recommendedDefaults = libS.mkOpinionatedOption "set recommended and secure default settings";
};
2022-12-23 05:53:53 +01:00
};
2023-12-03 21:46:41 +01:00
config = {
# the default values are hardcoded instead of using options. because I couldn't figure out how to extract them from the freeform type
2023-12-03 21:46:41 +01:00
assertions = lib.mkIf cfg.enable [
{
assertion = cfg.oauth.enable -> cfg.settings."auth.generic_oauth".client_secret != null;
message = ''
2023-12-05 02:52:08 +01:00
Setting services.grafana.oauth.enable to true requires to set services.grafana.settings."auth.generic_oauth".client_secret.
Use this `$__file{/path/to/some/secret}` syntax to reference secrets securely.
2023-12-03 21:46:41 +01:00
'';
}
{
2023-06-28 14:51:48 +02:00
assertion = cfg.settings.security.secret_key != "SW2YcwTIb9zpOOhoPsMm";
message = "services.grafana.settings.security.secret_key must be changed from it's insecure, default value!";
}
{
assertion = cfg.settings.security.admin_password != "admin";
message = "services.grafana.settings.security.admin_password must be changed from it's insecure, default value!";
}
];
2023-12-03 21:46:41 +01:00
services.grafana.settings = lib.mkMerge [
(lib.mkIf (cfg.enable && cfg.recommendedDefaults) (libS.modules.mkRecursiveDefault {
# no analytics, sorry, not sorry
analytics = {
feedback_links_enabled = false;
reporting_enabled = false;
};
2023-12-03 23:19:10 +01:00
log.level = "warn";
2023-12-03 21:46:41 +01:00
security = {
cookie_secure = true;
content_security_policy = true;
strict_transport_security = true;
};
server = {
enable_gzip = true;
root_url = "https://${cfg.settings.server.domain}";
};
}))
(lib.mkIf (cfg.enable && cfg.oauth.enable) {
"auth.generic_oauth" = let
2023-12-05 02:52:23 +01:00
inherit (config.services.dex.settings) issuer;
2023-12-03 21:46:41 +01:00
in {
enabled = true;
allow_assign_grafana_admin = true; # required for grafana-admins
allow_sign_up = true; # otherwise no new users can be created
2023-12-05 02:52:23 +01:00
api_url = "${issuer}/userinfo";
auth_url = "${issuer}/auth";
2023-12-03 21:46:41 +01:00
client_id = "grafana";
disable_login_form = true; # only allow OAuth
icon = "signin";
2023-12-05 02:52:23 +01:00
name = config.services.portunus.domain;
2023-12-03 23:19:20 +01:00
oauth_allow_insecure_email_lookup = true; # otherwise updating the mail in ldap will break login
2023-12-03 21:46:41 +01:00
oauth_auto_login = true; # redirect automatically to the only oauth provider
2023-12-03 23:19:20 +01:00
use_refresh_token = true;
2023-12-03 21:46:41 +01:00
role_attribute_path = "contains(groups[*], 'grafana-admins') && 'Admin' || contains(info.roles[*], 'grafana-user') && 'Editor'"
+ lib.optionalString cfg.oauth.enableViewerRole "|| 'Viewer'";
role_attribute_strict = true;
# https://dexidp.io/docs/custom-scopes-claims-clients/
scopes = "openid email groups profile offline_access";
2023-12-05 02:52:23 +01:00
token_url = "${issuer}/token";
2023-12-03 21:46:41 +01:00
};
server.protocol = "socket";
2023-12-03 21:46:41 +01:00
})
];
};
2023-12-03 21:59:40 +01:00
config.services.nginx = lib.mkIf (cfg.enable && cfg.configureNginx) {
2024-01-08 14:47:38 +01:00
upstreams.grafana.servers."unix:${cfg.settings.server.socket}" = { };
2023-12-03 21:59:40 +01:00
virtualHosts = {
"${cfg.settings.server.domain}".locations = {
"/".proxyPass = "http://grafana";
"/api/live/ws" = {
proxyPass = "http://grafana";
proxyWebsockets = true;
};
};
};
};
2023-12-03 21:46:41 +01:00
config.services.portunus = {
dex = lib.mkIf cfg.oauth.enable {
enable = true;
oidcClients = [{
callbackURL = "https://${cfg.settings.server.domain}/login/generic_oauth";
id = "grafana";
}];
};
seedSettings.groups = lib.optional (cfg.oauth.adminGroup != null) {
long_name = "Grafana Administrators";
2023-12-03 21:59:40 +01:00
name = cfg.oauth.adminGroup;
2023-12-03 21:46:41 +01:00
permissions = { };
} ++ lib.optional (cfg.oauth.userGroup != null) {
long_name = "Grafana Users";
2023-12-03 21:59:40 +01:00
name = cfg.oauth.userGroup;
2023-12-03 21:46:41 +01:00
permissions = { };
};
2022-12-23 05:53:53 +01:00
};
}