at 21.11-pre 6.7 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.rabbitmq; 7 8 inherit (builtins) concatStringsSep; 9 10 config_file_content = lib.generators.toKeyValue {} cfg.configItems; 11 config_file = pkgs.writeText "rabbitmq.conf" config_file_content; 12 13 advanced_config_file = pkgs.writeText "advanced.config" cfg.config; 14 15in { 16 ###### interface 17 options = { 18 services.rabbitmq = { 19 enable = mkOption { 20 type = types.bool; 21 default = false; 22 description = '' 23 Whether to enable the RabbitMQ server, an Advanced Message 24 Queuing Protocol (AMQP) broker. 25 ''; 26 }; 27 28 package = mkOption { 29 default = pkgs.rabbitmq-server; 30 type = types.package; 31 defaultText = "pkgs.rabbitmq-server"; 32 description = '' 33 Which rabbitmq package to use. 34 ''; 35 }; 36 37 listenAddress = mkOption { 38 default = "127.0.0.1"; 39 example = ""; 40 description = '' 41 IP address on which RabbitMQ will listen for AMQP 42 connections. Set to the empty string to listen on all 43 interfaces. Note that RabbitMQ creates a user named 44 <literal>guest</literal> with password 45 <literal>guest</literal> by default, so you should delete 46 this user if you intend to allow external access. 47 48 Together with 'port' setting it's mostly an alias for 49 configItems."listeners.tcp.1" and it's left for backwards 50 compatibility with previous version of this module. 51 ''; 52 type = types.str; 53 }; 54 55 port = mkOption { 56 default = 5672; 57 description = '' 58 Port on which RabbitMQ will listen for AMQP connections. 59 ''; 60 type = types.int; 61 }; 62 63 dataDir = mkOption { 64 type = types.path; 65 default = "/var/lib/rabbitmq"; 66 description = '' 67 Data directory for rabbitmq. 68 ''; 69 }; 70 71 cookie = mkOption { 72 default = ""; 73 type = types.str; 74 description = '' 75 Erlang cookie is a string of arbitrary length which must 76 be the same for several nodes to be allowed to communicate. 77 Leave empty to generate automatically. 78 ''; 79 }; 80 81 configItems = mkOption { 82 default = {}; 83 type = types.attrsOf types.str; 84 example = literalExample '' 85 { 86 "auth_backends.1.authn" = "rabbit_auth_backend_ldap"; 87 "auth_backends.1.authz" = "rabbit_auth_backend_internal"; 88 } 89 ''; 90 description = '' 91 Configuration options in RabbitMQ's new config file format, 92 which is a simple key-value format that can not express nested 93 data structures. This is known as the <literal>rabbitmq.conf</literal> file, 94 although outside NixOS that filename may have Erlang syntax, particularly 95 prior to RabbitMQ 3.7.0. 96 97 If you do need to express nested data structures, you can use 98 <literal>config</literal> option. Configuration from <literal>config</literal> 99 will be merged into these options by RabbitMQ at runtime to 100 form the final configuration. 101 102 See https://www.rabbitmq.com/configure.html#config-items 103 For the distinct formats, see https://www.rabbitmq.com/configure.html#config-file-formats 104 ''; 105 }; 106 107 config = mkOption { 108 default = ""; 109 type = types.str; 110 description = '' 111 Verbatim advanced configuration file contents using the Erlang syntax. 112 This is also known as the <literal>advanced.config</literal> file or the old config format. 113 114 <literal>configItems</literal> is preferred whenever possible. However, nested 115 data structures can only be expressed properly using the <literal>config</literal> option. 116 117 The contents of this option will be merged into the <literal>configItems</literal> 118 by RabbitMQ at runtime to form the final configuration. 119 120 See the second table on https://www.rabbitmq.com/configure.html#config-items 121 For the distinct formats, see https://www.rabbitmq.com/configure.html#config-file-formats 122 ''; 123 }; 124 125 plugins = mkOption { 126 default = []; 127 type = types.listOf types.str; 128 description = "The names of plugins to enable"; 129 }; 130 131 pluginDirs = mkOption { 132 default = []; 133 type = types.listOf types.path; 134 description = "The list of directories containing external plugins"; 135 }; 136 }; 137 }; 138 139 140 ###### implementation 141 config = mkIf cfg.enable { 142 143 # This is needed so we will have 'rabbitmqctl' in our PATH 144 environment.systemPackages = [ cfg.package ]; 145 146 services.epmd.enable = true; 147 148 users.users.rabbitmq = { 149 description = "RabbitMQ server user"; 150 home = "${cfg.dataDir}"; 151 createHome = true; 152 group = "rabbitmq"; 153 uid = config.ids.uids.rabbitmq; 154 }; 155 156 users.groups.rabbitmq.gid = config.ids.gids.rabbitmq; 157 158 services.rabbitmq.configItems = { 159 "listeners.tcp.1" = mkDefault "${cfg.listenAddress}:${toString cfg.port}"; 160 }; 161 162 systemd.services.rabbitmq = { 163 description = "RabbitMQ Server"; 164 165 wantedBy = [ "multi-user.target" ]; 166 after = [ "network.target" "epmd.socket" ]; 167 wants = [ "network.target" "epmd.socket" ]; 168 169 path = [ 170 cfg.package 171 pkgs.coreutils # mkdir/chown/chmod for preStart 172 ]; 173 174 environment = { 175 RABBITMQ_MNESIA_BASE = "${cfg.dataDir}/mnesia"; 176 RABBITMQ_LOGS = "-"; 177 SYS_PREFIX = ""; 178 RABBITMQ_CONFIG_FILE = config_file; 179 RABBITMQ_PLUGINS_DIR = concatStringsSep ":" cfg.pluginDirs; 180 RABBITMQ_ENABLED_PLUGINS_FILE = pkgs.writeText "enabled_plugins" '' 181 [ ${concatStringsSep "," cfg.plugins} ]. 182 ''; 183 } // optionalAttrs (cfg.config != "") { RABBITMQ_ADVANCED_CONFIG_FILE = advanced_config_file; }; 184 185 serviceConfig = { 186 ExecStart = "${cfg.package}/sbin/rabbitmq-server"; 187 ExecStop = "${cfg.package}/sbin/rabbitmqctl shutdown"; 188 User = "rabbitmq"; 189 Group = "rabbitmq"; 190 LogsDirectory = "rabbitmq"; 191 WorkingDirectory = cfg.dataDir; 192 Type = "notify"; 193 NotifyAccess = "all"; 194 UMask = "0027"; 195 LimitNOFILE = "100000"; 196 Restart = "on-failure"; 197 RestartSec = "10"; 198 TimeoutStartSec = "3600"; 199 }; 200 201 preStart = '' 202 ${optionalString (cfg.cookie != "") '' 203 echo -n ${cfg.cookie} > ${cfg.dataDir}/.erlang.cookie 204 chmod 600 ${cfg.dataDir}/.erlang.cookie 205 ''} 206 ''; 207 }; 208 209 }; 210 211}