Last active
February 15, 2026 19:34
-
-
Save alexhaydock/3a458b36ce79851f4576794e5f18e1d5 to your computer and use it in GitHub Desktop.
NixOS module to overlay latest NetworkManager with CLAT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # /etc/nixos/nm-clat.nix | |
| { config, pkgs, ... }: | |
| { | |
| # Use NetworkManager | |
| networking.networkmanager.enable = true; | |
| # Horrible hack to create a dispatcher to enable CLAT every time a connection | |
| # comes up since networkmanager.settings doesn't seem to accept settings that | |
| # only exist in the upstream dev branch | |
| # | |
| # Since this fires on `up` it probably only starts working after a disconnect | |
| # and reconnect rather than immediately | |
| networking.networkmanager.dispatcherScripts = [ { | |
| source = pkgs.writeText "upHook" '' | |
| if [ "$2" = "up" ]; then | |
| conn="$(${config.networking.networkmanager.package}/bin/nmcli -t -f NAME,DEVICE connection show | grep $1 | cut -d: -f1)" | |
| ${config.networking.networkmanager.package}/bin/nmcli connection modify "$conn" ipv4.clat auto | |
| ${config.networking.networkmanager.package}/bin/nmcli connection modify "$conn" ipv4.dhcp-ipv6-only-preferred yes | |
| fi | |
| ''; | |
| type = "basic"; | |
| } ]; | |
| # We need this to make nmcli available to the dispatcher scripts when they actually run | |
| # otherwise the scripts can't find the nmcli binary and error out | |
| systemd.services.NetworkManager-dispatcher = { | |
| enable = true; | |
| path = [ | |
| "${config.networking.networkmanager.package}/bin" | |
| ]; | |
| }; | |
| # Override NetworkManager with the latest commit from the Git HEAD | |
| # | |
| # I originally went with the commit which merged the original CLAT PR but there's | |
| # been a bunch of improvements merged since | |
| networking.networkmanager.package = pkgs.networkmanager.overrideAttrs (oldAttrs: let | |
| src = pkgs.fetchFromGitLab { | |
| domain = "gitlab.freedesktop.org"; | |
| owner = "NetworkManager"; | |
| repo = "NetworkManager"; | |
| rev = "871da67916cd86d6a99c32f8d47b413fd16d68c6"; | |
| hash = "sha256-PEWl0ZB9ok+kXQHDPd08Cp7iVCBdez66bbxx/nRY618="; | |
| }; | |
| # Patched version of the nixpkgs upstream fix-paths.patch for the udev rules | |
| # and some other files | |
| # | |
| # I removed a hunk from this that would no longer apply on the latest Git HEAD | |
| # so hopefully it wasn't needed lol | |
| nixosPathPatch = pkgs.writeText "fix-paths.patch" '' | |
| diff --git a/data/84-nm-drivers.rules b/data/84-nm-drivers.rules | |
| index 148acade5c..6395fbfbe5 100644 | |
| --- a/data/84-nm-drivers.rules | |
| +++ b/data/84-nm-drivers.rules | |
| @@ -7,6 +7,6 @@ ACTION!="add|change|move", GOTO="nm_drivers_end" | |
| # Determine ID_NET_DRIVER if there's no ID_NET_DRIVER or DRIVERS (old udev?) | |
| ENV{ID_NET_DRIVER}=="?*", GOTO="nm_drivers_end" | |
| DRIVERS=="?*", GOTO="nm_drivers_end" | |
| -PROGRAM="/bin/sh -c '/usr/sbin/ethtool -i $$1 |/usr/bin/sed -n s/^driver:\ //p' -- $env{INTERFACE}", ENV{ID_NET_DRIVER}="%c" | |
| +PROGRAM="@runtimeShell@ -c '@ethtool@/bin/ethtool -i $$1 |@gnused@/bin/sed -n s/^driver:\ //p' -- $env{INTERFACE}", ENV{ID_NET_DRIVER}="%c" | |
| LABEL="nm_drivers_end" | |
| diff --git a/src/libnmc-base/nm-vpn-helpers.c b/src/libnmc-base/nm-vpn-helpers.c | |
| index cbe76f5f1c..6ec684f9fe 100644 | |
| --- a/src/libnmc-base/nm-vpn-helpers.c | |
| +++ b/src/libnmc-base/nm-vpn-helpers.c | |
| @@ -284,15 +284,6 @@ nm_vpn_openconnect_authenticate_helper(NMSettingVpn *s_vpn, GPtrArray *secrets, | |
| const char *const *iter; | |
| const char *path; | |
| const char *opt; | |
| - const char *const DEFAULT_PATHS[] = { | |
| - "/sbin/", | |
| - "/usr/sbin/", | |
| - "/usr/local/sbin/", | |
| - "/bin/", | |
| - "/usr/bin/", | |
| - "/usr/local/bin/", | |
| - NULL, | |
| - }; | |
| const char *oc_argv[(12 + 2 * G_N_ELEMENTS(oc_property_args))]; | |
| const char *gw; | |
| int port; | |
| @@ -311,13 +302,8 @@ nm_vpn_openconnect_authenticate_helper(NMSettingVpn *s_vpn, GPtrArray *secrets, | |
| port = extract_url_port(gw); | |
| - path = nm_utils_file_search_in_paths("openconnect", | |
| - "/usr/sbin/openconnect", | |
| - DEFAULT_PATHS, | |
| - G_FILE_TEST_IS_EXECUTABLE, | |
| - NULL, | |
| - NULL, | |
| - error); | |
| + path = g_find_program_in_path("openconnect"); | |
| + | |
| if (!path) | |
| return FALSE; | |
| ''; | |
| nixosInstallPathPatch = pkgs.writeText "fix-install-paths.patch" '' | |
| diff --git a/meson.build b/meson.build | |
| index 61c025b9d7..d2ae60da34 100644 | |
| --- a/meson.build | |
| +++ b/meson.build | |
| @@ -1025,9 +1025,9 @@ meson.add_install_script( | |
| join_paths('tools', 'meson-post-install.sh'), | |
| nm_datadir, | |
| nm_bindir, | |
| - nm_pkgconfdir, | |
| + nm_prefix + nm_pkgconfdir, | |
| nm_pkglibdir, | |
| - nm_pkgstatedir, | |
| + nm_prefix + nm_pkgstatedir, | |
| nm_mandir, | |
| nm_sysconfdir, | |
| enable_docs ? '1' : '0', | |
| ''; | |
| in | |
| { | |
| name = "networkmanager"; | |
| inherit src; | |
| # Apply our patch, ensuring that some packages are available in the context | |
| # while we do it so their paths can be injected into the patch | |
| patches = [ | |
| (pkgs.replaceVars nixosPathPatch { | |
| runtimeShell = pkgs.stdenv.shell; | |
| ethtool = pkgs.ethtool; | |
| gnused = pkgs.gnused; | |
| }) | |
| nixosInstallPathPatch | |
| ]; | |
| # We need to patch the shebangs in that one script for Nix compatibility, | |
| # and also patch the meson.build for the bpf based CLAT to tell it where | |
| # to find our Linux Headers and some glibc header stuff | |
| postPatch = '' | |
| patchShebangs tools/create-exports-NetworkManager.sh | |
| sed -i "s|bpf_clang_flags = \[|bpf_clang_flags = ['-I${pkgs.linuxHeaders}/include', '-I${pkgs.glibc.dev}/include',|" src/core/bpf/meson.build | |
| ''; | |
| # Import some new packages we need to build the CLAT that aren't | |
| # already in the upstream default.nix - mostly this is clang stuff | |
| # to build the bpf code for the CLAT | |
| nativeBuildInputs = oldAttrs.nativeBuildInputs ++ [ | |
| pkgs.bpftools | |
| pkgs.clang.cc | |
| pkgs.cmake | |
| pkgs.libbpf | |
| pkgs.linuxHeaders | |
| pkgs.ethtool | |
| pkgs.gnused | |
| ]; | |
| }); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment