I have a lot of Raspberry Pi Zeros. Most of them are spread across various basement growth chambers at the University of Arizona. They run sensors that monitor heat and humidity inside the chambers and upload the data to the cloud for visualization in a Shiny app. To keep costs down, I run the Pi’s headless, meaning no monitor, mouse, or keyboard. This works fine at home, where I can easily add the network name and password to the /etc/wpa_supplicant/wpa_supplicant.conf
file by directly editing it on the SD card before I plug it into the Pi, as described in the Raspberry Pi docs:
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
country=US
update_config=1
network={
ssid="<Name of your wireless LAN>"
psk="<Password for your wireless LAN>"
}
However, when I try to do the same thing on campus, I quickly run into problems. When you connect to the University of Arizona wifi you have to click through a series of screens where you enter your username and password. This doesn’t work on a headless Pi. Fortunately, with the right configuration files you can still get through. I got the following network configurations from campus IT: “Phase II authentication: MCSCHAPV2, EAP method: PEAP, Certificate: do not validate, Anonymous Identity: leave blank.” Combining this info with directions from this blog post allowed me to complete the configuration.
First, edit the /etc/wpa_supplicant/wpa_supplicant.conf
file as follows:
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=US
network={
ssid="UAWiFi"
priority=1
proto=RSN
key_mgmt=WPA-EAP
pairwise=CCMP
auth_alg=OPEN
eap=PEAP
identity="insert_username_here"
password=hash:insert_hashed_password_here
phase1="peaplabel=0"
phase2="auth=MSCHAPV2"
}
Note that this time we’ll be responsible and not store our password in plain text. To hash your password, use this command:
echo -n 'password_in_plaintext' | iconv -t utf16le | openssl md4
Next, edit one more file, /etc/network/interfaces
. If you don’t have this file, you’ll need to create one. The file should read:
# interfaces(5) file used by ifup(8) and ifdown(8)
# Please note that this file is written to be used with dhcpcd
# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'
# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d
auto lo
iface lo inet loopback
iface eth0 inet dhcp
allow-hotplug wlan0
iface wlan0 inet dhcp
pre-up wpa_supplicant -B -Dwext -i wlan0 -c/etc/wpa_supplicant/wpa_supplicant.conf
post-down killall -q wpa_supplicant
And that’s it! Except for one small thing. It looks like the University of Arizona has decided to block whichever port Network Time Protocol (NTP) uses (I think port 123), causing the Raspberry Pi to not know what time it is. You can check this after you connect your Pi to the network by printing the current time with date
and the checking status of NTP with sudo systemctl status --no-pager systemd-timesyncd
. This can be a big problem if you are, for example, recording the system time along with your sensor readings. To get around this, I installed htpdate
with the following command:
sudo apt-get install htpdate
htpdate
will “synchronize your computer’s time by extracting timestamps from HTTP headers found in web server responses,” eliminating the need to access special ports. The downside is that it’s not as accurate as NTP, but the <1 second accuracy is good enough for my projects.
In writing this post I came across this page from the University of Arizona. They describe a wpa_supplicant
configuration for Raspberry Pi/Linux that might also work. Full disclosure: I’m not even close to being an expert at these things. I have tested my method using Raspberry Pi OS Lite kernel version 5.10. Good luck!