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

182 lines
6.8 KiB
Markdown
Raw Normal View History

2020-10-08 23:07:35 +02:00
+++
title = "Arch on a Raspberry Pi - the basics"
date = 2020-09-26
2020-10-15 00:06:47 +02:00
tags = ["raspberry pi"]
2020-10-08 23:07:35 +02:00
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