at 25.11-pre 7.2 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8with lib; 9 10let 11 cfg = config.services.elasticsearch; 12 13 es7 = builtins.compareVersions cfg.package.version "7" >= 0; 14 15 esConfig = '' 16 network.host: ${cfg.listenAddress} 17 cluster.name: ${cfg.cluster_name} 18 ${lib.optionalString cfg.single_node "discovery.type: single-node"} 19 ${lib.optionalString (cfg.single_node && es7) "gateway.auto_import_dangling_indices: true"} 20 21 http.port: ${toString cfg.port} 22 transport.port: ${toString cfg.tcp_port} 23 24 ${cfg.extraConf} 25 ''; 26 27 configDir = cfg.dataDir + "/config"; 28 29 elasticsearchYml = pkgs.writeTextFile { 30 name = "elasticsearch.yml"; 31 text = esConfig; 32 }; 33 34 loggingConfigFilename = "log4j2.properties"; 35 loggingConfigFile = pkgs.writeTextFile { 36 name = loggingConfigFilename; 37 text = cfg.logging; 38 }; 39 40 esPlugins = pkgs.buildEnv { 41 name = "elasticsearch-plugins"; 42 paths = cfg.plugins; 43 postBuild = "${pkgs.coreutils}/bin/mkdir -p $out/plugins"; 44 }; 45 46in 47{ 48 49 ###### interface 50 51 options.services.elasticsearch = { 52 enable = mkOption { 53 description = "Whether to enable elasticsearch."; 54 default = false; 55 type = types.bool; 56 }; 57 58 package = mkPackageOption pkgs "elasticsearch" { }; 59 60 listenAddress = mkOption { 61 description = "Elasticsearch listen address."; 62 default = "127.0.0.1"; 63 type = types.str; 64 }; 65 66 port = mkOption { 67 description = "Elasticsearch port to listen for HTTP traffic."; 68 default = 9200; 69 type = types.port; 70 }; 71 72 tcp_port = mkOption { 73 description = "Elasticsearch port for the node to node communication."; 74 default = 9300; 75 type = types.int; 76 }; 77 78 cluster_name = mkOption { 79 description = "Elasticsearch name that identifies your cluster for auto-discovery."; 80 default = "elasticsearch"; 81 type = types.str; 82 }; 83 84 single_node = mkOption { 85 description = "Start a single-node cluster"; 86 default = true; 87 type = types.bool; 88 }; 89 90 extraConf = mkOption { 91 description = "Extra configuration for elasticsearch."; 92 default = ""; 93 type = types.str; 94 example = '' 95 node.name: "elasticsearch" 96 node.master: true 97 node.data: false 98 ''; 99 }; 100 101 logging = mkOption { 102 description = "Elasticsearch logging configuration."; 103 default = '' 104 logger.action.name = org.elasticsearch.action 105 logger.action.level = info 106 107 appender.console.type = Console 108 appender.console.name = console 109 appender.console.layout.type = PatternLayout 110 appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%m%n 111 112 rootLogger.level = info 113 rootLogger.appenderRef.console.ref = console 114 ''; 115 type = types.str; 116 }; 117 118 dataDir = mkOption { 119 type = types.path; 120 default = "/var/lib/elasticsearch"; 121 description = '' 122 Data directory for elasticsearch. 123 ''; 124 }; 125 126 extraCmdLineOptions = mkOption { 127 description = "Extra command line options for the elasticsearch launcher."; 128 default = [ ]; 129 type = types.listOf types.str; 130 }; 131 132 extraJavaOptions = mkOption { 133 description = "Extra command line options for Java."; 134 default = [ ]; 135 type = types.listOf types.str; 136 example = [ "-Djava.net.preferIPv4Stack=true" ]; 137 }; 138 139 plugins = mkOption { 140 description = "Extra elasticsearch plugins"; 141 default = [ ]; 142 type = types.listOf types.package; 143 example = lib.literalExpression "[ pkgs.elasticsearchPlugins.discovery-ec2 ]"; 144 }; 145 146 restartIfChanged = mkOption { 147 type = types.bool; 148 description = '' 149 Automatically restart the service on config change. 150 This can be set to false to defer restarts on a server or cluster. 151 Please consider the security implications of inadvertently running an older version, 152 and the possibility of unexpected behavior caused by inconsistent versions across a cluster when disabling this option. 153 ''; 154 default = true; 155 }; 156 157 }; 158 159 ###### implementation 160 161 config = mkIf cfg.enable { 162 systemd.services.elasticsearch = { 163 description = "Elasticsearch Daemon"; 164 wantedBy = [ "multi-user.target" ]; 165 after = [ "network.target" ]; 166 path = [ pkgs.inetutils ]; 167 inherit (cfg) restartIfChanged; 168 environment = { 169 ES_HOME = cfg.dataDir; 170 ES_JAVA_OPTS = toString cfg.extraJavaOptions; 171 ES_PATH_CONF = configDir; 172 }; 173 serviceConfig = { 174 ExecStart = "${cfg.package}/bin/elasticsearch ${toString cfg.extraCmdLineOptions}"; 175 User = "elasticsearch"; 176 PermissionsStartOnly = true; 177 LimitNOFILE = "1024000"; 178 Restart = "always"; 179 TimeoutStartSec = "infinity"; 180 }; 181 preStart = '' 182 ${optionalString (!config.boot.isContainer) '' 183 # Only set vm.max_map_count if lower than ES required minimum 184 # This avoids conflict if configured via boot.kernel.sysctl 185 if [ `${pkgs.procps}/bin/sysctl -n vm.max_map_count` -lt 262144 ]; then 186 ${pkgs.procps}/bin/sysctl -w vm.max_map_count=262144 187 fi 188 ''} 189 190 mkdir -m 0700 -p ${cfg.dataDir} 191 192 # Install plugins 193 ln -sfT ${esPlugins}/plugins ${cfg.dataDir}/plugins 194 ln -sfT ${cfg.package}/lib ${cfg.dataDir}/lib 195 ln -sfT ${cfg.package}/modules ${cfg.dataDir}/modules 196 197 # elasticsearch needs to create the elasticsearch.keystore in the config directory 198 # so this directory needs to be writable. 199 mkdir -m 0700 -p ${configDir} 200 201 # Note that we copy config files from the nix store instead of symbolically linking them 202 # because otherwise X-Pack Security will raise the following exception: 203 # java.security.AccessControlException: 204 # access denied ("java.io.FilePermission" "/var/lib/elasticsearch/config/elasticsearch.yml" "read") 205 206 cp ${elasticsearchYml} ${configDir}/elasticsearch.yml 207 # Make sure the logging configuration for old elasticsearch versions is removed: 208 rm -f "${configDir}/logging.yml" 209 cp ${loggingConfigFile} ${configDir}/${loggingConfigFilename} 210 mkdir -p ${configDir}/scripts 211 cp ${cfg.package}/config/jvm.options ${configDir}/jvm.options 212 # redirect jvm logs to the data directory 213 mkdir -m 0700 -p ${cfg.dataDir}/logs 214 ${pkgs.sd}/bin/sd 'logs/gc.log' '${cfg.dataDir}/logs/gc.log' ${configDir}/jvm.options \ 215 216 if [ "$(id -u)" = 0 ]; then chown -R elasticsearch:elasticsearch ${cfg.dataDir}; fi 217 ''; 218 postStart = '' 219 # Make sure elasticsearch is up and running before dependents 220 # are started 221 while ! ${pkgs.curl}/bin/curl -sS -f http://${cfg.listenAddress}:${toString cfg.port} 2>/dev/null; do 222 sleep 1 223 done 224 ''; 225 }; 226 227 environment.systemPackages = [ cfg.package ]; 228 229 users = { 230 groups.elasticsearch.gid = config.ids.gids.elasticsearch; 231 users.elasticsearch = { 232 uid = config.ids.uids.elasticsearch; 233 description = "Elasticsearch daemon user"; 234 home = cfg.dataDir; 235 group = "elasticsearch"; 236 }; 237 }; 238 }; 239}