[ home ] [ writings ]

Setting Up Alpine Linux Headlessly on a Raspberry Pi 3

[Networking] Posted May 6, 2026 12:09 UTC (Wed)

A guide to installing Alpine Linux on Raspberry Pi 3 in Diskless Mode without local peripherals, ensuring SSH access persists across reboots with multi-SSID configuration, and an SD card failover strategy for headless recovery.

Background

This project was prompted by the need to repurpose a Raspberry Pi 3B for a new development cycle requiring Linux-specific APIs. Having returned home post-graduation, I found the device’s original network credentials were outdated as my parents changed our WiFi provider.

Without local peripherals to manually reconfigure the interface, I needed a deployment strategy that prioritized automated networking and remote accessibility. This also gave me an opportunity to select a headless distribution due to the fact that I rarely use the GUI.

Why Alpine?

Alpine's diskless mode runs the OS entirely from RAM, and SD cards last much longer when they're rarely written to. It's footprint is also very small, making it perfect for programming on the Raspberry Pi.

First Boot with Headless Bootstrap

Write an Alpine Linux Pi image to your SD card. Then download headless.apkovl.tar.gz from macmpi/alpine-linux-headless-bootstrap and place it on the boot partition alongside a wpa_supplicant.conf with your WiFi credentials:

ctrl_interface=/var/run/wpa_supplicant
ctrl_interface_group=wheel
update_config=1

network={
    ssid="YourNetwork"
    psk="yourpassword"
}

Boot the Pi and wait about 10–20 seconds. The bootstrap script connects to WiFi and starts a temporary SSH server with no password. Find the IP from your router or with:

sudo arp-scan -lI en0

SSH in as root, then remove the bootstrap overlay so it doesn't run again:

mount -o remount,rw /media/mmcblk0p1
rm /media/mmcblk0p1/headless.apkovl.tar.gz
mount -o remount,ro /media/mmcblk0p1

setup-alpine

Run setup-alpine and work through the prompts.

Use wlan0 for the network interface.

You should create a user profile and prevent root logins as well. Root will be accessible through doas.

Set the hostname in the running session too, since setup-alpine only sets it for future boots:

hostname yourshortname

Commit everything to the overlay:

lbu add /etc/ssh
lbu commit -d
apk cache sync

In diskless Alpine, lbu commit is how changes survive reboot. Without it, nothing is persisted.

Before rebooting, restart sshd and verify you can still connect:

rc-service sshd restart

Note: restarting sshd regenerates the host keys. Your SSH client will refuse the connection citing a key mismatch, so delete the old entry from ~/.ssh/known_hosts first.

WiFi Fallback Networks

If your primary WiFi changes and you have no physical access to the Pi, a fallback network (a phone hotspot works well) keeps SSH reachable. wpa_supplicant supports multiple networks natively, connecting to whichever is available, preferring higher priority values:

# /etc/wpa_supplicant/wpa_supplicant.conf
country=US
ctrl_interface=/var/run/wpa_supplicant
ctrl_interface_group=wheel
update_config=1

network={
    ssid="YourMainNetwork"
    psk="mainpassword"
    priority=10
}

network={
    ssid="YourHotspot"
    psk="hotspotpassword"
    priority=5
}

The header lines are required. Without ctrl_interface and update_config, wpa_supplicant may not parse the file. The country code matters for hotspots — some channels are restricted by region.

If an SSID contains an apostrophe (common in iPhone hotspot names), encode it as hex to avoid parse errors:

echo -n "Someone's iPhone" | xxd -p | tr -d '\n'

Use the hex output as the ssid value without quotes:

network={
    ssid=536f6d656f6e657320694f70686f6e65
    psk="hotspotpassword"
    priority=5
}

Commit after editing:

lbu commit -d

Recovering via SD Card

If you lose SSH access entirely, you can edit the overlay directly. The boot partition is FAT32 and mounts automatically on a Mac. The overlay is hostname.apkovl.tar.gz:

mkdir ~/apkovl
cd ~/apkovl
tar xzf /Volumes/ALPINE/pi.apkovl.tar.gz

vim etc/wpa_supplicant/wpa_supplicant.conf

dot_clean /Volumes/ALPINE/
tar czf /Volumes/ALPINE/pi.apkovl.tar.gz .
dot_clean /Volumes/ALPINE/
diskutil eject /dev/disk2

To verify the tarball contains your edits before ejecting:

tar xOf /Volumes/ALPINE/pi.apkovl.tar.gz \
  etc/wpa_supplicant/wpa_supplicant.conf

Pitfalls

Mac Resource Fork Files

macOS creates ._filename metadata files on FAT32 volumes. Alpine picks the first .apkovl.tar.gz alphabetically, so ._pi.apkovl.tar.gz sorts before pi.apkovl.tar.gz and will be loaded instead of yours. Always run dot_clean /Volumes/ALPINE/ after repacking and before ejecting.

5GHz WiFi

The Pi 3 is 2.4GHz only. If you configure an SSID running 5GHz, the Pi will never connect.