at 23.11-pre 5.1 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 (lib.mdDoc "ucarp, userspace implementation of CARP"); 32 33 interface = mkOption { 34 type = types.str; 35 description = lib.mdDoc "Network interface to bind to."; 36 example = "eth0"; 37 }; 38 39 srcIp = mkOption { 40 type = types.str; 41 description = lib.mdDoc "Source (real) IP address of this host."; 42 }; 43 44 vhId = mkOption { 45 type = types.ints.between 1 255; 46 description = lib.mdDoc "Virtual IP identifier shared between CARP hosts."; 47 example = 1; 48 }; 49 50 passwordFile = mkOption { 51 type = types.str; 52 description = lib.mdDoc "File containing shared password between CARP hosts."; 53 example = "/run/keys/ucarp-password"; 54 }; 55 56 preempt = mkOption { 57 type = types.bool; 58 description = lib.mdDoc '' 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 = lib.mdDoc "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 = lib.mdDoc "Virtual shared IP address."; 74 }; 75 76 advBase = mkOption { 77 type = types.ints.unsigned; 78 description = lib.mdDoc "Advertisement frequency in seconds."; 79 default = 1; 80 }; 81 82 advSkew = mkOption { 83 type = types.ints.unsigned; 84 description = lib.mdDoc "Advertisement skew in seconds."; 85 default = 0; 86 }; 87 88 upscript = mkOption { 89 type = types.path; 90 description = lib.mdDoc '' 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 = lib.mdDoc '' 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 = lib.mdDoc "Ratio to consider a host as dead."; 119 default = 3; 120 }; 121 122 shutdown = mkOption { 123 type = types.bool; 124 description = lib.mdDoc "Call downscript at exit."; 125 default = false; 126 }; 127 128 ignoreIfState = mkOption { 129 type = types.bool; 130 description = lib.mdDoc "Ignore interface state, e.g., down or no carrier."; 131 default = false; 132 }; 133 134 noMcast = mkOption { 135 type = types.bool; 136 description = lib.mdDoc "Use broadcast instead of multicast advertisements."; 137 default = false; 138 }; 139 140 extraParam = mkOption { 141 type = types.nullOr types.str; 142 description = lib.mdDoc "Extra parameter to pass to the up/down scripts."; 143 default = null; 144 }; 145 146 package = mkOption { 147 type = types.package; 148 description = lib.mdDoc '' 149 Package that should be used for ucarp. 150 151 Please note that the default package, pkgs.ucarp, has not received any 152 upstream updates for a long time and can be considered as unmaintained. 153 ''; 154 default = pkgs.ucarp; 155 defaultText = literalExpression "pkgs.ucarp"; 156 }; 157 }; 158 159 config = mkIf cfg.enable { 160 systemd.services.ucarp = { 161 description = "ucarp, userspace implementation of CARP"; 162 163 wantedBy = [ "multi-user.target" ]; 164 after = [ "network.target" ]; 165 166 serviceConfig = { 167 Type = "exec"; 168 ExecStart = ucarpExec; 169 170 ProtectSystem = "strict"; 171 ProtectHome = true; 172 PrivateTmp = true; 173 ProtectClock = true; 174 ProtectKernelModules = true; 175 ProtectControlGroups = true; 176 MemoryDenyWriteExecute = true; 177 RestrictRealtime = true; 178 }; 179 }; 180 }; 181 182 meta.maintainers = with lib.maintainers; [ oxzi ]; 183}