at 25.11-pre 4.8 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8with lib; 9 10let 11 cfg = config.networking.ucarp; 12 13 ucarpExec = concatStringsSep " " ( 14 [ 15 "${cfg.package}/bin/ucarp" 16 "--interface=${cfg.interface}" 17 "--srcip=${cfg.srcIp}" 18 "--vhid=${toString cfg.vhId}" 19 "--passfile=${cfg.passwordFile}" 20 "--addr=${cfg.addr}" 21 "--advbase=${toString cfg.advBase}" 22 "--advskew=${toString cfg.advSkew}" 23 "--upscript=${cfg.upscript}" 24 "--downscript=${cfg.downscript}" 25 "--deadratio=${toString cfg.deadratio}" 26 ] 27 ++ (optional cfg.preempt "--preempt") 28 ++ (optional cfg.neutral "--neutral") 29 ++ (optional cfg.shutdown "--shutdown") 30 ++ (optional cfg.ignoreIfState "--ignoreifstate") 31 ++ (optional cfg.noMcast "--nomcast") 32 ++ (optional (cfg.extraParam != null) "--xparam=${cfg.extraParam}") 33 ); 34in 35{ 36 options.networking.ucarp = { 37 enable = mkEnableOption "ucarp, userspace implementation of CARP"; 38 39 interface = mkOption { 40 type = types.str; 41 description = "Network interface to bind to."; 42 example = "eth0"; 43 }; 44 45 srcIp = mkOption { 46 type = types.str; 47 description = "Source (real) IP address of this host."; 48 }; 49 50 vhId = mkOption { 51 type = types.ints.between 1 255; 52 description = "Virtual IP identifier shared between CARP hosts."; 53 example = 1; 54 }; 55 56 passwordFile = mkOption { 57 type = types.str; 58 description = "File containing shared password between CARP hosts."; 59 example = "/run/keys/ucarp-password"; 60 }; 61 62 preempt = mkOption { 63 type = types.bool; 64 description = '' 65 Enable preemptive failover. 66 Thus, this host becomes the CARP master as soon as possible. 67 ''; 68 default = false; 69 }; 70 71 neutral = mkOption { 72 type = types.bool; 73 description = "Do not run downscript at start if the host is the backup."; 74 default = false; 75 }; 76 77 addr = mkOption { 78 type = types.str; 79 description = "Virtual shared IP address."; 80 }; 81 82 advBase = mkOption { 83 type = types.ints.unsigned; 84 description = "Advertisement frequency in seconds."; 85 default = 1; 86 }; 87 88 advSkew = mkOption { 89 type = types.ints.unsigned; 90 description = "Advertisement skew in seconds."; 91 default = 0; 92 }; 93 94 upscript = mkOption { 95 type = types.path; 96 description = '' 97 Command to run after become master, the interface name, virtual address 98 and optional extra parameters are passed as arguments. 99 ''; 100 example = literalExpression '' 101 pkgs.writeScript "upscript" ''' 102 #!/bin/sh 103 ''${pkgs.iproute2}/bin/ip addr add "$2"/24 dev "$1" 104 '''; 105 ''; 106 }; 107 108 downscript = mkOption { 109 type = types.path; 110 description = '' 111 Command to run after become backup, the interface name, virtual address 112 and optional extra parameters are passed as arguments. 113 ''; 114 example = literalExpression '' 115 pkgs.writeScript "downscript" ''' 116 #!/bin/sh 117 ''${pkgs.iproute2}/bin/ip addr del "$2"/24 dev "$1" 118 '''; 119 ''; 120 }; 121 122 deadratio = mkOption { 123 type = types.ints.unsigned; 124 description = "Ratio to consider a host as dead."; 125 default = 3; 126 }; 127 128 shutdown = mkOption { 129 type = types.bool; 130 description = "Call downscript at exit."; 131 default = false; 132 }; 133 134 ignoreIfState = mkOption { 135 type = types.bool; 136 description = "Ignore interface state, e.g., down or no carrier."; 137 default = false; 138 }; 139 140 noMcast = mkOption { 141 type = types.bool; 142 description = "Use broadcast instead of multicast advertisements."; 143 default = false; 144 }; 145 146 extraParam = mkOption { 147 type = types.nullOr types.str; 148 description = "Extra parameter to pass to the up/down scripts."; 149 default = null; 150 }; 151 152 package = mkPackageOption pkgs "ucarp" { 153 extraDescription = '' 154 Please note that the default package, pkgs.ucarp, has not received any 155 upstream updates for a long time and can be considered as unmaintained. 156 ''; 157 }; 158 }; 159 160 config = mkIf cfg.enable { 161 systemd.services.ucarp = { 162 description = "ucarp, userspace implementation of CARP"; 163 164 wantedBy = [ "multi-user.target" ]; 165 after = [ "network.target" ]; 166 167 serviceConfig = { 168 Type = "exec"; 169 ExecStart = ucarpExec; 170 171 ProtectSystem = "strict"; 172 ProtectHome = true; 173 PrivateTmp = true; 174 ProtectClock = true; 175 ProtectKernelModules = true; 176 ProtectControlGroups = true; 177 MemoryDenyWriteExecute = true; 178 RestrictRealtime = true; 179 }; 180 }; 181 }; 182 183 meta.maintainers = with lib.maintainers; [ oxzi ]; 184}