NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
18.28k stars 14.26k forks source link

In some cases, enabling networkd will break in-initrd network #157034

Open flokli opened 2 years ago

flokli commented 2 years ago

Describe the bug

I'm using in-initrd ssh to unlock disks. Previously, my system config was defaulting to the scripted networking and no explicit list of interfaces to DHCP from.

I enabled systemd-networkd on my server configuration, by adding the following block:

  # use networkd
  networking.useNetworkd = true;
  networking.useDHCP = false;
  systemd.network.networks = {
    "10-uplink" = {
      matchConfig = {
        Name = "en* eth*";
        Driver = "igb";
      };
      networkConfig.IPv6AcceptRA = false;
      address = [
        "xxx.xxx.xxx.xxx/32"
        "2a01:4f8:xxxx:xxxx::1/128"
      ];
      routes = [
        {
          routeConfig = {
            Gateway = "xxx.xxx.xxx.xxx";
            GatewayOnLink = true;
          };
        }
        {
          routeConfig = {
            Gateway = "fe80::1";
            GatewayOnLink = true;
          };
        }
      ];
    };
  };

I switched my system to this config, verified everything came up properly, and rebooted.

I noticed the in-initrd networking "stack" didn't come up. It didn't explicitly configure the addresses, and didn't do DHCP either.

This was a bit surprising.

Digging into nixos/modules/system/boot/initrd-network.nix, I remembered the following two lines:

  dhcpInterfaces = lib.attrNames (lib.filterAttrs (iface: v: v.useDHCP == true) (config.networking.interfaces or {}));
  doDhcp = config.networking.useDHCP || dhcpInterfaces != [];

Essentially, because we don't enable dhcp via the networking.useDHCP or networking.interfaces.*.useDHCP knobs, in-initrd dhcp is disabled, and as network configuration is set via systemd.network.networks, the in-initrd networking stack can't configure anything.

As a workaround, I dropped a dummy networking.interfaces.enp195s0.useDHCP = true; in my config, which is not pretty and very generic, but at least causes the in-initrd network stack to still do DHCP.

I feel like we should probably log a warning if no DHCP is enabled, no addresses configured, but boot.initrd.network.enable set to true.

In-initrd systemd (https://github.com/NixOS/nixpkgs/issues/72401) should probably fix this as well, as we could also run networkd in there.

(cc @Mic92 @kirelagin @ElvishJerricco @andir )

kevinboulain commented 1 year ago

Same here, but the following workaround appears to work and will not enable dhcpcd so I can keep using systemd-networkd (the OP was slightly different, so leaving that here for reference):

networking = {                                                                                                                                                                                                                 
  dhcpcd.enable = false;                                                                                                                                                                                                       
  useDHCP = true;                                                                                                                                                                                                  
};  

I assume #169116 will make that obsolete since the configuration appears to be shareable between stage 1 and 2.

ElvishJerricco commented 1 year ago

Yea, fwiw, you would be able to share networkd config between stage 1 and stage 2 with #169116. Although scripted initrd probably should have a knob for configuring which interfaces to set up, I don't know if we should bother when #169116 will let you just use networkd.

bouk commented 10 months ago

I ran into this, just to be clear, if I enable boot.initrd.systemd.enable = true then networking in initrd with networkd enabled should work, right?

just so others coming across this know what to do.

ElvishJerricco commented 10 months ago

@bouk The problem in this case is that interfaces are configured manually with systemd.network.networks, rather than with networking.interfaces. In the latter case, it would work with either scripted or systemd network. But if you just manually configure interfaces with NixOS's networkd options, then no, neither initrd implementation will automatically configure those interfaces. But, at least it's easier with systemd initrd, since you can just do boot.initrd.systemd.network = config.systemd.network;

SuperSandro2000 commented 5 months ago

But, at least it's easier with systemd initrd, since you can just do boot.initrd.systemd.network = config.systemd.network;

Why isn't this the default?

flokli commented 5 months ago

But, at least it's easier with systemd initrd, since you can just do boot.initrd.systemd.network = config.systemd.network;

Why isn't this the default?

Because networkd in initrd came later than networkd elsewhere, and doing do might have had the chance to break peoples' setups. We should go the deprecation warning approach, once all usecases are confirmed to work, or at least explored.

SuperSandro2000 commented 5 months ago

I know that if you are missing some kernel modules, eg. bridge or bonding https://gitea.c3d2.de/c3d2/nix-config/src/branch/master/modules/baremetal.nix#L18