182 lines
6.8 KiB
Markdown
182 lines
6.8 KiB
Markdown
|
+++
|
||
|
title = "Arch on a Raspberry Pi - the basics"
|
||
|
date = 2020-09-26
|
||
|
tags = ["admin"]
|
||
|
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
|