1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.elasticsearch;
7
8 esConfig = ''
9 network.host: ${cfg.listenAddress}
10 network.port: ${toString cfg.port}
11 network.tcp.port: ${toString cfg.tcp_port}
12 # TODO: find a way to enable security manager
13 security.manager.enabled: false
14 cluster.name: ${cfg.cluster_name}
15 ${cfg.extraConf}
16 '';
17
18 configDir = pkgs.buildEnv {
19 name = "elasticsearch-config";
20 paths = [
21 (pkgs.writeTextDir "elasticsearch.yml" esConfig)
22 (pkgs.writeTextDir "logging.yml" cfg.logging)
23 ];
24 };
25
26 esPlugins = pkgs.buildEnv {
27 name = "elasticsearch-plugins";
28 paths = cfg.plugins;
29 };
30
31in {
32
33 ###### interface
34
35 options.services.elasticsearch = {
36 enable = mkOption {
37 description = "Whether to enable elasticsearch.";
38 default = false;
39 type = types.bool;
40 };
41
42 package = mkOption {
43 description = "Elasticsearch package to use.";
44 default = pkgs.elasticsearch2;
45 defaultText = "pkgs.elasticsearch2";
46 type = types.package;
47 };
48
49 listenAddress = mkOption {
50 description = "Elasticsearch listen address.";
51 default = "127.0.0.1";
52 type = types.str;
53 };
54
55 port = mkOption {
56 description = "Elasticsearch port to listen for HTTP traffic.";
57 default = 9200;
58 type = types.int;
59 };
60
61 tcp_port = mkOption {
62 description = "Elasticsearch port for the node to node communication.";
63 default = 9300;
64 type = types.int;
65 };
66
67 cluster_name = mkOption {
68 description = "Elasticsearch name that identifies your cluster for auto-discovery.";
69 default = "elasticsearch";
70 type = types.str;
71 };
72
73 extraConf = mkOption {
74 description = "Extra configuration for elasticsearch.";
75 default = "";
76 type = types.str;
77 example = ''
78 node.name: "elasticsearch"
79 node.master: true
80 node.data: false
81 index.number_of_shards: 5
82 index.number_of_replicas: 1
83 '';
84 };
85
86 logging = mkOption {
87 description = "Elasticsearch logging configuration.";
88 default = ''
89 rootLogger: INFO, console
90 logger:
91 action: INFO
92 com.amazonaws: WARN
93 appender:
94 console:
95 type: console
96 layout:
97 type: consolePattern
98 conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n"
99 '';
100 type = types.str;
101 };
102
103 dataDir = mkOption {
104 type = types.path;
105 default = "/var/lib/elasticsearch";
106 description = ''
107 Data directory for elasticsearch.
108 '';
109 };
110
111 extraCmdLineOptions = mkOption {
112 description = "Extra command line options for the elasticsearch launcher.";
113 default = [];
114 type = types.listOf types.str;
115 example = [ "-Djava.net.preferIPv4Stack=true" ];
116 };
117
118 plugins = mkOption {
119 description = "Extra elasticsearch plugins";
120 default = [];
121 type = types.listOf types.package;
122 };
123
124 };
125
126 ###### implementation
127
128 config = mkIf cfg.enable {
129 systemd.services.elasticsearch = {
130 description = "Elasticsearch Daemon";
131 wantedBy = [ "multi-user.target" ];
132 after = [ "network-interfaces.target" ];
133 path = [ pkgs.inetutils ];
134 environment = {
135 ES_HOME = cfg.dataDir;
136 };
137 serviceConfig = {
138 ExecStart = "${cfg.package}/bin/elasticsearch -Des.path.conf=${configDir} ${toString cfg.extraCmdLineOptions}";
139 User = "elasticsearch";
140 PermissionsStartOnly = true;
141 };
142 preStart = ''
143 mkdir -m 0700 -p ${cfg.dataDir}
144
145 # Install plugins
146 ln -sfT ${esPlugins}/plugins ${cfg.dataDir}/plugins
147 ln -sfT ${cfg.package}/lib ${cfg.dataDir}/lib
148 ln -sfT ${cfg.package}/modules ${cfg.dataDir}/modules
149 if [ "$(id -u)" = 0 ]; then chown -R elasticsearch ${cfg.dataDir}; fi
150 '';
151 postStart = mkBefore ''
152 until ${pkgs.curl.bin}/bin/curl -s -o /dev/null ${cfg.listenAddress}:${toString cfg.port}; do
153 sleep 1
154 done
155 '';
156 };
157
158 environment.systemPackages = [ cfg.package ];
159
160 users = {
161 groups.elasticsearch.gid = config.ids.gids.elasticsearch;
162 users.elasticsearch = {
163 uid = config.ids.uids.elasticsearch;
164 description = "Elasticsearch daemon user";
165 home = cfg.dataDir;
166 group = "elasticsearch";
167 };
168 };
169 };
170}