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