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