2016-07-22 19:29:35 +02:00
|
|
|
|
{ config, lib, pkgs, ... }:
|
|
|
|
|
|
|
|
|
|
let
|
2021-04-29 08:39:35 +02:00
|
|
|
|
inherit (lib)
|
|
|
|
|
concatStringsSep
|
|
|
|
|
flip
|
2022-06-12 11:19:20 +02:00
|
|
|
|
literalMD
|
2021-10-03 18:06:03 +02:00
|
|
|
|
literalExpression
|
2021-04-29 08:39:35 +02:00
|
|
|
|
optionalAttrs
|
|
|
|
|
optionals
|
|
|
|
|
recursiveUpdate
|
2022-06-12 11:19:20 +02:00
|
|
|
|
mdDoc
|
2021-04-29 08:39:35 +02:00
|
|
|
|
mkEnableOption
|
|
|
|
|
mkIf
|
|
|
|
|
mkOption
|
|
|
|
|
types
|
|
|
|
|
versionAtLeast
|
|
|
|
|
;
|
|
|
|
|
|
2016-07-22 19:29:35 +02:00
|
|
|
|
cfg = config.services.cassandra;
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2017-11-07 14:11:56 +01:00
|
|
|
|
defaultUser = "cassandra";
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
|
|
|
|
cassandraConfig = flip recursiveUpdate cfg.extraConfig (
|
|
|
|
|
{
|
|
|
|
|
commitlog_sync = "batch";
|
|
|
|
|
commitlog_sync_batch_window_in_ms = 2;
|
|
|
|
|
start_native_transport = cfg.allowClients;
|
|
|
|
|
cluster_name = cfg.clusterName;
|
|
|
|
|
partitioner = "org.apache.cassandra.dht.Murmur3Partitioner";
|
|
|
|
|
endpoint_snitch = "SimpleSnitch";
|
|
|
|
|
data_file_directories = [ "${cfg.homeDir}/data" ];
|
|
|
|
|
commitlog_directory = "${cfg.homeDir}/commitlog";
|
|
|
|
|
saved_caches_directory = "${cfg.homeDir}/saved_caches";
|
2021-04-29 08:39:35 +02:00
|
|
|
|
} // optionalAttrs (cfg.seedAddresses != [ ]) {
|
2021-04-29 08:22:39 +02:00
|
|
|
|
seed_provider = [
|
|
|
|
|
{
|
|
|
|
|
class_name = "org.apache.cassandra.locator.SimpleSeedProvider";
|
|
|
|
|
parameters = [{ seeds = concatStringsSep "," cfg.seedAddresses; }];
|
|
|
|
|
}
|
|
|
|
|
];
|
2021-04-29 08:39:35 +02:00
|
|
|
|
} // optionalAttrs (versionAtLeast cfg.package.version "3") {
|
2021-04-29 08:22:39 +02:00
|
|
|
|
hints_directory = "${cfg.homeDir}/hints";
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
cassandraConfigWithAddresses = cassandraConfig // (
|
|
|
|
|
if cfg.listenAddress == null
|
|
|
|
|
then { listen_interface = cfg.listenInterface; }
|
|
|
|
|
else { listen_address = cfg.listenAddress; }
|
|
|
|
|
) // (
|
|
|
|
|
if cfg.rpcAddress == null
|
|
|
|
|
then { rpc_interface = cfg.rpcInterface; }
|
|
|
|
|
else { rpc_address = cfg.rpcAddress; }
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
cassandraEtc = pkgs.stdenv.mkDerivation {
|
|
|
|
|
name = "cassandra-etc";
|
|
|
|
|
|
|
|
|
|
cassandraYaml = builtins.toJSON cassandraConfigWithAddresses;
|
|
|
|
|
cassandraEnvPkg = "${cfg.package}/conf/cassandra-env.sh";
|
|
|
|
|
cassandraLogbackConfig = pkgs.writeText "logback.xml" cfg.logbackConfig;
|
|
|
|
|
|
|
|
|
|
passAsFile = [ "extraEnvSh" ];
|
|
|
|
|
inherit (cfg) extraEnvSh;
|
|
|
|
|
|
|
|
|
|
buildCommand = ''
|
|
|
|
|
mkdir -p "$out"
|
|
|
|
|
|
|
|
|
|
echo "$cassandraYaml" > "$out/cassandra.yaml"
|
|
|
|
|
ln -s "$cassandraLogbackConfig" "$out/logback.xml"
|
|
|
|
|
|
|
|
|
|
( cat "$cassandraEnvPkg"
|
|
|
|
|
echo "# lines from services.cassandra.extraEnvSh: "
|
|
|
|
|
cat "$extraEnvShPath"
|
|
|
|
|
) > "$out/cassandra-env.sh"
|
|
|
|
|
|
|
|
|
|
# Delete default JMX Port, otherwise we can't set it using env variable
|
|
|
|
|
sed -i '/JMX_PORT="7199"/d' "$out/cassandra-env.sh"
|
|
|
|
|
|
|
|
|
|
# Delete default password file
|
|
|
|
|
sed -i '/-Dcom.sun.management.jmxremote.password.file=\/etc\/cassandra\/jmxremote.password/d' "$out/cassandra-env.sh"
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
defaultJmxRolesFile =
|
|
|
|
|
builtins.foldl'
|
|
|
|
|
(left: right: left + right) ""
|
|
|
|
|
(map (role: "${role.username} ${role.password}") cfg.jmxRoles);
|
|
|
|
|
|
|
|
|
|
fullJvmOptions =
|
|
|
|
|
cfg.jvmOpts
|
2021-04-29 08:39:35 +02:00
|
|
|
|
++ optionals (cfg.jmxRoles != [ ]) [
|
2019-04-23 04:52:44 +02:00
|
|
|
|
"-Dcom.sun.management.jmxremote.authenticate=true"
|
2019-04-26 00:59:23 +02:00
|
|
|
|
"-Dcom.sun.management.jmxremote.password.file=${cfg.jmxRolesFile}"
|
2021-04-29 08:39:35 +02:00
|
|
|
|
] ++ optionals cfg.remoteJmx [
|
2019-04-23 04:52:44 +02:00
|
|
|
|
"-Djava.rmi.server.hostname=${cfg.rpcAddress}"
|
|
|
|
|
];
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
|
|
|
|
in
|
|
|
|
|
{
|
2016-07-22 19:29:35 +02:00
|
|
|
|
options.services.cassandra = {
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2017-11-07 14:11:56 +01:00
|
|
|
|
enable = mkEnableOption ''
|
|
|
|
|
Apache Cassandra – Scalable and highly available database.
|
|
|
|
|
'';
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2019-04-07 07:22:41 +02:00
|
|
|
|
clusterName = mkOption {
|
|
|
|
|
type = types.str;
|
2019-06-18 01:12:06 +02:00
|
|
|
|
default = "Test Cluster";
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
2019-04-07 07:22:41 +02:00
|
|
|
|
The name of the cluster.
|
|
|
|
|
This setting prevents nodes in one logical cluster from joining
|
|
|
|
|
another. All nodes in a cluster must have the same value.
|
|
|
|
|
'';
|
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2016-07-22 19:29:35 +02:00
|
|
|
|
user = mkOption {
|
2017-11-07 14:11:56 +01:00
|
|
|
|
type = types.str;
|
|
|
|
|
default = defaultUser;
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc "Run Apache Cassandra under this user.";
|
2016-07-22 19:29:35 +02:00
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2016-07-22 19:29:35 +02:00
|
|
|
|
group = mkOption {
|
|
|
|
|
type = types.str;
|
2017-11-07 14:11:56 +01:00
|
|
|
|
default = defaultUser;
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc "Run Apache Cassandra under this group.";
|
2016-07-22 19:29:35 +02:00
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2017-11-07 14:11:56 +01:00
|
|
|
|
homeDir = mkOption {
|
2016-07-22 19:29:35 +02:00
|
|
|
|
type = types.path;
|
2017-11-07 14:11:56 +01:00
|
|
|
|
default = "/var/lib/cassandra";
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
2017-11-07 14:11:56 +01:00
|
|
|
|
Home directory for Apache Cassandra.
|
|
|
|
|
'';
|
2016-07-22 19:29:35 +02:00
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2017-11-07 14:11:56 +01:00
|
|
|
|
package = mkOption {
|
|
|
|
|
type = types.package;
|
|
|
|
|
default = pkgs.cassandra;
|
2021-10-03 18:06:03 +02:00
|
|
|
|
defaultText = literalExpression "pkgs.cassandra";
|
|
|
|
|
example = literalExpression "pkgs.cassandra_3_11";
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
2017-11-07 14:11:56 +01:00
|
|
|
|
The Apache Cassandra package to use.
|
|
|
|
|
'';
|
2016-07-22 19:29:35 +02:00
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2017-11-07 14:11:56 +01:00
|
|
|
|
jvmOpts = mkOption {
|
2016-07-22 19:29:35 +02:00
|
|
|
|
type = types.listOf types.str;
|
2021-04-29 08:22:39 +02:00
|
|
|
|
default = [ ];
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
|
|
|
|
Populate the `JVM_OPT` environment variable.
|
2017-11-07 14:11:56 +01:00
|
|
|
|
'';
|
2016-07-22 19:29:35 +02:00
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2016-07-22 19:29:35 +02:00
|
|
|
|
listenAddress = mkOption {
|
2017-11-07 14:11:56 +01:00
|
|
|
|
type = types.nullOr types.str;
|
|
|
|
|
default = "127.0.0.1";
|
2021-04-29 08:43:58 +02:00
|
|
|
|
example = null;
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
2017-11-07 14:11:56 +01:00
|
|
|
|
Address or interface to bind to and tell other Cassandra nodes
|
|
|
|
|
to connect to. You _must_ change this if you want multiple
|
|
|
|
|
nodes to be able to communicate!
|
|
|
|
|
|
2022-06-12 11:19:20 +02:00
|
|
|
|
Set {option}`listenAddress` OR {option}`listenInterface`, not both.
|
2017-11-07 14:11:56 +01:00
|
|
|
|
|
|
|
|
|
Leaving it blank leaves it up to
|
2022-06-12 11:19:20 +02:00
|
|
|
|
`InetAddress.getLocalHost()`. This will always do the "Right
|
|
|
|
|
Thing" _if_ the node is properly configured (hostname, name
|
2017-11-07 14:11:56 +01:00
|
|
|
|
resolution, etc), and the Right Thing is to use the address
|
|
|
|
|
associated with the hostname (it might not be).
|
|
|
|
|
|
2022-06-12 11:19:20 +02:00
|
|
|
|
Setting {option}`listenAddress` to `0.0.0.0` is always wrong.
|
2016-07-22 19:29:35 +02:00
|
|
|
|
'';
|
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2017-11-07 14:11:56 +01:00
|
|
|
|
listenInterface = mkOption {
|
|
|
|
|
type = types.nullOr types.str;
|
|
|
|
|
default = null;
|
|
|
|
|
example = "eth1";
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
|
|
|
|
Set `listenAddress` OR `listenInterface`, not both. Interfaces
|
2017-11-07 14:11:56 +01:00
|
|
|
|
must correspond to a single address, IP aliasing is not
|
|
|
|
|
supported.
|
2016-07-22 19:29:35 +02:00
|
|
|
|
'';
|
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2017-11-07 14:11:56 +01:00
|
|
|
|
rpcAddress = mkOption {
|
|
|
|
|
type = types.nullOr types.str;
|
|
|
|
|
default = "127.0.0.1";
|
2021-04-29 08:43:58 +02:00
|
|
|
|
example = null;
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
2017-11-07 14:11:56 +01:00
|
|
|
|
The address or interface to bind the native transport server to.
|
|
|
|
|
|
2022-06-12 11:19:20 +02:00
|
|
|
|
Set {option}`rpcAddress` OR {option}`rpcInterface`, not both.
|
2017-11-07 14:11:56 +01:00
|
|
|
|
|
2022-06-12 11:19:20 +02:00
|
|
|
|
Leaving {option}`rpcAddress` blank has the same effect as on
|
|
|
|
|
{option}`listenAddress` (i.e. it will be based on the configured hostname
|
2017-11-07 14:11:56 +01:00
|
|
|
|
of the node).
|
|
|
|
|
|
2022-06-12 11:19:20 +02:00
|
|
|
|
Note that unlike {option}`listenAddress`, you can specify `"0.0.0.0"`, but you
|
|
|
|
|
must also set `extraConfig.broadcast_rpc_address` to a value other
|
|
|
|
|
than `"0.0.0.0"`.
|
2017-11-07 14:11:56 +01:00
|
|
|
|
|
|
|
|
|
For security reasons, you should not expose this port to the
|
|
|
|
|
internet. Firewall it if needed.
|
2016-07-22 19:29:35 +02:00
|
|
|
|
'';
|
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2017-11-07 14:11:56 +01:00
|
|
|
|
rpcInterface = mkOption {
|
|
|
|
|
type = types.nullOr types.str;
|
2016-07-22 19:29:35 +02:00
|
|
|
|
default = null;
|
2017-11-07 14:11:56 +01:00
|
|
|
|
example = "eth1";
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
|
|
|
|
Set {option}`rpcAddress` OR {option}`rpcInterface`, not both. Interfaces must
|
2017-11-07 14:11:56 +01:00
|
|
|
|
correspond to a single address, IP aliasing is not supported.
|
2016-07-22 19:29:35 +02:00
|
|
|
|
'';
|
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2018-12-05 14:56:23 +01:00
|
|
|
|
logbackConfig = mkOption {
|
|
|
|
|
type = types.lines;
|
|
|
|
|
default = ''
|
|
|
|
|
<configuration scan="false">
|
|
|
|
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
|
|
|
|
<encoder>
|
|
|
|
|
<pattern>%-5level %date{HH:mm:ss,SSS} %msg%n</pattern>
|
|
|
|
|
</encoder>
|
|
|
|
|
</appender>
|
2016-07-22 19:29:35 +02:00
|
|
|
|
|
2018-12-05 14:56:23 +01:00
|
|
|
|
<root level="INFO">
|
|
|
|
|
<appender-ref ref="STDOUT" />
|
|
|
|
|
</root>
|
|
|
|
|
|
|
|
|
|
<logger name="com.thinkaurelius.thrift" level="ERROR"/>
|
|
|
|
|
</configuration>
|
|
|
|
|
'';
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
2018-12-05 14:56:23 +01:00
|
|
|
|
XML logback configuration for cassandra
|
|
|
|
|
'';
|
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2019-04-07 05:02:51 +02:00
|
|
|
|
seedAddresses = mkOption {
|
|
|
|
|
type = types.listOf types.str;
|
|
|
|
|
default = [ "127.0.0.1" ];
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
2019-04-07 05:02:51 +02:00
|
|
|
|
The addresses of hosts designated as contact points in the cluster. A
|
|
|
|
|
joining node contacts one of the nodes in the seeds list to learn the
|
|
|
|
|
topology of the ring.
|
2022-06-12 11:19:20 +02:00
|
|
|
|
Set to `[ "127.0.0.1" ]` for a single node cluster.
|
2019-04-07 05:02:51 +02:00
|
|
|
|
'';
|
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2019-04-07 05:02:32 +02:00
|
|
|
|
allowClients = mkOption {
|
|
|
|
|
type = types.bool;
|
|
|
|
|
default = true;
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
2019-04-07 05:02:32 +02:00
|
|
|
|
Enables or disables the native transport server (CQL binary protocol).
|
2022-06-12 11:19:20 +02:00
|
|
|
|
This server uses the same address as the {option}`rpcAddress`,
|
|
|
|
|
but the port it uses is not `rpc_port` but
|
|
|
|
|
`native_transport_port`. See the official Cassandra
|
2019-04-07 05:02:32 +02:00
|
|
|
|
docs for more information on these variables and set them using
|
2022-06-12 11:19:20 +02:00
|
|
|
|
{option}`extraConfig`.
|
2019-04-07 05:02:32 +02:00
|
|
|
|
'';
|
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2017-11-07 14:11:56 +01:00
|
|
|
|
extraConfig = mkOption {
|
|
|
|
|
type = types.attrs;
|
2021-04-29 08:22:39 +02:00
|
|
|
|
default = { };
|
2017-11-07 14:11:56 +01:00
|
|
|
|
example =
|
2021-04-29 08:22:39 +02:00
|
|
|
|
{
|
|
|
|
|
commitlog_sync_batch_window_in_ms = 3;
|
2017-11-07 14:11:56 +01:00
|
|
|
|
};
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
|
|
|
|
Extra options to be merged into {file}`cassandra.yaml` as nix attribute set.
|
2017-11-07 14:11:56 +01:00
|
|
|
|
'';
|
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2020-09-16 17:19:39 +02:00
|
|
|
|
extraEnvSh = mkOption {
|
|
|
|
|
type = types.lines;
|
|
|
|
|
default = "";
|
2021-10-03 18:06:03 +02:00
|
|
|
|
example = literalExpression ''"CLASSPATH=$CLASSPATH:''${extraJar}"'';
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
|
|
|
|
Extra shell lines to be appended onto {file}`cassandra-env.sh`.
|
2020-09-16 17:19:39 +02:00
|
|
|
|
'';
|
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2017-11-07 14:11:56 +01:00
|
|
|
|
fullRepairInterval = mkOption {
|
|
|
|
|
type = types.nullOr types.str;
|
|
|
|
|
default = "3w";
|
2021-04-29 08:43:58 +02:00
|
|
|
|
example = null;
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
2021-04-29 08:22:39 +02:00
|
|
|
|
Set the interval how often full repairs are run, i.e.
|
2022-06-12 11:19:20 +02:00
|
|
|
|
{command}`nodetool repair --full` is executed. See
|
|
|
|
|
<https://cassandra.apache.org/doc/latest/operating/repair.html>
|
2021-04-29 08:22:39 +02:00
|
|
|
|
for more information.
|
2016-07-22 19:29:35 +02:00
|
|
|
|
|
2022-06-12 11:19:20 +02:00
|
|
|
|
Set to `null` to disable full repairs.
|
2021-04-29 08:22:39 +02:00
|
|
|
|
'';
|
2016-07-22 19:29:35 +02:00
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2017-11-07 14:11:56 +01:00
|
|
|
|
fullRepairOptions = mkOption {
|
|
|
|
|
type = types.listOf types.str;
|
2021-04-29 08:22:39 +02:00
|
|
|
|
default = [ ];
|
2017-11-07 14:11:56 +01:00
|
|
|
|
example = [ "--partitioner-range" ];
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
2021-04-29 08:22:39 +02:00
|
|
|
|
Options passed through to the full repair command.
|
|
|
|
|
'';
|
2016-07-22 19:29:35 +02:00
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2017-11-07 14:11:56 +01:00
|
|
|
|
incrementalRepairInterval = mkOption {
|
|
|
|
|
type = types.nullOr types.str;
|
|
|
|
|
default = "3d";
|
2021-04-29 08:43:58 +02:00
|
|
|
|
example = null;
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
2021-04-29 08:22:39 +02:00
|
|
|
|
Set the interval how often incremental repairs are run, i.e.
|
2022-06-12 11:19:20 +02:00
|
|
|
|
{command}`nodetool repair` is executed. See
|
|
|
|
|
<https://cassandra.apache.org/doc/latest/operating/repair.html>
|
2021-04-29 08:22:39 +02:00
|
|
|
|
for more information.
|
2017-11-07 14:11:56 +01:00
|
|
|
|
|
2022-06-12 11:19:20 +02:00
|
|
|
|
Set to `null` to disable incremental repairs.
|
2021-04-29 08:22:39 +02:00
|
|
|
|
'';
|
2016-07-22 19:29:35 +02:00
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2017-11-07 14:11:56 +01:00
|
|
|
|
incrementalRepairOptions = mkOption {
|
2019-08-08 22:48:27 +02:00
|
|
|
|
type = types.listOf types.str;
|
2021-04-29 08:22:39 +02:00
|
|
|
|
default = [ ];
|
2017-11-07 14:11:56 +01:00
|
|
|
|
example = [ "--partitioner-range" ];
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
2021-04-29 08:22:39 +02:00
|
|
|
|
Options passed through to the incremental repair command.
|
|
|
|
|
'';
|
2016-07-22 19:29:35 +02:00
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2019-04-07 06:30:26 +02:00
|
|
|
|
maxHeapSize = mkOption {
|
2019-08-08 22:48:27 +02:00
|
|
|
|
type = types.nullOr types.str;
|
2019-04-07 06:30:26 +02:00
|
|
|
|
default = null;
|
|
|
|
|
example = "4G";
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
|
|
|
|
Must be left blank or set together with {option}`heapNewSize`.
|
2019-04-07 06:30:26 +02:00
|
|
|
|
If left blank a sensible value for the available amount of RAM and CPU
|
|
|
|
|
cores is calculated.
|
|
|
|
|
|
|
|
|
|
Override to set the amount of memory to allocate to the JVM at
|
|
|
|
|
start-up. For production use you may wish to adjust this for your
|
2022-06-12 11:19:20 +02:00
|
|
|
|
environment. `MAX_HEAP_SIZE` is the total amount of memory dedicated
|
|
|
|
|
to the Java heap. `HEAP_NEWSIZE` refers to the size of the young
|
2019-04-07 06:30:26 +02:00
|
|
|
|
generation.
|
|
|
|
|
|
|
|
|
|
The main trade-off for the young generation is that the larger it
|
|
|
|
|
is, the longer GC pause times will be. The shorter it is, the more
|
|
|
|
|
expensive GC will be (usually).
|
|
|
|
|
'';
|
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2019-04-07 06:30:26 +02:00
|
|
|
|
heapNewSize = mkOption {
|
2019-08-08 22:48:27 +02:00
|
|
|
|
type = types.nullOr types.str;
|
2019-04-07 06:30:26 +02:00
|
|
|
|
default = null;
|
|
|
|
|
example = "800M";
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
|
|
|
|
Must be left blank or set together with {option}`heapNewSize`.
|
2019-04-07 06:30:26 +02:00
|
|
|
|
If left blank a sensible value for the available amount of RAM and CPU
|
|
|
|
|
cores is calculated.
|
|
|
|
|
|
|
|
|
|
Override to set the amount of memory to allocate to the JVM at
|
|
|
|
|
start-up. For production use you may wish to adjust this for your
|
2022-06-12 11:19:20 +02:00
|
|
|
|
environment. `HEAP_NEWSIZE` refers to the size of the young
|
2019-04-07 06:30:26 +02:00
|
|
|
|
generation.
|
|
|
|
|
|
|
|
|
|
The main trade-off for the young generation is that the larger it
|
|
|
|
|
is, the longer GC pause times will be. The shorter it is, the more
|
|
|
|
|
expensive GC will be (usually).
|
|
|
|
|
|
2022-06-12 11:19:20 +02:00
|
|
|
|
The example `HEAP_NEWSIZE` assumes a modern 8-core+ machine for decent pause
|
2019-04-07 06:30:26 +02:00
|
|
|
|
times. If in doubt, and if you do not particularly want to tweak, go with
|
|
|
|
|
100 MB per physical CPU core.
|
|
|
|
|
'';
|
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2019-04-07 06:30:26 +02:00
|
|
|
|
mallocArenaMax = mkOption {
|
|
|
|
|
type = types.nullOr types.int;
|
|
|
|
|
default = null;
|
|
|
|
|
example = 4;
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
2019-04-07 06:30:26 +02:00
|
|
|
|
Set this to control the amount of arenas per-thread in glibc.
|
|
|
|
|
'';
|
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2019-04-07 06:30:26 +02:00
|
|
|
|
remoteJmx = mkOption {
|
|
|
|
|
type = types.bool;
|
|
|
|
|
default = false;
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
2019-04-07 06:30:26 +02:00
|
|
|
|
Cassandra ships with JMX accessible *only* from localhost.
|
|
|
|
|
To enable remote JMX connections set to true.
|
|
|
|
|
|
|
|
|
|
Be sure to also enable authentication and/or TLS.
|
2022-06-12 11:19:20 +02:00
|
|
|
|
See: <https://wiki.apache.org/cassandra/JmxSecurity>
|
2019-04-07 06:30:26 +02:00
|
|
|
|
'';
|
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2019-04-07 06:30:26 +02:00
|
|
|
|
jmxPort = mkOption {
|
|
|
|
|
type = types.int;
|
|
|
|
|
default = 7199;
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
2019-04-07 06:30:26 +02:00
|
|
|
|
Specifies the default port over which Cassandra will be available for
|
|
|
|
|
JMX connections.
|
|
|
|
|
For security reasons, you should not expose this port to the internet.
|
|
|
|
|
Firewall it if needed.
|
|
|
|
|
'';
|
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2019-04-23 04:52:44 +02:00
|
|
|
|
jmxRoles = mkOption {
|
2021-04-29 08:22:39 +02:00
|
|
|
|
default = [ ];
|
2022-06-12 11:19:20 +02:00
|
|
|
|
description = mdDoc ''
|
|
|
|
|
Roles that are allowed to access the JMX (e.g. {command}`nodetool`)
|
|
|
|
|
BEWARE: The passwords will be stored world readable in the nix store.
|
2019-04-26 01:13:09 +02:00
|
|
|
|
It's recommended to use your own protected file using
|
2022-06-12 11:19:20 +02:00
|
|
|
|
{option}`jmxRolesFile`
|
2019-04-26 00:59:23 +02:00
|
|
|
|
|
|
|
|
|
Doesn't work in versions older than 3.11 because they don't like that
|
|
|
|
|
it's world readable.
|
2019-04-23 04:52:44 +02:00
|
|
|
|
'';
|
|
|
|
|
type = types.listOf (types.submodule {
|
|
|
|
|
options = {
|
|
|
|
|
username = mkOption {
|
2019-08-08 22:48:27 +02:00
|
|
|
|
type = types.str;
|
2022-07-28 23:19:15 +02:00
|
|
|
|
description = lib.mdDoc "Username for JMX";
|
2019-04-23 04:52:44 +02:00
|
|
|
|
};
|
|
|
|
|
password = mkOption {
|
2019-08-08 22:48:27 +02:00
|
|
|
|
type = types.str;
|
2022-07-28 23:19:15 +02:00
|
|
|
|
description = lib.mdDoc "Password for JMX";
|
2019-04-23 04:52:44 +02:00
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
|
2019-04-26 00:59:23 +02:00
|
|
|
|
jmxRolesFile = mkOption {
|
|
|
|
|
type = types.nullOr types.path;
|
2021-04-29 08:22:39 +02:00
|
|
|
|
default =
|
2021-04-29 08:39:35 +02:00
|
|
|
|
if versionAtLeast cfg.package.version "3.11"
|
2021-04-29 08:22:39 +02:00
|
|
|
|
then pkgs.writeText "jmx-roles-file" defaultJmxRolesFile
|
|
|
|
|
else null;
|
2022-06-12 11:19:20 +02:00
|
|
|
|
defaultText = literalMD ''generated configuration file if version is at least 3.11, otherwise `null`'';
|
2019-04-26 00:59:23 +02:00
|
|
|
|
example = "/var/lib/cassandra/jmx.password";
|
2022-07-28 23:19:15 +02:00
|
|
|
|
description = lib.mdDoc ''
|
2019-04-26 00:59:23 +02:00
|
|
|
|
Specify your own jmx roles file.
|
|
|
|
|
|
|
|
|
|
Make sure the permissions forbid "others" from reading the file if
|
|
|
|
|
you're using Cassandra below version 3.11.
|
|
|
|
|
'';
|
|
|
|
|
};
|
2017-11-07 14:11:56 +01:00
|
|
|
|
};
|
2016-07-22 19:29:35 +02:00
|
|
|
|
|
2017-11-07 14:11:56 +01:00
|
|
|
|
config = mkIf cfg.enable {
|
2021-04-29 08:22:39 +02:00
|
|
|
|
assertions = [
|
|
|
|
|
{
|
|
|
|
|
assertion = (cfg.listenAddress == null) != (cfg.listenInterface == null);
|
|
|
|
|
message = "You have to set either listenAddress or listenInterface";
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
assertion = (cfg.rpcAddress == null) != (cfg.rpcInterface == null);
|
|
|
|
|
message = "You have to set either rpcAddress or rpcInterface";
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
assertion = (cfg.maxHeapSize == null) == (cfg.heapNewSize == null);
|
|
|
|
|
message = "If you set either of maxHeapSize or heapNewSize you have to set both";
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
assertion = cfg.remoteJmx -> cfg.jmxRolesFile != null;
|
|
|
|
|
message = ''
|
|
|
|
|
If you want JMX available remotely you need to set a password using
|
|
|
|
|
<literal>jmxRoles</literal> or <literal>jmxRolesFile</literal> if
|
|
|
|
|
using Cassandra older than v3.11.
|
|
|
|
|
'';
|
|
|
|
|
}
|
|
|
|
|
];
|
2017-11-07 14:11:56 +01:00
|
|
|
|
users = mkIf (cfg.user == defaultUser) {
|
2021-04-29 08:51:40 +02:00
|
|
|
|
users.${defaultUser} = {
|
2021-04-29 08:22:39 +02:00
|
|
|
|
group = cfg.group;
|
|
|
|
|
home = cfg.homeDir;
|
|
|
|
|
createHome = true;
|
|
|
|
|
uid = config.ids.uids.cassandra;
|
|
|
|
|
description = "Cassandra service user";
|
|
|
|
|
};
|
2021-04-29 08:51:40 +02:00
|
|
|
|
groups.${defaultUser}.gid = config.ids.gids.cassandra;
|
2016-07-22 19:29:35 +02:00
|
|
|
|
};
|
|
|
|
|
|
2021-04-29 08:22:39 +02:00
|
|
|
|
systemd.services.cassandra = {
|
|
|
|
|
description = "Apache Cassandra service";
|
|
|
|
|
after = [ "network.target" ];
|
|
|
|
|
environment = {
|
|
|
|
|
CASSANDRA_CONF = "${cassandraEtc}";
|
|
|
|
|
JVM_OPTS = builtins.concatStringsSep " " fullJvmOptions;
|
|
|
|
|
MAX_HEAP_SIZE = toString cfg.maxHeapSize;
|
|
|
|
|
HEAP_NEWSIZE = toString cfg.heapNewSize;
|
|
|
|
|
MALLOC_ARENA_MAX = toString cfg.mallocArenaMax;
|
|
|
|
|
LOCAL_JMX = if cfg.remoteJmx then "no" else "yes";
|
|
|
|
|
JMX_PORT = toString cfg.jmxPort;
|
|
|
|
|
};
|
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
|
serviceConfig = {
|
|
|
|
|
User = cfg.user;
|
|
|
|
|
Group = cfg.group;
|
|
|
|
|
ExecStart = "${cfg.package}/bin/cassandra -f";
|
|
|
|
|
SuccessExitStatus = 143;
|
2017-11-07 14:11:56 +01:00
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
};
|
2016-07-22 19:29:35 +02:00
|
|
|
|
|
2021-04-29 08:22:39 +02:00
|
|
|
|
systemd.services.cassandra-full-repair = {
|
|
|
|
|
description = "Perform a full repair on this Cassandra node";
|
|
|
|
|
after = [ "cassandra.service" ];
|
|
|
|
|
requires = [ "cassandra.service" ];
|
|
|
|
|
serviceConfig = {
|
|
|
|
|
User = cfg.user;
|
|
|
|
|
Group = cfg.group;
|
|
|
|
|
ExecStart =
|
2021-04-29 08:39:35 +02:00
|
|
|
|
concatStringsSep " "
|
2021-04-29 08:22:39 +02:00
|
|
|
|
([
|
|
|
|
|
"${cfg.package}/bin/nodetool"
|
|
|
|
|
"repair"
|
|
|
|
|
"--full"
|
|
|
|
|
] ++ cfg.fullRepairOptions);
|
2017-11-07 14:11:56 +01:00
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
};
|
|
|
|
|
|
2017-11-07 14:11:56 +01:00
|
|
|
|
systemd.timers.cassandra-full-repair =
|
2019-04-24 05:48:22 +02:00
|
|
|
|
mkIf (cfg.fullRepairInterval != null) {
|
2017-11-07 14:11:56 +01:00
|
|
|
|
description = "Schedule full repairs on Cassandra";
|
|
|
|
|
wantedBy = [ "timers.target" ];
|
2021-04-29 08:22:39 +02:00
|
|
|
|
timerConfig = {
|
|
|
|
|
OnBootSec = cfg.fullRepairInterval;
|
|
|
|
|
OnUnitActiveSec = cfg.fullRepairInterval;
|
|
|
|
|
Persistent = true;
|
|
|
|
|
};
|
2016-07-22 19:29:35 +02:00
|
|
|
|
};
|
|
|
|
|
|
2021-04-29 08:22:39 +02:00
|
|
|
|
systemd.services.cassandra-incremental-repair = {
|
|
|
|
|
description = "Perform an incremental repair on this cassandra node.";
|
|
|
|
|
after = [ "cassandra.service" ];
|
|
|
|
|
requires = [ "cassandra.service" ];
|
|
|
|
|
serviceConfig = {
|
|
|
|
|
User = cfg.user;
|
|
|
|
|
Group = cfg.group;
|
|
|
|
|
ExecStart =
|
2021-04-29 08:39:35 +02:00
|
|
|
|
concatStringsSep " "
|
2021-04-29 08:22:39 +02:00
|
|
|
|
([
|
|
|
|
|
"${cfg.package}/bin/nodetool"
|
|
|
|
|
"repair"
|
|
|
|
|
] ++ cfg.incrementalRepairOptions);
|
2017-11-07 14:11:56 +01:00
|
|
|
|
};
|
2021-04-29 08:22:39 +02:00
|
|
|
|
};
|
|
|
|
|
|
2017-11-07 14:11:56 +01:00
|
|
|
|
systemd.timers.cassandra-incremental-repair =
|
2019-04-24 05:48:22 +02:00
|
|
|
|
mkIf (cfg.incrementalRepairInterval != null) {
|
2017-11-07 14:11:56 +01:00
|
|
|
|
description = "Schedule incremental repairs on Cassandra";
|
|
|
|
|
wantedBy = [ "timers.target" ];
|
2021-04-29 08:22:39 +02:00
|
|
|
|
timerConfig = {
|
|
|
|
|
OnBootSec = cfg.incrementalRepairInterval;
|
|
|
|
|
OnUnitActiveSec = cfg.incrementalRepairInterval;
|
|
|
|
|
Persistent = true;
|
|
|
|
|
};
|
2016-07-22 19:29:35 +02:00
|
|
|
|
};
|
|
|
|
|
};
|
2021-04-29 08:46:51 +02:00
|
|
|
|
|
|
|
|
|
meta.maintainers = with lib.maintainers; [ roberth ];
|
2016-07-22 19:29:35 +02:00
|
|
|
|
}
|