1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.kibana;
7
8 atLeast54 = versionAtLeast (builtins.parseDrvName cfg.package.name).version "5.4";
9
10 cfgFile = if atLeast54 then cfgFile5 else cfgFile4;
11
12 cfgFile4 = pkgs.writeText "kibana.json" (builtins.toJSON (
13 (filterAttrsRecursive (n: v: v != null) ({
14 host = cfg.listenAddress;
15 port = cfg.port;
16 ssl_cert_file = cfg.cert;
17 ssl_key_file = cfg.key;
18
19 kibana_index = cfg.index;
20 default_app_id = cfg.defaultAppId;
21
22 elasticsearch_url = cfg.elasticsearch.url;
23 kibana_elasticsearch_username = cfg.elasticsearch.username;
24 kibana_elasticsearch_password = cfg.elasticsearch.password;
25 kibana_elasticsearch_cert = cfg.elasticsearch.cert;
26 kibana_elasticsearch_key = cfg.elasticsearch.key;
27 ca = cfg.elasticsearch.ca;
28
29 bundled_plugin_ids = [
30 "plugins/dashboard/index"
31 "plugins/discover/index"
32 "plugins/doc/index"
33 "plugins/kibana/index"
34 "plugins/markdown_vis/index"
35 "plugins/metric_vis/index"
36 "plugins/settings/index"
37 "plugins/table_vis/index"
38 "plugins/vis_types/index"
39 "plugins/visualize/index"
40 ];
41 } // cfg.extraConf)
42 )));
43
44 cfgFile5 = pkgs.writeText "kibana.json" (builtins.toJSON (
45 (filterAttrsRecursive (n: v: v != null) ({
46 server.host = cfg.listenAddress;
47 server.port = cfg.port;
48 server.ssl.certificate = cfg.cert;
49 server.ssl.key = cfg.key;
50
51 kibana.index = cfg.index;
52 kibana.defaultAppId = cfg.defaultAppId;
53
54 elasticsearch.url = cfg.elasticsearch.url;
55 elasticsearch.username = cfg.elasticsearch.username;
56 elasticsearch.password = cfg.elasticsearch.password;
57
58 elasticsearch.ssl.certificate = cfg.elasticsearch.cert;
59 elasticsearch.ssl.key = cfg.elasticsearch.key;
60 elasticsearch.ssl.certificateAuthorities = cfg.elasticsearch.certificateAuthorities;
61 } // cfg.extraConf)
62 )));
63
64in {
65 options.services.kibana = {
66 enable = mkEnableOption "enable kibana service";
67
68 listenAddress = mkOption {
69 description = "Kibana listening host";
70 default = "127.0.0.1";
71 type = types.str;
72 };
73
74 port = mkOption {
75 description = "Kibana listening port";
76 default = 5601;
77 type = types.int;
78 };
79
80 cert = mkOption {
81 description = "Kibana ssl certificate.";
82 default = null;
83 type = types.nullOr types.path;
84 };
85
86 key = mkOption {
87 description = "Kibana ssl key.";
88 default = null;
89 type = types.nullOr types.path;
90 };
91
92 index = mkOption {
93 description = "Elasticsearch index to use for saving kibana config.";
94 default = ".kibana";
95 type = types.str;
96 };
97
98 defaultAppId = mkOption {
99 description = "Elasticsearch default application id.";
100 default = "discover";
101 type = types.str;
102 };
103
104 elasticsearch = {
105 url = mkOption {
106 description = "Elasticsearch url";
107 default = "http://localhost:9200";
108 type = types.str;
109 };
110
111 username = mkOption {
112 description = "Username for elasticsearch basic auth.";
113 default = null;
114 type = types.nullOr types.str;
115 };
116
117 password = mkOption {
118 description = "Password for elasticsearch basic auth.";
119 default = null;
120 type = types.nullOr types.str;
121 };
122
123 ca = mkOption {
124 description = ''
125 CA file to auth against elasticsearch.
126
127 It's recommended to use the <option>certificateAuthorities</option> option
128 when using kibana-5.4 or newer.
129 '';
130 default = null;
131 type = types.nullOr types.path;
132 };
133
134 certificateAuthorities = mkOption {
135 description = ''
136 CA files to auth against elasticsearch.
137
138 Please use the <option>ca</option> option when using kibana < 5.4
139 because those old versions don't support setting multiple CA's.
140
141 This defaults to the singleton list [ca] when the <option>ca</option> option is defined.
142 '';
143 default = if isNull cfg.elasticsearch.ca then [] else [ca];
144 type = types.listOf types.path;
145 };
146
147 cert = mkOption {
148 description = "Certificate file to auth against elasticsearch.";
149 default = null;
150 type = types.nullOr types.path;
151 };
152
153 key = mkOption {
154 description = "Key file to auth against elasticsearch.";
155 default = null;
156 type = types.nullOr types.path;
157 };
158 };
159
160 package = mkOption {
161 description = "Kibana package to use";
162 default = pkgs.kibana;
163 defaultText = "pkgs.kibana";
164 example = "pkgs.kibana5";
165 type = types.package;
166 };
167
168 dataDir = mkOption {
169 description = "Kibana data directory";
170 default = "/var/lib/kibana";
171 type = types.path;
172 };
173
174 extraConf = mkOption {
175 description = "Kibana extra configuration";
176 default = {};
177 type = types.attrs;
178 };
179 };
180
181 config = mkIf (cfg.enable) {
182 systemd.services.kibana = {
183 description = "Kibana Service";
184 wantedBy = [ "multi-user.target" ];
185 after = [ "network.target" "elasticsearch.service" ];
186 environment = { BABEL_CACHE_PATH = "${cfg.dataDir}/.babelcache.json"; };
187 serviceConfig = {
188 ExecStart = "${cfg.package}/bin/kibana --config ${cfgFile}";
189 User = "kibana";
190 WorkingDirectory = cfg.dataDir;
191 };
192 };
193
194 environment.systemPackages = [ cfg.package ];
195
196 users.extraUsers = singleton {
197 name = "kibana";
198 uid = config.ids.uids.kibana;
199 description = "Kibana service user";
200 home = cfg.dataDir;
201 createHome = true;
202 };
203 };
204}