diff options
Diffstat (limited to 'nixos/modules/services/amqp')
-rw-r--r-- | nixos/modules/services/amqp/activemq/ActiveMQBroker.java | 19 | ||||
-rw-r--r-- | nixos/modules/services/amqp/activemq/default.nix | 135 | ||||
-rw-r--r-- | nixos/modules/services/amqp/rabbitmq.nix | 228 |
3 files changed, 382 insertions, 0 deletions
diff --git a/nixos/modules/services/amqp/activemq/ActiveMQBroker.java b/nixos/modules/services/amqp/activemq/ActiveMQBroker.java new file mode 100644 index 00000000000..c0f5d16ea11 --- /dev/null +++ b/nixos/modules/services/amqp/activemq/ActiveMQBroker.java @@ -0,0 +1,19 @@ +import org.apache.activemq.broker.BrokerService; +import org.apache.activemq.broker.BrokerFactory; +import java.net.URI; + +public class ActiveMQBroker { + + public static void main(String[] args) throws Throwable { + URI uri = new URI((args.length > 0) ? args[0] : "xbean:activemq.xml"); + BrokerService broker = BrokerFactory.createBroker(uri); + broker.start(); + if (broker.waitUntilStarted()) { + broker.waitUntilStopped(); + } else { + System.out.println("Failed starting broker"); + System.exit(-1); + }; + } + +} diff --git a/nixos/modules/services/amqp/activemq/default.nix b/nixos/modules/services/amqp/activemq/default.nix new file mode 100644 index 00000000000..47669b05aa9 --- /dev/null +++ b/nixos/modules/services/amqp/activemq/default.nix @@ -0,0 +1,135 @@ +{ config, lib, pkgs, ... }: + +with pkgs; +with lib; + +let + + cfg = config.services.activemq; + + activemqBroker = stdenv.mkDerivation { + name = "activemq-broker"; + phases = [ "installPhase" ]; + buildInputs = [ jdk ]; + installPhase = '' + mkdir -p $out/lib + source ${activemq}/lib/classpath.env + export CLASSPATH + ln -s "${./ActiveMQBroker.java}" ActiveMQBroker.java + javac -d $out/lib ActiveMQBroker.java + ''; + }; + +in { + + options = { + services.activemq = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Enable the Apache ActiveMQ message broker service. + ''; + }; + configurationDir = mkOption { + default = "${activemq}/conf"; + defaultText = literalExpression ''"''${pkgs.activemq}/conf"''; + type = types.str; + description = '' + The base directory for ActiveMQ's configuration. + By default, this directory is searched for a file named activemq.xml, + which should contain the configuration for the broker service. + ''; + }; + configurationURI = mkOption { + type = types.str; + default = "xbean:activemq.xml"; + description = '' + The URI that is passed along to the BrokerFactory to + set up the configuration of the ActiveMQ broker service. + You should not need to change this. For custom configuration, + set the <literal>configurationDir</literal> instead, and create + an activemq.xml configuration file in it. + ''; + }; + baseDir = mkOption { + type = types.str; + default = "/var/activemq"; + description = '' + The base directory where ActiveMQ stores its persistent data and logs. + This will be overridden if you set "activemq.base" and "activemq.data" + in the <literal>javaProperties</literal> option. You can also override + this in activemq.xml. + ''; + }; + javaProperties = mkOption { + type = types.attrs; + default = { }; + example = literalExpression '' + { + "java.net.preferIPv4Stack" = "true"; + } + ''; + apply = attrs: { + "activemq.base" = "${cfg.baseDir}"; + "activemq.data" = "${cfg.baseDir}/data"; + "activemq.conf" = "${cfg.configurationDir}"; + "activemq.home" = "${activemq}"; + } // attrs; + description = '' + Specifies Java properties that are sent to the ActiveMQ + broker service with the "-D" option. You can set properties + here to change the behaviour and configuration of the broker. + All essential properties that are not set here are automatically + given reasonable defaults. + ''; + }; + extraJavaOptions = mkOption { + type = types.separatedString " "; + default = ""; + example = "-Xmx2G -Xms2G -XX:MaxPermSize=512M"; + description = '' + Add extra options here that you want to be sent to the + Java runtime when the broker service is started. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + users.users.activemq = { + description = "ActiveMQ server user"; + group = "activemq"; + uid = config.ids.uids.activemq; + }; + + users.groups.activemq.gid = config.ids.gids.activemq; + + systemd.services.activemq_init = { + wantedBy = [ "activemq.service" ]; + partOf = [ "activemq.service" ]; + before = [ "activemq.service" ]; + serviceConfig.Type = "oneshot"; + script = '' + mkdir -p "${cfg.javaProperties."activemq.data"}" + chown -R activemq "${cfg.javaProperties."activemq.data"}" + ''; + }; + + systemd.services.activemq = { + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + path = [ jre ]; + serviceConfig.User = "activemq"; + script = '' + source ${activemq}/lib/classpath.env + export CLASSPATH=${activemqBroker}/lib:${cfg.configurationDir}:$CLASSPATH + exec java \ + ${concatStringsSep " \\\n" (mapAttrsToList (name: value: "-D${name}=${value}") cfg.javaProperties)} \ + ${cfg.extraJavaOptions} ActiveMQBroker "${cfg.configurationURI}" + ''; + }; + + }; + +} diff --git a/nixos/modules/services/amqp/rabbitmq.nix b/nixos/modules/services/amqp/rabbitmq.nix new file mode 100644 index 00000000000..3255942fe43 --- /dev/null +++ b/nixos/modules/services/amqp/rabbitmq.nix @@ -0,0 +1,228 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.rabbitmq; + + inherit (builtins) concatStringsSep; + + config_file_content = lib.generators.toKeyValue { } cfg.configItems; + config_file = pkgs.writeText "rabbitmq.conf" config_file_content; + + advanced_config_file = pkgs.writeText "advanced.config" cfg.config; + +in +{ + ###### interface + options = { + services.rabbitmq = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable the RabbitMQ server, an Advanced Message + Queuing Protocol (AMQP) broker. + ''; + }; + + package = mkOption { + default = pkgs.rabbitmq-server; + type = types.package; + defaultText = literalExpression "pkgs.rabbitmq-server"; + description = '' + Which rabbitmq package to use. + ''; + }; + + listenAddress = mkOption { + default = "127.0.0.1"; + example = ""; + description = '' + IP address on which RabbitMQ will listen for AMQP + connections. Set to the empty string to listen on all + interfaces. Note that RabbitMQ creates a user named + <literal>guest</literal> with password + <literal>guest</literal> by default, so you should delete + this user if you intend to allow external access. + + Together with 'port' setting it's mostly an alias for + configItems."listeners.tcp.1" and it's left for backwards + compatibility with previous version of this module. + ''; + type = types.str; + }; + + port = mkOption { + default = 5672; + description = '' + Port on which RabbitMQ will listen for AMQP connections. + ''; + type = types.port; + }; + + dataDir = mkOption { + type = types.path; + default = "/var/lib/rabbitmq"; + description = '' + Data directory for rabbitmq. + ''; + }; + + cookie = mkOption { + default = ""; + type = types.str; + description = '' + Erlang cookie is a string of arbitrary length which must + be the same for several nodes to be allowed to communicate. + Leave empty to generate automatically. + ''; + }; + + configItems = mkOption { + default = { }; + type = types.attrsOf types.str; + example = literalExpression '' + { + "auth_backends.1.authn" = "rabbit_auth_backend_ldap"; + "auth_backends.1.authz" = "rabbit_auth_backend_internal"; + } + ''; + description = '' + Configuration options in RabbitMQ's new config file format, + which is a simple key-value format that can not express nested + data structures. This is known as the <literal>rabbitmq.conf</literal> file, + although outside NixOS that filename may have Erlang syntax, particularly + prior to RabbitMQ 3.7.0. + + If you do need to express nested data structures, you can use + <literal>config</literal> option. Configuration from <literal>config</literal> + will be merged into these options by RabbitMQ at runtime to + form the final configuration. + + See https://www.rabbitmq.com/configure.html#config-items + For the distinct formats, see https://www.rabbitmq.com/configure.html#config-file-formats + ''; + }; + + config = mkOption { + default = ""; + type = types.str; + description = '' + Verbatim advanced configuration file contents using the Erlang syntax. + This is also known as the <literal>advanced.config</literal> file or the old config format. + + <literal>configItems</literal> is preferred whenever possible. However, nested + data structures can only be expressed properly using the <literal>config</literal> option. + + The contents of this option will be merged into the <literal>configItems</literal> + by RabbitMQ at runtime to form the final configuration. + + See the second table on https://www.rabbitmq.com/configure.html#config-items + For the distinct formats, see https://www.rabbitmq.com/configure.html#config-file-formats + ''; + }; + + plugins = mkOption { + default = [ ]; + type = types.listOf types.str; + description = "The names of plugins to enable"; + }; + + pluginDirs = mkOption { + default = [ ]; + type = types.listOf types.path; + description = "The list of directories containing external plugins"; + }; + + managementPlugin = { + enable = mkEnableOption "the management plugin"; + port = mkOption { + default = 15672; + type = types.port; + description = '' + On which port to run the management plugin + ''; + }; + }; + }; + }; + + + ###### implementation + config = mkIf cfg.enable { + + # This is needed so we will have 'rabbitmqctl' in our PATH + environment.systemPackages = [ cfg.package ]; + + services.epmd.enable = true; + + users.users.rabbitmq = { + description = "RabbitMQ server user"; + home = "${cfg.dataDir}"; + createHome = true; + group = "rabbitmq"; + uid = config.ids.uids.rabbitmq; + }; + + users.groups.rabbitmq.gid = config.ids.gids.rabbitmq; + + services.rabbitmq.configItems = { + "listeners.tcp.1" = mkDefault "${cfg.listenAddress}:${toString cfg.port}"; + } // optionalAttrs cfg.managementPlugin.enable { + "management.tcp.port" = toString cfg.managementPlugin.port; + "management.tcp.ip" = cfg.listenAddress; + }; + + services.rabbitmq.plugins = optional cfg.managementPlugin.enable "rabbitmq_management"; + + systemd.services.rabbitmq = { + description = "RabbitMQ Server"; + + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" "epmd.socket" ]; + wants = [ "network.target" "epmd.socket" ]; + + path = [ + cfg.package + pkgs.coreutils # mkdir/chown/chmod for preStart + ]; + + environment = { + RABBITMQ_MNESIA_BASE = "${cfg.dataDir}/mnesia"; + RABBITMQ_LOGS = "-"; + SYS_PREFIX = ""; + RABBITMQ_CONFIG_FILE = config_file; + RABBITMQ_PLUGINS_DIR = concatStringsSep ":" cfg.pluginDirs; + RABBITMQ_ENABLED_PLUGINS_FILE = pkgs.writeText "enabled_plugins" '' + [ ${concatStringsSep "," cfg.plugins} ]. + ''; + } // optionalAttrs (cfg.config != "") { RABBITMQ_ADVANCED_CONFIG_FILE = advanced_config_file; }; + + serviceConfig = { + ExecStart = "${cfg.package}/sbin/rabbitmq-server"; + ExecStop = "${cfg.package}/sbin/rabbitmqctl shutdown"; + User = "rabbitmq"; + Group = "rabbitmq"; + LogsDirectory = "rabbitmq"; + WorkingDirectory = cfg.dataDir; + Type = "notify"; + NotifyAccess = "all"; + UMask = "0027"; + LimitNOFILE = "100000"; + Restart = "on-failure"; + RestartSec = "10"; + TimeoutStartSec = "3600"; + }; + + preStart = '' + ${optionalString (cfg.cookie != "") '' + echo -n ${cfg.cookie} > ${cfg.dataDir}/.erlang.cookie + chmod 600 ${cfg.dataDir}/.erlang.cookie + ''} + ''; + }; + + }; + +} |