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