Chris Dzombak

sharing preview • dzombak.com

Maintaining a solid WiFi connection on Raspberry Pi

The first issue you're likely to hit with a long-running Pi, particularly with a Raspberry Pi Zero, is the Pi dropping off your WiFi network for no apparent reason after days or just hours of operation.

Maintaining a solid WiFi connection on Raspberry Pi

Part of the Raspberry Pi Reliability series.

The first issue you’re likely to hit with a long-running Pi, particularly with a Raspberry Pi Zero, is the Pi dropping off your WiFi network for no apparent reason after days or just hours of operation.

The information in this post is, to the best of my knowledge, current as of November 2023. It should work on Raspberry Pi OS versions bullseye and bookworm, at least, but I make no promises.

Monitoring for this problem

Fortunately, this is one of the easiest problems to watch for. Tell your favorite monitoring software — I use Uptime Kuma at home — to ping the Pi on a regular basis and alert you if it stops responding for more than a couple minutes.

The Pi will need to have a static IP, DHCP reservation, or a consistent name (maybe a .local name, via mDNS) to use for monitoring.

Possible causes

I’ll briefly note a few possible causes:

Fixes

These fixes are not without risk, and you should only use any given intervention if you understand it and what it will do. (See my Pi Reliability post on risk vs. benefits.)

The wifi-check script

This feels like a hack, but based on hours of reading online discussions, most people seem to settle on a script that periodically checks whether the WiFi connection is good, and restarts the WiFi interface or the whole Pi if it’s not.

I’ve written what I think is the best possible version of this hack: my wifi-check.sh script starts by disabling the WiFi chip’s low power mode, then checks to see if that worked, and escalates from there to more extreme measures.

You can grab the latest version of the script from my dotfiles repository. Place it at /usr/local/bin/wifi-check.sh, or wherever you prefer.

When scheduling it to run, it’s important to use flock to ensure there’s only ever a single copy of the script running. I schedule it by placing the following content at /etc/cron.d/wifi-check:

*  *  *  *  *  root  flock -x -n -E 0 /tmp/wifi-check.lock env PING_TARGET=192.168.1.1 WLAN_IF=wlan0 /usr/local/bin/wifi-check.sh

Note that if this script reboots the machine while you're performing maintenance or upgrades, your Pi could be left in a broken state. Disable this cron job before doing any risky maintenance.

To reduce the risk of this intervention, I also disable automatic updates; see this post on disabling/removing unneeded software.

The watchdog

The Raspberry Pi’s little-known watchdog feature can monitor a network interface and reboot the Pi if … something bad happens? I haven’t been able to figure out exactly what about the interface it watches for, but I’m enabling this feature on my Pi Zeros, figuring it can’t hurt.

After setting up the watchdog — for which I’ll refer you to my Pi Reliability post on hardware/firmware issues — you can tell it to watch your WiFi interface by adding the following line to /etc/watchdog.conf:

interface = wlan0

The watchdog also has a “ping mode,” but I think my wifi-check script is a much more graceful and customizable way to handle ping failures. See watchdog.conf(5) for more.

Disable client steering on your WiFi network

Anecdotally, I think disabling the client steering feature on my Eero home network helped my Pi Zeros stay online more consistently. I don’t have enough data to say this definitively, though.

Disabling other “advanced” WiFi features, especially those that try to encourage clients to switch WiFi bands or access points, may help too.

Disable IPv6 on the Pi

This is unlikely to do anything unless you’re hitting some unusual bug, but it’s worth noting that IPv6 has, in the past, led to all sorts of strange behaviors in different networking contexts. (Disabling IPv6 on a device that lives on your home WiFi network is also unlikely to break anything.)

You can try disabling IPv6 by writing this to the file /etc/sysctl.d/90-disable-ipv6.conf, then rebooting:

net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

See Also: Considerations for a long-running Raspberry Pi.