From 16cccc251372c63f6dfdd5dd5a0f9046d9fecd8e Mon Sep 17 00:00:00 2001 From: Alexey Lebedeff Date: Thu, 25 Jan 2018 20:17:34 +0100 Subject: [PATCH 1/2] erlang: Build with systemd support That way 'epmd' can be started by systemd using socket activation. This is important to have when there is more than one Erlang system used on the same host. Support for this exists since 17.0: https://github.com/erlang/otp/commit/b7c95eabf6017ddb352fb8ce2b3749af108ebf29 Configure flag was added in 17.1: https://github.com/erlang/otp/commit/12cd5e5b394623fab9907622ad99163c5b9350e1 --- pkgs/development/interpreters/erlang/generic-builder.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/development/interpreters/erlang/generic-builder.nix b/pkgs/development/interpreters/erlang/generic-builder.nix index 6ea3ac73a4b..b4f70899693 100644 --- a/pkgs/development/interpreters/erlang/generic-builder.nix +++ b/pkgs/development/interpreters/erlang/generic-builder.nix @@ -3,6 +3,7 @@ , openjdk ? null # javacSupport , unixODBC ? null # odbcSupport , libGLU_combined ? null, wxGTK ? null, wxmac ? null, xorg ? null # wxSupport +, withSystemd ? stdenv.isLinux, systemd # systemd support in epmd }: { baseName ? "erlang" @@ -53,6 +54,7 @@ in stdenv.mkDerivation ({ ++ optionals wxSupport wxPackages2 ++ optionals odbcSupport odbcPackages ++ optionals javacSupport javacPackages + ++ optional withSystemd systemd ++ optionals stdenv.isDarwin (with pkgs.darwin.apple_sdk.frameworks; [ Carbon Cocoa ]); debugInfo = enableDebugInfo; @@ -82,6 +84,7 @@ in stdenv.mkDerivation ({ ++ optional javacSupport "--with-javac" ++ optional odbcSupport "--with-odbc=${unixODBC}" ++ optional wxSupport "--enable-wx" + ++ optional withSystemd "--enable-systemd" ++ optional stdenv.isDarwin "--enable-darwin-64bit"; # install-docs will generate and install manpages and html docs From c00d17aae388bca8bf5657a2f312a1e436e7aef0 Mon Sep 17 00:00:00 2001 From: Alexey Lebedeff Date: Thu, 25 Jan 2018 20:28:58 +0100 Subject: [PATCH 2/2] 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: https://github.com/rabbitmq/rabbitmq-server/blame/7741b37b1efa97ac9b17685cc626bd35ee52ca16/src/rabbit_epmd_monitor.erl#L36 Having the only one socket-activated epmd completely solves this problem. --- nixos/modules/module-list.nix | 1 + nixos/modules/services/networking/epmd.nix | 56 ++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 nixos/modules/services/networking/epmd.nix diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index cd00bc8d6bc..aa79849d18a 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -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 diff --git a/nixos/modules/services/networking/epmd.nix b/nixos/modules/services/networking/epmd.nix new file mode 100644 index 00000000000..692b75e4f08 --- /dev/null +++ b/nixos/modules/services/networking/epmd.nix @@ -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"; + }; + }; + }; +}