epmd: Introduce erlang port mapper daemon service

Having socket-activated epmd means that there always be only a single
instance managed centrally. Because Erlang also starts it
automatically if not available, and in worst case scenario 'epmd' can
be started by some Erlang application running under systemd. And then
restarting this application unit will cause complete loss of names in
'epmd' (if other Erlang system are also installed on this host).

E.g. see at which lengths RabbitMQ goes to recover from such
situations:
7741b37b1e/src/rabbit_epmd_monitor.erl (L36)

Having the only one socket-activated epmd completely solves this
problem.
This commit is contained in:
Alexey Lebedeff 2018-01-25 20:28:58 +01:00 committed by Alexey Lebedeff
parent 16cccc2513
commit c00d17aae3
2 changed files with 57 additions and 0 deletions

View file

@ -484,6 +484,7 @@
./services/networking/dnsdist.nix
./services/networking/dnsmasq.nix
./services/networking/ejabberd.nix
./services/networking/epmd.nix
./services/networking/fakeroute.nix
./services/networking/ferm.nix
./services/networking/firefox/sync-server.nix

View file

@ -0,0 +1,56 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.epmd;
in
{
###### interface
options.services.epmd = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable socket activation for Erlang Port Mapper Daemon (epmd),
which acts as a name server on all hosts involved in distributed
Erlang computations.
'';
};
package = mkOption {
type = types.package;
default = pkgs.erlang;
description = ''
The Erlang package to use to get epmd binary. That way you can re-use
an Erlang runtime that is already installed for other purposes.
'';
};
};
###### implementation
config = mkIf cfg.enable {
systemd.sockets.epmd = rec {
description = "Erlang Port Mapper Daemon Activation Socket";
wantedBy = [ "sockets.target" ];
before = wantedBy;
socketConfig = {
ListenStream = "4369";
Accept = "false";
};
};
systemd.services.epmd = {
description = "Erlang Port Mapper Daemon";
after = [ "network.target" ];
requires = [ "epmd.socket" ];
serviceConfig = {
DynamicUser = true;
ExecStart = "${cfg.package}/bin/epmd -systemd";
Type = "notify";
};
};
};
}