nixpkgs/nixos/modules/services/networking/consul.nix
William A. Kennington III 36f9b9c284 nixos/consul: Add module
2014-09-26 03:25:14 -07:00

167 lines
4.3 KiB
Nix

{ config, lib, pkgs, utils, ... }:
with lib;
let
dataDir = "/var/lib/consul";
cfg = config.services.consul;
configOptions = {
data_dir = dataDir;
rejoin_after_leave = true;
}
// (if cfg.webUi then { ui_dir = "${pkgs.consul.ui}"; } else { })
// cfg.extraConfig;
configFiles = [ "/etc/consul.json" "/etc/consul-addrs.json" ]
++ cfg.extraConfigFiles;
devices = attrValues (filterAttrs (_: i: i != null) cfg.interface);
systemdDevices = flip map devices
(i: "sys-subsystem-net-devices-${utils.escapeSystemdPath i}.device");
in
{
options = {
services.consul = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Enables the consul daemon.
'';
};
webUi = mkOption {
type = types.bool;
default = false;
description = ''
Enables the web interface on the consul http port.
'';
};
interface = {
advertise = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
The name of the interface to pull the advertise_addr from.
'';
};
bind = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
The name of the interface to pull the bind_addr from.
'';
};
};
forceIpv4 = mkOption {
type = types.bool;
default = false;
description = ''
Whether we should force the interfaces to only pull ipv4 addresses.
'';
};
dropPrivileges = mkOption {
type = types.bool;
default = true;
description = ''
Whether the consul agent should be run as a non-root consul user.
'';
};
extraConfig = mkOption {
default = { };
description = ''
Extra configuration options which are serialized to json and added
to the config.json file.
'';
};
extraConfigFiles = mkOption {
default = [ ];
type = types.listOf types.str;
description = ''
Additional configuration files to pass to consul
NOTE: These will not trigger the service to be restarted when altered.
'';
};
};
};
config = mkIf cfg.enable {
users.extraUsers."consul" = {
description = "Consul agent daemon user";
uid = config.ids.uids.consul;
};
environment = {
etc."consul.json".text = builtins.toJSON configOptions;
systemPackages = with pkgs; [ consul ];
};
systemd.services.consul = {
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ] ++ systemdDevices;
bindsTo = systemdDevices;
restartTriggers = [ config.environment.etc."consul.json".source ];
serviceConfig = {
ExecStart = "@${pkgs.consul}/bin/consul consul agent"
+ concatMapStrings (n: " -config-file ${n}") configFiles;
ExecStop = "${pkgs.consul}/bin/consul leave";
ExecReload = "${pkgs.consul}/bin/consul reload";
PermissionsStartOnly = true;
User = if cfg.dropPrivileges then "consul" else null;
};
path = with pkgs; [ iproute gnugrep gawk ];
preStart = ''
mkdir -m 0700 -p ${dataDir}
chown -R consul ${dataDir}
# Determine interface addresses
getAddrOnce () {
ip addr show dev "$1" \
| grep 'inet${optionalString (cfg.forceIpv4) " "}.*scope global' \
| awk -F '[ /\t]*' '{print $3}' | head -n 1
}
getAddr () {
ADDR="$(getAddrOnce $1)"
LEFT=60 # Die after 1 minute
while [ -z "$ADDR" ]; do
sleep 1
LEFT=$(expr $LEFT - 1)
if [ "$LEFT" -eq "0" ]; then
echo "Address lookup timed out"
exit 1
fi
ADDR="$(getAddrOnce $1)"
done
echo "$ADDR"
}
echo "{" > /etc/consul-addrs.json
''
+ concatStrings (flip mapAttrsToList cfg.interface (name: i:
optionalString (i != null) ''
echo " \"${name}_addr\": \"$(getAddr "${i}")\"," >> /etc/consul-addrs.json
''))
+ ''
echo " \"\": \"\"" >> /etc/consul-addrs.json
echo "}" >> /etc/consul-addrs.json
'';
};
};
}