line34
Coding, Scripting, Administration

NATural selection

Switching NAT interfaces on NixOS less painfully

One thing that bothered me when working with containers in NixOs is that I had to change my system configuration file when switching from wifi to ethernet or back and then run nixos-rebuild in order to keep NAT (network address translation) and therefore internet access working. I would have something like this in my config:

    nat.enable = true;
    nat.internalInterfaces = ["ve-+"];
    nat.externalInterface = "wlp3s0";

That was fine as long as I was on wifi. But every time I switched to ethernet I had to open the configuration file, find the correct spot, enter the ethernet interface name, save and run nixos-rebuild. So I pulled out the external interface name into its separate file:

    nat.enable = true;
    nat.internalInterfaces = ["ve-+"];
    nat.externalInterface = pkgs.lib.removeSuffix "\n" (builtins.readFile ./nat_if);

builtins.readFile will get the contents of the given file. They will be treated as if they had been given as a literal string. pkgs.lib.removeSuffix "\n" will ignore any newline character after the interface name.

Now it's enough to do something like

echo "enp0s31f6" > ./nat_if

and then run nixos-rebuild. And with a little shell script it comes down to one command, and I don't even have to type the interface name:

FILE=/pat/to/nat_if;
ETH="enp0s31f6"
WIFI="wlp3s0"

FROM_IF=$(cat $FILE);
if [[ $1 == "" ]]; then
    if [[ $FROM_IF == $WIFI ]]; then
        TO_IF=$ETH;
    else
        TO_IF=$WIFI;
    fi
else
    TO_IF=$1;
fi
echo "Switching from $FROM_IF to $TO_IF"
echo "Enter to continue"
read

echo $TO_IF > $FILE;
sudo nixos-rebuild switch;

It still takes a little longer than I'd like, but it's a lot smoother than before, and it was fun to hack up.

7th March 2019Filed under: NixOS   shell   network   containers   scripts   bash