Running NetworkManager in initrd

No, I never got NetworkManager working in initrd. It is quite a shame because I wanted to standardize a networking stack on all my wireless devices. However, I easily got wifi working with wpa_supplicant which doesn’t need dbus. I ssh into my server remotely with yggdrasil and decrypt it. Yggrasil is basically an overlay network halfway between Tailscale and TOR. So this solution probably would work for Tailscale. To get yggdrasil working I am using a binary called “yggstack” which is not in nixpkgs, so that is why you see me making my own systemd service.

Here is my current initrd.nix:

{
  config,
  lib,
  pkgs,
  ...
}:

{
  boot.loader.grub.configurationLimit = 25;

  boot.initrd =
    let
      hostname = "argon";

      yggScript = pkgs.writeShellApplication {
        name = "yggscript";
        runtimeInputs = [ pkgs.yggstack ];
        text = ''
          #!/usr/bin/env bash
          yggstack -useconffile /yggstack.conf -remote-tcp 5123:127.0.0.1:5123
        '';
      };

    in
    {

      services.udev.rules = config.services.udev.extraRules;

      availableKernelModules = [
        "ccm"
        "ctr"
        "iwlmvm"
        "iwlwifi"
      ];

      secrets = {

        "/yggstack.conf" = "/run/secrets/yggstack-ssh-initrd.conf";

        "/ssh-hostkey" = config.sops.secrets."initrd-ssh-host-key".path;

        "/etc/wpa_supplicant/wpa_supplicant-zl_wifi0.conf" =
          config.sops.secrets."initrd_wpa_supplicant.conf".path;

      };

      systemd.network = {
        enable = true;
        networks."10-eth" = {
          matchConfig.Name = "zl_eth0";
          networkConfig.DHCP = "yes";
        };

        networks."10-wifi" = {
          matchConfig.Name = "zl_wifi0";
          networkConfig.DHCP = "yes";
        };

      };

      systemd.users.root.shell = "/bin/systemd-tty-ask-password-agent";
      network.enable = true;

      network.ssh.enable = true;
      network.ssh.port = 5123;

      #This will get copied into the nix store, but it is just a public key
      network.ssh.authorizedKeyFiles = [ "${config.zl.secrets.secretsPath}/clear/zach_authorized_keys" ];

      network.ssh.ignoreEmptyHostKeys = true;

      #For whatever reason "network.ssh.hostKeys" makes sops not work, so i set ignoreempyhostkeys and set the HostKey in "network.ssh.extraConfig"
      network.ssh.extraConfig = "HostKey /ssh-hostkey";

      systemd = {

        enable = true;

        initrdBin = [
          pkgs.busybox
          pkgs.yggstack
          yggScript
          pkgs.wpa_supplicant
        ];

        packages = [ pkgs.wpa_supplicant ];

        extraBin.yggstack = "${pkgs.yggstack}/bin/yggstack";

        services."wpa_supplicant@".unitConfig.DefaultDependencies = false;
        services."wpa_supplicant".unitConfig.DefaultDependencies = false;
        services."wpa_supplicant@".enable = true;

        services."sshd".unitConfig.WantedBy = [
          "systemd-cryptsetup@argon_zfs_root_1.service"
          "systemd-cryptsetup@argon_zfs_root_2.service"
        ];
        services."sshd".unitConfig.Before = [
          "systemd-cryptsetup@argon_zfs_root_1.service"
          "systemd-cryptsetup@argon_zfs_root_2.service"
        ];
        services."sshd".unitConfig.Wants = [ "wpa_supplicant@zl_wifi0.service" ];
        services."sshd".unitConfig.After = [ "wpa_supplicant@zl_wifi0.service" ];
        services."sshd".unitConfig.DefaultDependencies = false;

        targets."initrd".unitConfig.Wants = [ "yggstack-ssh-gate-initrd.service" ];

        services."yggstack-ssh-gate-initrd" = {
          enable = true;
          description = "Expose SSH to Yggdrasil Network";
          unitConfig.DefaultDependencies = false;
          serviceConfig = {
            Type = "simple";
            RemainAfterExit = "yes";
            ExecStart = "${yggScript}/bin/yggscript";
          };
        };
      };
    };
}

And in order to rename my wifi card to “zl-wifi0” I added some udev rules in a different file. Of course you will have to manually add the driver of your wifi card here for it to work:

services.udev.extraRules = ''
    SUBSYSTEMS=="pci", ACTION=="add", DRIVERS=="iwlwifi", NAME="zl-wifi%n"

    SUBSYSTEMS=="pci", ACTION=="add", DRIVERS=="e1000|e1000e|r8169", NAME="zl-eth%n"
  '';

My config is kind of bloated, I just threw stuff against the wall until something worked and didn’t really delete the extra stuff, so you can probably delete a lot of it and it will still work for you.

But for anyone reading I am really still looking for NetworkManger in initrd, bare wpa_supplicant is only a temporary solution for me.