NetworkManager is bloat
Or how I came to love dhcpcd
and iwd
for all of my networking needs...
Background§
I have a weird fascination with running as little software as possible on my machines.
For whatever reason, minimizing RAM usage scratches some weird itch of mine. And no, it's not infected. At least, I hope not...
Anyways, after watching a video on installing Arch Linux for fun (don't judge me), the presenter Ermanno (who's videos I VERY HIGHLY RECOMMEND) covered a change to the install process that Arch Linux made recently.
Or I suppose a more accurate description is a change that Arch Linux made to how to connect to a wireless network when you're installing. Keep in mind that the standard Arch Linux install process doesn't have a GUI or any desktop environment with a graphical installer. There's no comfy icon to click on to configure networking, nothing.
Out of curiousity, I started looking into this new replacement sofware - iwd
.
Once I started falling down that rabbit hole, I discovered just how unnecessary NetworkManager
is in my setup.
Why this works for me§
Like I said, I run a minimal setup. This means I don't need nor want big fancy GUI's for my tools.
To give an example, I run:
- A tiling window manager (i3, bspwm, sway, river are all on regular rotation...)
- A CLI or ncurses-UI for connecting to wifi (this was
nmtui
when I was usingNetworkManager
). - A CLI VPN with no visual feedback or need to graphically configure said VPN.
- I don't connect to esoteric modems like PPPOE, etc from my laptop or desktop.
With all this in mind, all of the "extra" features (read: bloat) of NetworkManager
mean that I'm paying a pretty steep cost in terms of dependencies and memory usage for things I simply don't need.
Note that there are some GUI tools for
dhcpcd
andiwd
at this point, so check those out on the Arch Wiki if you're really curious.
How to make the change§
If you want to make the change yourself, it's actually pretty easy. I recommend doing things in this order, because if you can't get iwd/dhcpcd to work to your liking, it's trivial to go back to NetworkManager
.
Install iwd and dhcpcd (and openresolv)§
We need all three applications. In short, dhcpcd
handles the DHCP handshake (and thus giving you an IP address) when a connection is established, like plugging in an ethernet cable or connecting to a wifi network with iwd
. As stated iwd
handles wireless connections, that's it.
Lastly, openresolv
(a resolvconf
implementation) handles the DNS configuration (mostly the maintenance of your /etc/hosts
file). dhcpcd
works with openresolv
automatically, you can read its documentation for more details.
I did mess around with using systemd-resolvd to have one less dependency, but ran into several issues with DNS configuration reliability. Just use
openresolv
and you'll be much happier.
On Arch, I installed all necessary software with pacman like so:
# pacman -S iwd dhcpcd openresolv
Disable NetworkManager and wpa_supplicant§
Now that you've downloaded the necessary software, you've got to shutdown NetworkManager
and wpa_supplicant
to prevent conflicts between the two sets of software.
# systemctl stop NetworkManager wpa_supplicant
Note: Obviously, you'll lose internet at this point.
Start iwd and dhcpcd§
With NetworkManager
and its wireless sidekick taken care of, spin up iwd and dhcpcd.
# systemctl start iwd dhcpcd
Wifi setup§
dhcpcd
handles all wired connections automatically, so if you're already connected with an ethernet cable you're done.
But, if you need to connect to a wireless network (as I'd wager 99.99% of people reading this do...), you'll need to configured iwd
to know about your wireless network.
To do so you can use the delightful companion for iwd - iwctl
.
You can run iwctl
directly, type help
, and then follow the corresponding documentation. Alternatively, you can pass all of your commands directly to iwctl
, as I demonstrate at the end of this section.
In my case, I simply needed to type the following:
$ iwctl
[iwd]# device list
wlan0 ...
I simply wanted to ensure that a wireless device was recognized, and it was. This isn't actually required to connect to an access point.
[iwd]# station wlan0 scan
Wait a few seconds as iwd looks up all the networks in your area...
[iwd]# station wlan0 connect "MyNetworkName"
Enter password when prompted and wait ~10 seconds to ensure you don't get an error back. If you do, you likely mistyped your password or your wifi is on the fritz.
Note that you can press
Tab
to autocomplete pretty much all commands, including the wireless name above.
[iwd]# quit
Exit out of the application.
Note that instead of using the iwctl
REPL, you can just feed the associated commands directly to iwctl
, like so:
$ iwctl station wlan0 connect "MyNetworkName"
I do like the REPL, as it holds your hand (if necessary), supports tab completion and just feels polished. Use whatever method you prefer.
Ensure you've got an IP address§
You may need to wait a few seconds as iwd
and dhcpcd
do their corresonding thaaangs, but you should receive an IP address that looks somewhat familiar. You can check this with the ip
command.
$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 60:e1:86:87:bc:89 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.217/24 brd 192.168.1.255 scope global dynamic noprefixroute wlan0
valid_lft 33914sec preferred_lft 28514sec
inet6 fd22:f6c3:4e66::a7e/128 scope global dynamic noprefixroute
valid_lft 35181sec preferred_lft 35181sec
inet6 2600:6c52:7b00:55aa::a7e/128 scope global dynamic noprefixroute
valid_lft 35181sec preferred_lft 35181sec
inet6 fd22:f6c3:4e66:0:dcb8:7af:18a1:8bd9/64 scope global mngtmpaddr noprefixroute
valid_lft forever preferred_lft forever
inet6 2600:6c52:7b00:55aa:9af:4ba4:ee9b:d32d/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 573699sec preferred_lft 573699sec
inet6 fe80::1f0:1103:da4d:ee9b/64 scope link
valid_lft forever preferred_lft forever
While that might seem like a wall of text, the 192.168.1.217
under wlan0
is what I'm looking for and tells me that I'm properly connected to my home network.
You can confirm network + DNS connectivity with a simple:
$ ping austindw.com
Or use google.com, whatever you want...
If everything looks good, you can make the switch permanent:
# systemctl enable dhcpcd iwd
# systemctl disable NetworkManager wpa_supplicant
Reboot, and you should come up with a perfectly working internet connection.
How to revert§
If you run into issues and you want to switch back, simply do:
# systemctl disable --now dhcpcd iwd
# systemctl enable --now NetworkManager wpa_supplicant
This will immediately stop dhcpcd
and iwd
, then start NetworkManager
and wpa_supplicant
. With these commands, you'll even be safe to reboot and still use NetworkManager
.
Results§
"But Austin, I just replaced two networking programs with two more networking programs, how is this an improvement?"
Good question - if you measure the RAM usage before and after the switch, you should notice around a ~20MB reduction with the exact same end result.
Additionally, my wireless connections were much more stable with iwd
than with NetworkManager
. I used to have frequent disconnect/reconnect storms when I placed a decent amount of load on my wifi connection. I never quite tracked down the root cause, but the broader stroke of just replacing NetworkManager
completely has yielded a much improved networking experience.
So I have less resource usage, and an extremely stable wireless network connection.
I'm never going back to NetworkManager
if I can help it.
Hopefully this has helped convert you. Give it a try, and you just might be sold on the iwd
+ dhcpcd
power couple for life.