{ config, lib, pkgs, ... }: with lib; let cfg = config.services.grafana; b2s = val: if val then "true" else "false"; cfgFile = pkgs.writeText "grafana.ini" '' app_name = grafana app_mode = production [server] ; protocol (http or https) protocol = ${cfg.protocol} ; the ip address to bind to, empty will bind to all interfaces http_addr = ${cfg.addr} ; the http port to use http_port = ${toString cfg.port} ; The public facing domain name used to access grafana from a browser domain = ${cfg.domain} ; the full public facing url root_url = ${cfg.rootUrl} router_logging = false ; the path relative to the binary where the static (html/js/css) files are placed static_root_path = ${cfg.staticRootPath} ; enable gzip enable_gzip = false ; https certs & key file cert_file = ${cfg.certFile} cert_key = ${cfg.certKey} [analytics] # Server reporting, sends usage counters to stats.grafana.org every 24 hours. # No ip addresses are being tracked, only simple counters to track # running instances, dashboard and error counts. It is very helpful to us. # Change this option to false to disable reporting. reporting_enabled = true ; Google Analytics universal tracking code, only enabled if you specify an id here google_analytics_ua_id = [database] ; Either "mysql", "postgres" or "sqlite3", it's your choice type = ${cfg.database.type} host = ${cfg.database.host} name = ${cfg.database.name} user = ${cfg.database.user} password = ${cfg.database.password} ; For "postgres" only, either "disable", "require" or "verify-full" ssl_mode = disable ; For "sqlite3" only path = ${cfg.database.path} [session] ; Either "memory", "file", "redis", "mysql", default is "memory" provider = file ; Provider config options ; memory: not have any config yet ; file: session file path, e.g. `data/sessions` ; redis: config like redis server addr, poolSize, password, e.g. `127.0.0.1:6379,100,grafana` ; mysql: go-sql-driver/mysql dsn config string, e.g. `user:password@tcp(127.0.0.1)/database_name` provider_config = data/sessions ; Session cookie name cookie_name = grafana_sess ; If you use session in https only, default is false cookie_secure = false ; Session life time, default is 86400 session_life_time = 86400 ; session id hash func, Either "sha1", "sha256" or "md5" default is sha1 session_id_hashfunc = sha1 ; Session hash key, default is use random string session_id_hashkey = [security] ; default admin user, created on startup admin_user = ${cfg.security.adminUser} ; default admin password, can be changed before first start of grafana, or in profile settings admin_password = ${cfg.security.adminPassword} ; used for signing secret_key = ${cfg.security.secretKey} ; Auto-login remember days login_remember_days = 7 cookie_username = grafana_user cookie_remember_name = grafana_remember [users] ; disable user signup / registration allow_sign_up = ${b2s cfg.users.allowSignUp} ; Allow non admin users to create organizations allow_org_create = ${b2s cfg.users.allowOrgCreate} # Set to true to automatically assign new users to the default organization (id 1) auto_assign_org = ${b2s cfg.users.autoAssignOrg} ; Default role new users will be automatically assigned (if disabled above is set to true) auto_assign_org_role = ${cfg.users.autoAssignOrgRole} [auth.anonymous] ; enable anonymous access enabled = ${b2s cfg.auth.anonymous.enable} ; specify organization name that should be used for unauthenticated users org_name = Main Org. ; specify role for unauthenticated users org_role = Viewer [auth.github] enabled = false client_id = some_id client_secret = some_secret scopes = user:email auth_url = https://github.com/login/oauth/authorize token_url = https://github.com/login/oauth/access_token [auth.google] enabled = false client_id = some_client_id client_secret = some_client_secret scopes = https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email auth_url = https://accounts.google.com/o/oauth2/auth token_url = https://accounts.google.com/o/oauth2/token [log] root_path = data/log ; Either "console", "file", default is "console" ; Use comma to separate multiple modes, e.g. "console, file" mode = console ; Buffer length of channel, keep it as it is if you don't know what it is. buffer_len = 10000 ; Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Trace" level = Info ; For "console" mode only [log.console] level = ; For "file" mode only [log.file] level = ; This enables automated log rotate(switch of following options), default is true log_rotate = true ; Max line number of single file, default is 1000000 max_lines = 1000000 ; Max size shift of single file, default is 28 means 1 << 28, 256MB max_lines_shift = 28 ; Segment log daily, default is true daily_rotate = true ; Expired days of log file(delete after max days), default is 7 max_days = 7 [event_publisher] enabled = false rabbitmq_url = amqp://localhost/ exchange = grafana_events ''; in { options.services.grafana = { enable = mkEnableOption "Whether to enable grafana."; protocol = mkOption { description = "Which protocol to listen."; default = "http"; type = types.enum ["http" "https"]; }; addr = mkOption { description = "Listening address."; default = "127.0.0.1"; type = types.str; }; port = mkOption { description = "Listening port."; default = 3000; type = types.int; }; domain = mkOption { description = "The public facing domain name used to access grafana from a browser."; default = "localhost"; type = types.str; }; rootUrl = mkOption { description = "Full public facing url."; default = "%(protocol)s://%(domain)s:%(http_port)s/"; type = types.str; }; certFile = mkOption { description = "Cert file for ssl."; default = ""; type = types.str; }; certKey = mkOption { description = "Cert key for ssl."; default = ""; type = types.str; }; staticRootPath = mkOption { description = "Root path for static assets."; default = "${cfg.package}/share/go/src/github.com/grafana/grafana/public"; type = types.str; }; package = mkOption { description = "Package to use."; default = pkgs.goPackages.grafana; type = types.package; }; dataDir = mkOption { description = "Data directory."; default = "/var/lib/grafana"; type = types.path; }; database = { type = mkOption { description = "Database type."; default = "sqlite3"; type = types.enum ["mysql" "sqlite3" "postgresql"]; }; host = mkOption { description = "Database host."; default = "127.0.0.1:3306"; type = types.str; }; name = mkOption { description = "Database name."; default = "grafana"; type = types.str; }; user = mkOption { description = "Database user."; default = "root"; type = types.str; }; password = mkOption { description = "Database password."; default = ""; type = types.str; }; path = mkOption { description = "Database path."; default = "${cfg.dataDir}/data/grafana.db"; type = types.path; }; }; security = { adminUser = mkOption { description = "Default admin username."; default = "admin"; type = types.str; }; adminPassword = mkOption { description = "Default admin password."; default = "admin"; type = types.str; }; secretKey = mkOption { description = "Secret key used for signing."; default = "SW2YcwTIb9zpOOhoPsMm"; type = types.str; }; }; users = { allowSignUp = mkOption { description = "Disable user signup / registration"; default = false; type = types.bool; }; allowOrgCreate = mkOption { description = "Whether user is allowed to create organizations."; default = false; type = types.bool; }; autoAssignOrg = mkOption { description = "Whether to automatically assign new users to default org."; default = true; type = types.bool; }; autoAssignOrgRole = mkOption { description = "Default role new users will be auto assigned."; default = "Viewer"; type = types.enum ["Viewer" "Editor"]; }; }; auth.anonymous = { enable = mkOption { description = "Whether to allow anonymous access"; default = false; type = types.bool; }; }; }; config = mkIf cfg.enable { warnings = [ "Grafana passwords will be stored as plaintext in nix store!" ]; systemd.services.grafana = { description = "Grafana Service Daemon"; wantedBy = ["multi-user.target"]; after = ["networking.target"]; serviceConfig = { ExecStart = "${cfg.package}/bin/grafana --config ${cfgFile} web"; WorkingDirectory = cfg.dataDir; User = "grafana"; }; }; users.extraUsers.grafana = { uid = config.ids.uids.grafana; description = "Grafana user"; home = cfg.dataDir; createHome = true; }; }; }