1 { config, lib, pkgs, ... }:
6 cfg = config.networking.ucarp;
8 ucarpExec = concatStringsSep " " (
10 "${cfg.package}/bin/ucarp"
11 "--interface=${cfg.interface}"
12 "--srcip=${cfg.srcIp}"
13 "--vhid=${toString cfg.vhId}"
14 "--passfile=${cfg.passwordFile}"
16 "--advbase=${toString cfg.advBase}"
17 "--advskew=${toString cfg.advSkew}"
18 "--upscript=${cfg.upscript}"
19 "--downscript=${cfg.downscript}"
20 "--deadratio=${toString cfg.deadratio}"
22 ++ (optional cfg.preempt "--preempt")
23 ++ (optional cfg.neutral "--neutral")
24 ++ (optional cfg.shutdown "--shutdown")
25 ++ (optional cfg.ignoreIfState "--ignoreifstate")
26 ++ (optional cfg.noMcast "--nomcast")
27 ++ (optional (cfg.extraParam != null) "--xparam=${cfg.extraParam}")
30 options.networking.ucarp = {
31 enable = mkEnableOption "ucarp, userspace implementation of CARP";
33 interface = mkOption {
35 description = "Network interface to bind to.";
41 description = "Source (real) IP address of this host.";
45 type = types.ints.between 1 255;
46 description = "Virtual IP identifier shared between CARP hosts.";
50 passwordFile = mkOption {
52 description = "File containing shared password between CARP hosts.";
53 example = "/run/keys/ucarp-password";
59 Enable preemptive failover.
60 Thus, this host becomes the CARP master as soon as possible.
67 description = "Do not run downscript at start if the host is the backup.";
73 description = "Virtual shared IP address.";
77 type = types.ints.unsigned;
78 description = "Advertisement frequency in seconds.";
83 type = types.ints.unsigned;
84 description = "Advertisement skew in seconds.";
91 Command to run after become master, the interface name, virtual address
92 and optional extra parameters are passed as arguments.
94 example = literalExpression ''
95 pkgs.writeScript "upscript" '''
97 ''${pkgs.iproute2}/bin/ip addr add "$2"/24 dev "$1"
102 downscript = mkOption {
105 Command to run after become backup, the interface name, virtual address
106 and optional extra parameters are passed as arguments.
108 example = literalExpression ''
109 pkgs.writeScript "downscript" '''
111 ''${pkgs.iproute2}/bin/ip addr del "$2"/24 dev "$1"
116 deadratio = mkOption {
117 type = types.ints.unsigned;
118 description = "Ratio to consider a host as dead.";
122 shutdown = mkOption {
124 description = "Call downscript at exit.";
128 ignoreIfState = mkOption {
130 description = "Ignore interface state, e.g., down or no carrier.";
136 description = "Use broadcast instead of multicast advertisements.";
140 extraParam = mkOption {
141 type = types.nullOr types.str;
142 description = "Extra parameter to pass to the up/down scripts.";
146 package = mkPackageOption pkgs "ucarp" {
147 extraDescription = ''
148 Please note that the default package, pkgs.ucarp, has not received any
149 upstream updates for a long time and can be considered as unmaintained.
154 config = mkIf cfg.enable {
155 systemd.services.ucarp = {
156 description = "ucarp, userspace implementation of CARP";
158 wantedBy = [ "multi-user.target" ];
159 after = [ "network.target" ];
163 ExecStart = ucarpExec;
165 ProtectSystem = "strict";
169 ProtectKernelModules = true;
170 ProtectControlGroups = true;
171 MemoryDenyWriteExecute = true;
172 RestrictRealtime = true;
177 meta.maintainers = with lib.maintainers; [ oxzi ];