3
0
Fork 0
forked from mirrors/nixpkgs
nixpkgs/nixos/modules/services/networking/consul.nix

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

286 lines
8.1 KiB
Nix
Raw Normal View History

2014-09-15 09:26:26 +01:00
{ config, lib, pkgs, utils, ... }:
with lib;
let
dataDir = "/var/lib/consul";
cfg = config.services.consul;
configOptions = {
data_dir = dataDir;
2021-12-03 17:46:24 +00:00
ui_config = {
enabled = cfg.webUi;
};
} // cfg.extraConfig;
2014-09-15 09:26:26 +01:00
configFiles = [ "/etc/consul.json" "/etc/consul-addrs.json" ]
++ cfg.extraConfigFiles;
devices = attrValues (filterAttrs (_: i: i != null) cfg.interface);
systemdDevices = forEach devices
2014-09-15 09:26:26 +01:00
(i: "sys-subsystem-net-devices-${utils.escapeSystemdPath i}.device");
in
{
options = {
services.consul = {
enable = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
2014-09-15 09:26:26 +01:00
Enables the consul daemon.
'';
};
2016-01-07 23:54:43 +00:00
package = mkOption {
type = types.package;
default = pkgs.consul;
defaultText = literalExpression "pkgs.consul";
description = lib.mdDoc ''
2016-01-07 23:54:43 +00:00
The package used for the Consul agent and CLI.
'';
};
2014-09-15 09:26:26 +01:00
webUi = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
2014-09-15 09:26:26 +01:00
Enables the web interface on the consul http port.
'';
};
leaveOnStop = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
If enabled, causes a leave action to be sent when closing consul.
This allows a clean termination of the node, but permanently removes
it from the cluster. You probably don't want this option unless you
are running a node which going offline in a permanent / semi-permanent
fashion.
'';
};
2014-09-15 09:26:26 +01:00
interface = {
advertise = mkOption {
type = types.nullOr types.str;
default = null;
description = lib.mdDoc ''
2014-09-15 09:26:26 +01:00
The name of the interface to pull the advertise_addr from.
'';
};
bind = mkOption {
type = types.nullOr types.str;
default = null;
description = lib.mdDoc ''
2014-09-15 09:26:26 +01:00
The name of the interface to pull the bind_addr from.
'';
};
2022-04-20 12:57:32 +01:00
};
2014-09-15 09:26:26 +01:00
2022-04-20 12:57:32 +01:00
forceAddrFamily = mkOption {
type = types.enum [ "any" "ipv4" "ipv6" ];
default = "any";
description = lib.mdDoc ''
2022-04-20 12:57:32 +01:00
Whether to bind ipv4/ipv6 or both kind of addresses.
'';
2014-09-15 09:26:26 +01:00
};
forceIpv4 = mkOption {
2022-04-20 12:57:32 +01:00
type = types.nullOr types.bool;
default = null;
description = lib.mdDoc ''
2022-04-20 12:57:32 +01:00
Deprecated: Use consul.forceAddrFamily instead.
2014-09-15 09:26:26 +01:00
Whether we should force the interfaces to only pull ipv4 addresses.
'';
};
dropPrivileges = mkOption {
type = types.bool;
default = true;
description = lib.mdDoc ''
2014-09-15 09:26:26 +01:00
Whether the consul agent should be run as a non-root consul user.
'';
};
extraConfig = mkOption {
default = { };
2021-01-27 09:38:56 +00:00
type = types.attrsOf types.anything;
description = lib.mdDoc ''
2014-09-15 09:26:26 +01:00
Extra configuration options which are serialized to json and added
to the config.json file.
'';
};
extraConfigFiles = mkOption {
default = [ ];
type = types.listOf types.str;
description = lib.mdDoc ''
2014-09-15 09:26:26 +01:00
Additional configuration files to pass to consul
NOTE: These will not trigger the service to be restarted when altered.
'';
};
alerts = {
2015-06-21 16:19:46 +01:00
enable = mkEnableOption "consul-alerts";
2015-06-08 12:41:43 +01:00
package = mkOption {
description = lib.mdDoc "Package to use for consul-alerts.";
2015-06-08 12:41:43 +01:00
default = pkgs.consul-alerts;
defaultText = literalExpression "pkgs.consul-alerts";
2015-06-08 12:41:43 +01:00
type = types.package;
};
listenAddr = mkOption {
description = lib.mdDoc "Api listening address.";
default = "localhost:9000";
type = types.str;
};
consulAddr = mkOption {
description = lib.mdDoc "Consul api listening adddress";
default = "localhost:8500";
type = types.str;
};
watchChecks = mkOption {
description = lib.mdDoc "Whether to enable check watcher.";
default = true;
type = types.bool;
};
watchEvents = mkOption {
description = lib.mdDoc "Whether to enable event watcher.";
default = true;
type = types.bool;
};
};
2014-09-15 09:26:26 +01:00
};
};
2015-06-08 12:41:43 +01:00
config = mkIf cfg.enable (
mkMerge [{
2014-09-15 09:26:26 +01:00
2019-08-13 22:52:01 +01:00
users.users.consul = {
2015-06-08 12:41:43 +01:00
description = "Consul agent daemon user";
isSystemUser = true;
group = "consul";
2015-06-08 12:41:43 +01:00
# The shell is needed for health checks
shell = "/run/current-system/sw/bin/bash";
};
users.groups.consul = {};
2014-09-15 09:26:26 +01:00
2015-06-08 12:41:43 +01:00
environment = {
etc."consul.json".text = builtins.toJSON configOptions;
# We need consul.d to exist for consul to start
etc."consul.d/dummy.json".text = "{ }";
2016-01-07 23:54:43 +00:00
systemPackages = [ cfg.package ];
2015-06-08 12:41:43 +01:00
};
2014-09-15 09:26:26 +01:00
2022-04-20 12:57:32 +01:00
warnings = lib.flatten [
(lib.optional (cfg.forceIpv4 != null) ''
The option consul.forceIpv4 is deprecated, please use
consul.forceAddrFamily instead.
'')
];
2015-06-08 12:41:43 +01:00
systemd.services.consul = {
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ] ++ systemdDevices;
bindsTo = systemdDevices;
restartTriggers = [ config.environment.etc."consul.json".source ]
++ mapAttrsToList (_: d: d.source)
(filterAttrs (n: _: hasPrefix "consul.d/" n) config.environment.etc);
serviceConfig = {
ExecStart = "@${cfg.package}/bin/consul consul agent -config-dir /etc/consul.d"
2015-06-08 12:41:43 +01:00
+ concatMapStrings (n: " -config-file ${n}") configFiles;
ExecReload = "${cfg.package}/bin/consul reload";
2015-06-08 12:41:43 +01:00
PermissionsStartOnly = true;
User = if cfg.dropPrivileges then "consul" else null;
Restart = "on-failure";
TimeoutStartSec = "infinity";
2015-06-08 12:41:43 +01:00
} // (optionalAttrs (cfg.leaveOnStop) {
ExecStop = "${cfg.package}/bin/consul leave";
2015-06-08 12:41:43 +01:00
});
2021-03-14 16:05:16 +00:00
path = with pkgs; [ iproute2 gnugrep gawk consul ];
2022-04-20 12:57:32 +01:00
preStart = let
family = if cfg.forceAddrFamily == "ipv6" then
"-6"
else if cfg.forceAddrFamily == "ipv4" then
"-4"
else
"";
in ''
2015-06-08 12:41:43 +01:00
mkdir -m 0700 -p ${dataDir}
chown -R consul ${dataDir}
# Determine interface addresses
getAddrOnce () {
2022-04-20 12:57:32 +01:00
ip ${family} addr show dev "$1" scope global \
| awk -F '[ /\t]*' '/inet/ {print $3}' | head -n 1
2015-06-08 12:41:43 +01:00
}
getAddr () {
2014-09-15 09:26:26 +01:00
ADDR="$(getAddrOnce $1)"
2015-06-08 12:41:43 +01:00
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
delim=" "
''
+ concatStrings (flip mapAttrsToList cfg.interface (name: i:
optionalString (i != null) ''
echo "$delim \"${name}_addr\": \"$(getAddr "${i}")\"" >> /etc/consul-addrs.json
delim=","
''))
+ ''
echo "}" >> /etc/consul-addrs.json
'';
};
2015-06-08 12:41:43 +01:00
}
2022-04-20 12:57:32 +01:00
# deprecated
(mkIf (cfg.forceIpv4 != null && cfg.forceIpv4) {
services.consul.forceAddrFamily = "ipv4";
})
2015-06-08 12:41:43 +01:00
(mkIf (cfg.alerts.enable) {
systemd.services.consul-alerts = {
wantedBy = [ "multi-user.target" ];
after = [ "consul.service" ];
2016-01-07 23:54:43 +00:00
path = [ cfg.package ];
2015-06-08 12:41:43 +01:00
serviceConfig = {
ExecStart = ''
${cfg.alerts.package}/bin/consul-alerts start \
2015-06-08 12:41:43 +01:00
--alert-addr=${cfg.alerts.listenAddr} \
--consul-addr=${cfg.alerts.consulAddr} \
${optionalString cfg.alerts.watchChecks "--watch-checks"} \
${optionalString cfg.alerts.watchEvents "--watch-events"}
'';
User = if cfg.dropPrivileges then "consul" else null;
Restart = "on-failure";
};
};
})
2015-06-08 12:41:43 +01:00
]);
2014-09-15 09:26:26 +01:00
}