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 = mkOption { 28 description = "Whether to enable Zookeeper."; 29 default = false; 30 type = types.bool; 31 }; 32 33 port = mkOption { 34 description = "Zookeeper Client port."; 35 default = 2181; 36 type = types.int; 37 }; 38 39 id = mkOption { 40 description = "Zookeeper ID."; 41 default = 0; 42 type = types.int; 43 }; 44 45 purgeInterval = mkOption { 46 description = '' 47 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. 48 ''; 49 default = 1; 50 type = types.int; 51 }; 52 53 extraConf = mkOption { 54 description = "Extra configuration for Zookeeper."; 55 type = types.lines; 56 default = '' 57 initLimit=5 58 syncLimit=2 59 tickTime=2000 60 ''; 61 }; 62 63 servers = mkOption { 64 description = "All Zookeeper Servers."; 65 default = ""; 66 type = types.lines; 67 example = '' 68 server.0=host0:2888:3888 69 server.1=host1:2888:3888 70 server.2=host2:2888:3888 71 ''; 72 }; 73 74 logging = mkOption { 75 description = "Zookeeper logging configuration."; 76 default = '' 77 zookeeper.root.logger=INFO, CONSOLE 78 log4j.rootLogger=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 = types.lines; 84 }; 85 86 dataDir = mkOption { 87 type = types.path; 88 default = "/var/lib/zookeeper"; 89 description = '' 90 Data directory for Zookeeper 91 ''; 92 }; 93 94 extraCmdLineOptions = mkOption { 95 description = "Extra command line options for the Zookeeper launcher."; 96 default = [ "-Dcom.sun.management.jmxremote" "-Dcom.sun.management.jmxremote.local.only=true" ]; 97 type = types.listOf types.str; 98 example = [ "-Djava.net.preferIPv4Stack=true" "-Dcom.sun.management.jmxremote" "-Dcom.sun.management.jmxremote.local.only=true" ]; 99 }; 100 101 preferIPv4 = mkOption { 102 type = types.bool; 103 default = true; 104 description = '' 105 Add the -Djava.net.preferIPv4Stack=true flag to the Zookeeper server. 106 ''; 107 }; 108 109 }; 110 111 112 config = mkIf cfg.enable { 113 systemd.services.zookeeper = { 114 description = "Zookeeper Daemon"; 115 wantedBy = [ "multi-user.target" ]; 116 after = [ "network-interfaces.target" ]; 117 environment = { ZOOCFGDIR = configDir; }; 118 serviceConfig = { 119 ExecStart = '' 120 ${pkgs.jre}/bin/java \ 121 -cp "${pkgs.zookeeper}/lib/*:${pkgs.zookeeper}/${pkgs.zookeeper.name}.jar:${configDir}" \ 122 ${toString cfg.extraCmdLineOptions} \ 123 -Dzookeeper.datadir.autocreate=false \ 124 ${optionalString cfg.preferIPv4 "-Djava.net.preferIPv4Stack=true"} \ 125 org.apache.zookeeper.server.quorum.QuorumPeerMain \ 126 ${configDir}/zoo.cfg 127 ''; 128 User = "zookeeper"; 129 PermissionsStartOnly = true; 130 }; 131 preStart = '' 132 mkdir -m 0700 -p ${cfg.dataDir} 133 if [ "$(id -u)" = 0 ]; then chown zookeeper ${cfg.dataDir}; fi 134 echo "${toString cfg.id}" > ${cfg.dataDir}/myid 135 ''; 136 }; 137 138 users.extraUsers = singleton { 139 name = "zookeeper"; 140 uid = config.ids.uids.zookeeper; 141 description = "Zookeeper daemon user"; 142 home = cfg.dataDir; 143 }; 144 }; 145}