Skip to content

Commit

Permalink
systemd-initrd: Flush networkd
Browse files Browse the repository at this point in the history
  • Loading branch information
ElvishJerricco committed Apr 15, 2023
1 parent dfbe9a9 commit 0ff1545
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 2 deletions.
6 changes: 5 additions & 1 deletion nixos/modules/system/boot/initrd-network.nix
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,15 @@ in

boot.initrd.network.flushBeforeStage2 = mkOption {
type = types.bool;
default = true;
default = !config.boot.initrd.systemd.enable;
defaultText = "!config.boot.initrd.systemd.enable";
description = lib.mdDoc ''
Whether to clear the configuration of the interfaces that were set up in
the initrd right before stage 2 takes over. Stage 2 will do the regular network
configuration based on the NixOS networking options.
The default is false when systemd is enabled in initrd,
because the systemd-networkd documentation suggests it.
'';
};

Expand Down
33 changes: 33 additions & 0 deletions nixos/modules/system/boot/networkd.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3180,6 +3180,39 @@ let
];
kernelModules = [ "af_packet" ];

systemd.services.nixos-flush-networkd = mkIf config.boot.initrd.network.flushBeforeStage2 {
description = "Flush Network Configuration";
wantedBy = ["initrd.target"];
after = ["systemd-networkd.service" "dbus.socket" "dbus.service"];
before = ["shutdown.target" "initrd-switch-root.target"];
conflicts = ["shutdown.target" "initrd-switch-root.target"];
unitConfig.DefaultDependencies = false;
serviceConfig = {
# This service does nothing when starting, but brings down
# interfaces when switching root. This is the easiest way to
# ensure proper ordering while stopping. See systemd.unit(5)
# section on Before= and After=. The important part is that
# we are stopped before units we need, like dbus.service,
# and that we are stopped before starting units like
# initrd-switch-root.target
Type = "oneshot";
RemainAfterExit = true;
ExecStart = "/bin/true";
};
# systemd-networkd doesn't bring down interfaces on its own
# when it exits (see: systemd-networkd(8)), so we have to do
# it ourselves. The networkctl command doesn't have a way to
# bring all interfaces down, so we have to iterate over the
# list and filter out unmanaged interfaces to bring them down
# individually.
preStop = ''
networkctl list --full --no-legend | while read _idx link _type _operational setup _; do
[ "$setup" = unmanaged ] && continue
networkctl down "$link"
done
'';
};

})
];

Expand Down
34 changes: 33 additions & 1 deletion nixos/tests/systemd-initrd-networkd.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,23 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
name = "systemd-initrd-network";
meta.maintainers = [ lib.maintainers.elvishjerricco ];

nodes = {
nodes = let
mkFlushTest = flush: script: { ... }: {
boot.initrd.systemd.enable = true;
boot.initrd.network = {
enable = true;
flushBeforeStage2 = flush;
};
systemd.services.check-flush = {
requiredBy = ["multi-user.target"];
before = ["network-pre.target" "multi-user.target"];
unitConfig.DefaultDependencies = false;
serviceConfig.Type = "oneshot";
path = [ pkgs.iproute2 pkgs.iputils pkgs.gnugrep ];
inherit script;
};
};
in {
basic = { ... }: {
boot.initrd.network.enable = true;

Expand All @@ -29,11 +45,27 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
};
};
};

doFlush = mkFlushTest true ''
if ip addr | grep 10.0.2.15; then
echo "Network configuration survived switch-root; flushBeforeStage2 failed"
exit 1
fi
'';

dontFlush = mkFlushTest false ''
if ! (ip addr | grep 10.0.2.15); then
echo "Network configuration didn't survive switch-root"
exit 1
fi
'';
};

testScript = ''
start_all()
basic.wait_for_unit("multi-user.target")
doFlush.wait_for_unit("multi-user.target")
dontFlush.wait_for_unit("multi-user.target")
# Make sure the systemd-network user was set correctly in initrd
basic.succeed("[ $(stat -c '%U,%G' /run/systemd/netif/links) = systemd-network,systemd-network ]")
basic.succeed("ip addr show >&2")
Expand Down

0 comments on commit 0ff1545

Please sign in to comment.