1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7let
8 cfg = config.services.zookeeper;
9
10 zookeeperConfig = ''
11 dataDir=${cfg.dataDir}
12 clientPort=${toString cfg.port}
13 autopurge.purgeInterval=${toString cfg.purgeInterval}
14 ${cfg.extraConf}
15 ${cfg.servers}
16 '';
17
18 configDir = pkgs.buildEnv {
19 name = "zookeeper-conf";
20 paths = [
21 (pkgs.writeTextDir "zoo.cfg" zookeeperConfig)
22 (pkgs.writeTextDir "log4j.properties" cfg.logging)
23 ];
24 };
25
26in
27{
28
29 options.services.zookeeper = {
30 enable = lib.mkEnableOption "Zookeeper";
31
32 port = lib.mkOption {
33 description = "Zookeeper Client port.";
34 default = 2181;
35 type = lib.types.port;
36 };
37
38 id = lib.mkOption {
39 description = "Zookeeper ID.";
40 default = 0;
41 type = lib.types.int;
42 };
43
44 purgeInterval = lib.mkOption {
45 description = ''
46 The time interval in hours for which the purge task has to be triggered. Set to a positive integer (1 and above) to enable the auto purging.
47 '';
48 default = 1;
49 type = lib.types.int;
50 };
51
52 extraConf = lib.mkOption {
53 description = "Extra configuration for Zookeeper.";
54 type = lib.types.lines;
55 default = ''
56 initLimit=5
57 syncLimit=2
58 tickTime=2000
59 '';
60 };
61
62 servers = lib.mkOption {
63 description = "All Zookeeper Servers.";
64 default = "";
65 type = lib.types.lines;
66 example = ''
67 server.0=host0:2888:3888
68 server.1=host1:2888:3888
69 server.2=host2:2888:3888
70 '';
71 };
72
73 logging = lib.mkOption {
74 description = "Zookeeper logging configuration.";
75 default = ''
76 zookeeper.root.logger=INFO, CONSOLE
77 log4j.rootLogger=INFO, CONSOLE
78 log4j.logger.org.apache.zookeeper.audit.Log4jAuditLogger=INFO, CONSOLE
79 log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
80 log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
81 log4j.appender.CONSOLE.layout.ConversionPattern=[myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n
82 '';
83 type = lib.types.lines;
84 };
85
86 dataDir = lib.mkOption {
87 type = lib.types.path;
88 default = "/var/lib/zookeeper";
89 description = ''
90 Data directory for Zookeeper
91 '';
92 };
93
94 extraCmdLineOptions = lib.mkOption {
95 description = "Extra command line options for the Zookeeper launcher.";
96 default = [
97 "-Dcom.sun.management.jmxremote"
98 "-Dcom.sun.management.jmxremote.local.only=true"
99 ];
100 type = lib.types.listOf lib.types.str;
101 example = [
102 "-Djava.net.preferIPv4Stack=true"
103 "-Dcom.sun.management.jmxremote"
104 "-Dcom.sun.management.jmxremote.local.only=true"
105 ];
106 };
107
108 preferIPv4 = lib.mkOption {
109 type = lib.types.bool;
110 default = true;
111 description = ''
112 Add the -Djava.net.preferIPv4Stack=true flag to the Zookeeper server.
113 '';
114 };
115
116 package = lib.mkPackageOption pkgs "zookeeper" { };
117
118 jre = lib.mkOption {
119 description = "The JRE with which to run Zookeeper";
120 default = cfg.package.jre;
121 defaultText = lib.literalExpression "pkgs.zookeeper.jre";
122 example = lib.literalExpression "pkgs.jre";
123 type = lib.types.package;
124 };
125 };
126
127 config = lib.mkIf cfg.enable {
128 environment.systemPackages = [ cfg.package ];
129
130 systemd.tmpfiles.rules = [
131 "d '${cfg.dataDir}' 0700 zookeeper - - -"
132 "Z '${cfg.dataDir}' 0700 zookeeper - - -"
133 ];
134
135 systemd.services.zookeeper = {
136 description = "Zookeeper Daemon";
137 wantedBy = [ "multi-user.target" ];
138 after = [ "network.target" ];
139 serviceConfig = {
140 ExecStart = ''
141 ${cfg.jre}/bin/java \
142 -cp "${cfg.package}/lib/*:${configDir}" \
143 ${lib.escapeShellArgs cfg.extraCmdLineOptions} \
144 -Dzookeeper.datadir.autocreate=false \
145 ${lib.optionalString cfg.preferIPv4 "-Djava.net.preferIPv4Stack=true"} \
146 org.apache.zookeeper.server.quorum.QuorumPeerMain \
147 ${configDir}/zoo.cfg
148 '';
149 User = "zookeeper";
150 };
151 preStart = ''
152 echo "${toString cfg.id}" > ${cfg.dataDir}/myid
153 mkdir -p ${cfg.dataDir}/version-2
154 '';
155 };
156
157 users.users.zookeeper = {
158 isSystemUser = true;
159 group = "zookeeper";
160 description = "Zookeeper daemon user";
161 home = cfg.dataDir;
162 };
163 users.groups.zookeeper = { };
164 };
165}