1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.grafana; 7 8 b2s = val: if val then "true" else "false"; 9 10 envOptions = { 11 PATHS_DATA = cfg.dataDir; 12 PATHS_LOGS = "${cfg.dataDir}/log"; 13 14 SERVER_PROTOCOL = cfg.protocol; 15 SERVER_HTTP_ADDR = cfg.addr; 16 SERVER_HTTP_PORT = cfg.port; 17 SERVER_DOMAIN = cfg.domain; 18 SERVER_ROOT_URL = cfg.rootUrl; 19 SERVER_STATIC_ROOT_PATH = cfg.staticRootPath; 20 SERVER_CERT_FILE = cfg.certFile; 21 SERVER_CERT_KEY = cfg.certKey; 22 23 DATABASE_TYPE = cfg.database.type; 24 DATABASE_HOST = cfg.database.host; 25 DATABASE_NAME = cfg.database.name; 26 DATABASE_USER = cfg.database.user; 27 DATABASE_PASSWORD = cfg.database.password; 28 DATABASE_PATH = cfg.database.path; 29 30 SECURITY_ADMIN_USER = cfg.security.adminUser; 31 SECURITY_ADMIN_PASSWORD = cfg.security.adminPassword; 32 SECURITY_SECRET_KEY = cfg.security.secretKey; 33 34 USERS_ALLOW_SIGN_UP = b2s cfg.users.allowSignUp; 35 USERS_ALLOW_ORG_CREATE = b2s cfg.users.allowOrgCreate; 36 USERS_AUTO_ASSIGN_ORG = b2s cfg.users.autoAssignOrg; 37 USERS_AUTO_ASSIGN_ORG_ROLE = cfg.users.autoAssignOrgRole; 38 39 AUTH_ANONYMOUS_ENABLE = b2s cfg.auth.anonymous.enable; 40 } // cfg.extraOptions; 41 42in { 43 options.services.grafana = { 44 enable = mkEnableOption "grafana"; 45 46 protocol = mkOption { 47 description = "Which protocol to listen."; 48 default = "http"; 49 type = types.enum ["http" "https"]; 50 }; 51 52 addr = mkOption { 53 description = "Listening address."; 54 default = "127.0.0.1"; 55 type = types.str; 56 }; 57 58 port = mkOption { 59 description = "Listening port."; 60 default = 3000; 61 type = types.int; 62 }; 63 64 domain = mkOption { 65 description = "The public facing domain name used to access grafana from a browser."; 66 default = "localhost"; 67 type = types.str; 68 }; 69 70 rootUrl = mkOption { 71 description = "Full public facing url."; 72 default = "%(protocol)s://%(domain)s:%(http_port)s/"; 73 type = types.str; 74 }; 75 76 certFile = mkOption { 77 description = "Cert file for ssl."; 78 default = ""; 79 type = types.str; 80 }; 81 82 certKey = mkOption { 83 description = "Cert key for ssl."; 84 default = ""; 85 type = types.str; 86 }; 87 88 staticRootPath = mkOption { 89 description = "Root path for static assets."; 90 default = "${cfg.package.out}/share/grafana/public"; 91 type = types.str; 92 }; 93 94 package = mkOption { 95 description = "Package to use."; 96 default = pkgs.grafana; 97 defaultText = "pkgs.grafana"; 98 type = types.package; 99 }; 100 101 dataDir = mkOption { 102 description = "Data directory."; 103 default = "/var/lib/grafana"; 104 type = types.path; 105 }; 106 107 database = { 108 type = mkOption { 109 description = "Database type."; 110 default = "sqlite3"; 111 type = types.enum ["mysql" "sqlite3" "postgresql"]; 112 }; 113 114 host = mkOption { 115 description = "Database host."; 116 default = "127.0.0.1:3306"; 117 type = types.str; 118 }; 119 120 name = mkOption { 121 description = "Database name."; 122 default = "grafana"; 123 type = types.str; 124 }; 125 126 user = mkOption { 127 description = "Database user."; 128 default = "root"; 129 type = types.str; 130 }; 131 132 password = mkOption { 133 description = "Database password."; 134 default = ""; 135 type = types.str; 136 }; 137 138 path = mkOption { 139 description = "Database path."; 140 default = "${cfg.dataDir}/data/grafana.db"; 141 type = types.path; 142 }; 143 }; 144 145 security = { 146 adminUser = mkOption { 147 description = "Default admin username."; 148 default = "admin"; 149 type = types.str; 150 }; 151 152 adminPassword = mkOption { 153 description = "Default admin password."; 154 default = "admin"; 155 type = types.str; 156 }; 157 158 secretKey = mkOption { 159 description = "Secret key used for signing."; 160 default = "SW2YcwTIb9zpOOhoPsMm"; 161 type = types.str; 162 }; 163 }; 164 165 users = { 166 allowSignUp = mkOption { 167 description = "Disable user signup / registration"; 168 default = false; 169 type = types.bool; 170 }; 171 172 allowOrgCreate = mkOption { 173 description = "Whether user is allowed to create organizations."; 174 default = false; 175 type = types.bool; 176 }; 177 178 autoAssignOrg = mkOption { 179 description = "Whether to automatically assign new users to default org."; 180 default = true; 181 type = types.bool; 182 }; 183 184 autoAssignOrgRole = mkOption { 185 description = "Default role new users will be auto assigned."; 186 default = "Viewer"; 187 type = types.enum ["Viewer" "Editor"]; 188 }; 189 }; 190 191 auth.anonymous = { 192 enable = mkOption { 193 description = "Whether to allow anonymous access"; 194 default = false; 195 type = types.bool; 196 }; 197 }; 198 199 extraOptions = mkOption { 200 description = '' 201 Extra configuration options passed as env variables as specified in 202 <link xlink:href="http://docs.grafana.org/installation/configuration/">documentation</link>, 203 but without GF_ prefix 204 ''; 205 default = {}; 206 type = types.attrsOf types.str; 207 }; 208 }; 209 210 config = mkIf cfg.enable { 211 warnings = [ 212 "Grafana passwords will be stored as plaintext in the Nix store!" 213 ]; 214 215 systemd.services.grafana = { 216 description = "Grafana Service Daemon"; 217 wantedBy = ["multi-user.target"]; 218 after = ["networking.target"]; 219 environment = mapAttrs' (n: v: nameValuePair "GF_${n}" (toString v)) envOptions; 220 serviceConfig = { 221 ExecStart = "${cfg.package}/bin/grafana -homepath ${cfg.dataDir}"; 222 WorkingDirectory = cfg.dataDir; 223 User = "grafana"; 224 }; 225 preStart = '' 226 ln -fs ${cfg.package}/share/grafana/conf ${cfg.dataDir} 227 ''; 228 }; 229 230 users.extraUsers.grafana = { 231 uid = config.ids.uids.grafana; 232 description = "Grafana user"; 233 home = cfg.dataDir; 234 createHome = true; 235 }; 236 }; 237}