From 8673a40eda6784a33f8e03521e9132ebe557d94f Mon Sep 17 00:00:00 2001 From: Alvar Penning Date: Sun, 13 Jun 2021 22:00:09 +0200 Subject: [PATCH] nixos/ucarp: init --- .../from_md/release-notes/rl-2111.section.xml | 8 + .../manual/release-notes/rl-2111.section.md | 4 + nixos/modules/module-list.nix | 1 + nixos/modules/services/networking/ucarp.nix | 183 ++++++++++++++++++ 4 files changed, 196 insertions(+) create mode 100644 nixos/modules/services/networking/ucarp.nix diff --git a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml index 781734a189a8..72fee8d16d02 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml @@ -40,6 +40,14 @@ services.sourcehut. + + + ucarp, + an userspace implementation of the Common Address Redundancy + Protocol (CARP). Available as + networking.ucarp. + +
diff --git a/nixos/doc/manual/release-notes/rl-2111.section.md b/nixos/doc/manual/release-notes/rl-2111.section.md index 3a29b29f1063..1aa22b3a4b6f 100644 --- a/nixos/doc/manual/release-notes/rl-2111.section.md +++ b/nixos/doc/manual/release-notes/rl-2111.section.md @@ -18,6 +18,10 @@ In addition to numerous new and upgraded packages, this release has the followin development. Available as [services.sourcehut](options.html#opt-services.sourcehut.enable). +* [ucarp](https://download.pureftpd.org/pub/ucarp/README), an userspace + implementation of the Common Address Redundancy Protocol (CARP). Available as + [networking.ucarp](options.html#opt-networking.ucarp.enable). + ## Backward Incompatibilities * The `staticjinja` package has been upgraded from 1.0.4 to 2.0.0 diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 2938f79fb16a..1a4c2fb719dc 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -839,6 +839,7 @@ ./services/networking/tox-node.nix ./services/networking/toxvpn.nix ./services/networking/tvheadend.nix + ./services/networking/ucarp.nix ./services/networking/unbound.nix ./services/networking/unifi.nix ./services/networking/v2ray.nix diff --git a/nixos/modules/services/networking/ucarp.nix b/nixos/modules/services/networking/ucarp.nix new file mode 100644 index 000000000000..9b19a19687bc --- /dev/null +++ b/nixos/modules/services/networking/ucarp.nix @@ -0,0 +1,183 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.networking.ucarp; + + ucarpExec = concatStringsSep " " ( + [ + "${cfg.package}/bin/ucarp" + "--interface=${cfg.interface}" + "--srcip=${cfg.srcIp}" + "--vhid=${toString cfg.vhId}" + "--passfile=${cfg.passwordFile}" + "--addr=${cfg.addr}" + "--advbase=${toString cfg.advBase}" + "--advskew=${toString cfg.advSkew}" + "--upscript=${cfg.upscript}" + "--downscript=${cfg.downscript}" + "--deadratio=${toString cfg.deadratio}" + ] + ++ (optional cfg.preempt "--preempt") + ++ (optional cfg.neutral "--neutral") + ++ (optional cfg.shutdown "--shutdown") + ++ (optional cfg.ignoreIfState "--ignoreifstate") + ++ (optional cfg.noMcast "--nomcast") + ++ (optional (cfg.extraParam != null) "--xparam=${cfg.extraParam}") + ); +in { + options.networking.ucarp = { + enable = mkEnableOption "ucarp, userspace implementation of CARP"; + + interface = mkOption { + type = types.str; + description = "Network interface to bind to."; + example = "eth0"; + }; + + srcIp = mkOption { + type = types.str; + description = "Source (real) IP address of this host."; + }; + + vhId = mkOption { + type = types.ints.between 1 255; + description = "Virtual IP identifier shared between CARP hosts."; + example = 1; + }; + + passwordFile = mkOption { + type = types.str; + description = "File containing shared password between CARP hosts."; + example = "/run/keys/ucarp-password"; + }; + + preempt = mkOption { + type = types.bool; + description = '' + Enable preemptive failover. + Thus, this host becomes the CARP master as soon as possible. + ''; + default = false; + }; + + neutral = mkOption { + type = types.bool; + description = "Do not run downscript at start if the host is the backup."; + default = false; + }; + + addr = mkOption { + type = types.str; + description = "Virtual shared IP address."; + }; + + advBase = mkOption { + type = types.ints.unsigned; + description = "Advertisement frequency in seconds."; + default = 1; + }; + + advSkew = mkOption { + type = types.ints.unsigned; + description = "Advertisement skew in seconds."; + default = 0; + }; + + upscript = mkOption { + type = types.path; + description = '' + Command to run after become master, the interface name, virtual address + and optional extra parameters are passed as arguments. + ''; + example = '' + pkgs.writeScript "upscript" ''' + #!/bin/sh + $\{pkgs.iproute2\}/bin/ip addr add "$2"/24 dev "$1" + '''; + ''; + }; + + downscript = mkOption { + type = types.path; + description = '' + Command to run after become backup, the interface name, virtual address + and optional extra parameters are passed as arguments. + ''; + example = '' + pkgs.writeScript "downscript" ''' + #!/bin/sh + $\{pkgs.iproute2\}/bin/ip addr del "$2"/24 dev "$1" + '''; + ''; + }; + + deadratio = mkOption { + type = types.ints.unsigned; + description = "Ratio to consider a host as dead."; + default = 3; + }; + + shutdown = mkOption { + type = types.bool; + description = "Call downscript at exit."; + default = false; + }; + + ignoreIfState = mkOption { + type = types.bool; + description = "Ignore interface state, e.g., down or no carrier."; + default = false; + }; + + noMcast = mkOption { + type = types.bool; + description = "Use broadcast instead of multicast advertisements."; + default = false; + }; + + extraParam = mkOption { + type = types.nullOr types.str; + description = "Extra parameter to pass to the up/down scripts."; + default = null; + }; + + package = mkOption { + type = types.package; + description = '' + Package that should be used for ucarp. + + Please note that the default package, pkgs.ucarp, has not received any + upstream updates for a long time and can be considered as unmaintained. + ''; + default = pkgs.ucarp; + defaultText = "pkgs.ucarp"; + }; + }; + + config = mkIf cfg.enable { + systemd.services.ucarp = { + description = "ucarp, userspace implementation of CARP"; + + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + serviceConfig = { + Type = "exec"; + ExecStart = ucarpExec; + + ProtectSystem = "strict"; + ProtectHome = true; + PrivateTmp = true; + ProtectClock = true; + ProtectKernelModules = true; + ProtectControlGroups = true; + MemoryDenyWriteExecute = true; + RestrictRealtime = true; + }; + }; + }; + + meta.maintainers = with lib.maintainers; [ oxzi ]; +}