+++ 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][aw-arm-install]. ## 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][aw-ssh] ; 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 : ``` systemd [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 : ``` systemd [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 : ``` wpa-supplicant 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][replace-hostapd]. `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][se-static-addr], 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 ``` systemd # 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 ! [aw-arm-install]: https://archlinuxarm.org/platforms/armv6/raspberry-pi [aw-ssh]: https://wiki.archlinux.org/index.php/OpenSSH [replace-hostapd]: https://raspberrypi.stackexchange.com/questions/94970/replacing-hostapd-with-wpa-supplicant [se-static-addr]: https://unix.stackexchange.com/questions/308944/systemd-networkd-default-static-address-if-dhcp-fails