wanderings/content/posts/arch-on-rpi.md

6.8 KiB

+++ title = "Arch on a Raspberry Pi - the basics" date = 2020-09-26 tags = ["raspberry pi"] toc = true +++ Installing Arch on a Raspberry Pi is amazingly easy. the Arch ARM project gives instructions for the basic installation here.

Chroot into the SD card

When you finished installing the basic system to the SD card, you may wish to install the following packages in your host system (we'll suppose your host system is already an Arch linux) : arch-install-script that provides the arch-chroot command, and qemu-user-static-bin, that provides the means to run ARM binaries from the host system. Then you can mount the SD card on e.g. /mnt and do :

# arch-chroot /mnt

arch-chroot will mount all useful mounts like /mnt/proc, /mnt/sys, /mnt/dev, and event /mnt/boot if it's in /mnt/etc/fstab. When you're done, it will clean everything and hopefully let you unmount the drive cleanly.

Setup SSH

Over there you can modify your target system, which provides a user named pi. You might use that or add a user. Make sure you set up ssh login credentials. If in doubt check Archlinux wiki's OpenSSh page ; I believe it's installed by default on archlinuxarm.

When you're done just hit Ctrl-d to unbind the chroot.

Networking

The tricky bit is to be able to log into it on a headless config. You will have to make sure it's reachable on the network so you can ssh into it. There are a few options here : if the RPi provides an ethernet plug, connect over ethernet. If not (as for the RPi zero series), connect with USB over ethernet. If you need (or crave) to connect wirelessly, the wifi leaves you options to either make it connect to your local network, or turn the RPi into a wifi hotspot.

Note that wireless networking does imply a certain overhead ; you might consider turning it off when in production use, specially when running JACK (I read it somewhere in a JACK tutorial page but I can't remember where).

Wired over USB

Skip this part if your RPi has an ethernet socket. Else chroot in the SD card. Add the following to /boot/cmdline.txt :

modules_load=dwc2,g_ether

Now into /boot/config.txt, add the following line :

dtoverlay=dwc2

This will let the system load an ethernet over USB module at boot-time. To have it setup at boot-time run :

# systemctl enable systemd-networkd

And create or edit /etc/systemd/network/01-usb.network so that it reads :

[Match]
Name=usb*

[Network]
LinkLocalAddressing=ipv4
IPv4LLRoute=yes

get out of the chroot, unmount the SD card and boot.

Wireless - connect to a local network

You will need the wpa_supplicant package, and a systemd service to launch it. Chroot into the SD card, and run as root :

# pacman -S wpa_supplicant

wpa_supplicant can be started by systemd-networkd : edit/create /etc/systemd/network/05-wlan.network with the following contents :

[Match]
Name=wlan*

# Run as a client with wpa_supplicant
[Network]
DHCP=ipv4
MulticastDNS=yes

Now edit or create /etc/wpa_supplicant/wpa_supplicant-wlan0.conf, and add your local network credentials. Refer to man wpa_supplicant.conf for details. The syntax is :

network={
    ssid="THE_NAME_OF_YOUR_ACCESS_POINT"
    psk="THE_ACCESS_POINT_PASSWORD"
}

systemd-networkd will start wpa_supplicant@wlan0.service, who will in turn use the latter config file to run. You can quit the chroot, unmount the SD card and boot it ; the system should connect to the local network at boot-time. You can add Access Points at run-time with the wpa_passphrase utility, like in :

wpa_passphrase AP_NAME AP_PASSWORD | sudo tee --append
/etc/wpa_supplicant/wpa_supplicant-wlan0.conf

Wireless - fallback to hotspot

It can be very handy to fall back to setting up an Access Point if we can't connect to any known network. This way you're still able to ssh back into the RPi and for instance register a new Access Point to connect to. This trick was derived from this post.

wpa_supplicant provides this feature with a rather ... cryptic manner ; see by yourself :

# AP configuration as a fallback :
network={
    ssid="RPi"
    mode=2
    priority=-999
    key_mgmt=WPA-PSK
    psk="a rather long raspberry pi password"
    frequency=2412
}

You just insert this snippet in /etc/wpa_supplicant/wpa_supplicant-wlan0.conf so that it gets loaded only if the other networks are not found. It doesn't have to sit in the bottom, so you can still append more attractive APs with wpa_passphrase. Even if you don't use the priority option, wpa_supplicant will be smart enough to load it only if no known host is found. The RPi Zero W doesn't do 802.11g, it's only capable of 802.11b, but you don't need to tell it, it will handle that. I actually tested all these options, because I couldn't find documentation on these features.

But it won't give you or your client an IP address - for this a DHCP server is needed. The RPi can act like one with the dnsmasq package, who will in turn require the interface to be setup with a static address. As stated in this StackExchange discussion, you can have several addresses on the same interface at the same moment. So in /etc/systemd/network/05-wlan0.network, append this line to the [Network] section :

Address=192.168.2.1/24

We just want dnsmasq to run if the RPi is in Access Point mode. Systemd can help here, you may add a conditional on dnsmasq.service's execution with the following snippet :

file: /etc/systemd/system/dnsmasq.service.d/only-if-we-are-an-AP.conf
# Insert a test that fails if the device is not an Access Point.
[Unit]
After=wpa_supplicant@wlan0.service

[Service]
ExecStartPre=/bin/sh -c 'eval $(wpa_cli -i wlan0 status) && test "$mode" == "AP"'

[Install]
WantedBy=wpa_supplicant@wlan0.service

If you want to know what it does, try sudo wpa_cli -i wlan0 status ; you'll see it outputs various informations about the network device, including its mode, with possible values AP and managed. The above test succeeds only if the interface is configured as an Access Point. And Systemd services fail if any of the ExecStartPre instructions fail. The drawback of this setup is that the service will simply appear as failed in journalctl, with no explanation.

Copy the snippet to the given location, reboot. If you can't ping the RPi on the local network, look for it in the available APs. Connect to it, ssh it. You're done !