Bootstrap Arch on Raspberry Pi with only a Wifi dongle

Installing Arch on the Raspberry Pi is rather simple and well documented. There is an offline step, where you copy a base system on the SD card. Then, you place the card in the Raspberry Pi, boot it and you log into that new system somehow, to finish the configuration and start customizing. “Somehow” is either: you plug a keyboard and a screen to the Raspberry Pi and work within the console, or: you plug the Raspberry Pi to your router/computer through an Ethernet cable and log in over SSH. But what if all you have is a Wifi dongle?

Install Arch Linux on the SD Card

Let’s start with the basics. Download the Arch image for the Raspberry Pi and plug the SD card to your computer. You can follow the official installation instructions (under the “Installation” tab), but I propose a slightly different way of doing. I mount the boot partition at the right place before extracting, so that there is no need to move the boot files afterwards. For the sake of completeness, here is the modified procedure:

  1. Start fdisk to partition the SD card:
fdisk /dev/sdX
  1. At the fdisk prompt, delete old partitions and create a new one:
    • Type o. This will clear out any partitions on the drive.
    • Type p to list partitions. There should be no partitions left.
    • Type n, then p for primary, 1 for the first partition on the drive, press ENTER to accept the default first sector, then type +100M for the last sector.
    • Type t, then c to set the first partition to type W95 FAT32 (LBA).
    • Type n, then p for primary, 2 for the second partition on the drive, and then press ENTER twice to accept the default first and last sector.
    • Write the partition table and exit by typing w.
  2. Create the file systems
mkfs.vfat /dev/sdX1 mkfs.ext4 /dev/sdX2
  1. Mount the filesystems in the same hierarchy as they should be on the Pi
mkdir root mount /dev/sdX2 root mkdir root/boot mount /dev/sdX1 root/boot
  1. Extract the base system
bsdtar -xpf ArchLinuxARM-rpi-latest.tar.gz -C root sync
  1. Do not unmount yet!

Installing Required Packages

Moving on to something more interesting. We are going to prepare the system offline, so that it connects to the wifi network when booting. We will use netctl, which is already installed, but we will also need wpa_supplicant to access secure networks. Unfortunately, this package isn’t included by default and we must install it. For this, we need to configure pacman to operate on the SD card and use the proper mirrors and architecture. The easiest is to tweak the pacman.conf file of the Raspberry Pi. In the below instructions, I mounted the Pi’s root partition onto /tmp/root. Change this if yours is different.

cp /tmp/root/etc/pacman.conf pacman.armv6h.conf

Then, edit the file to change all the necessary paths and options [full file here]:

#
# GENERAL OPTIONS
#
[options]
# The following paths are commented out with their default values listed.
# If you wish to use different paths, uncomment and update the paths.
RootDir     = /tmp/root
DBPath      = /tmp/root/var/lib/pacman/
CacheDir    = /tmp/root/var/cache/pacman/pkg/
LogFile     = /tmp/root/var/log/pacman.log
GPGDir      = /tmp/root/etc/pacman.d/gnupg/
HoldPkg     = pacman glibc
#XferCommand = /usr/bin/curl -C - -f %u > %o
#XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u
#CleanMethod = KeepInstalled
#UseDelta    = 0.7
Architecture = armv6h
# The testing repositories are disabled by default. To enable, uncomment the
# repo name header and Include lines. You can add preferred servers immediately
# after the header, and they will be used before the default mirrors.

[core]
Include = /tmp/root/etc/pacman.d/mirrorlist

[extra]
Include = /tmp/root/etc/pacman.d/mirrorlist

[community]
Include = /tmp/root/etc/pacman.d/mirrorlist

[alarm]
Include = /tmp/root/etc/pacman.d/mirrorlist

[aur]
Include = /tmp/root/etc/pacman.d/mirrorlist

Now you can use pacman to install wpa_supplicant, using the modified configuration file.

pacman --config pacman.armv6h.conf -S wpa_supplicant

My dongle — an Edimax USB dongle — works out-of-the-box (8192cu). However, if your dongle needs extra drivers, you can install the corresponding packages too, as long as they do not have an install script.

Configuring netctl

Step 1: the easy part. Well… kind of… Go to root/etc/netctl and copy one of the example profiles that suits your need. I will name the profile MyNet, you can replace this if you wish.

cp examples/wireless-wpa MyNet

Then, edit the file to configure the network, like you normally would. Note that, at the moment, the Wifi interface still receives the traditional name wlan0, instead of  a typical persistent name from systemd (e.g. wlp2s0).

Description='MyNet Configuration'
Interface=wlan0
Connection=wireless

Security=wpa
IP=dhcp

ESSID='MyNet'
Key=\"e631c3058388d716ba3693eae6e5607131d32c09c0a9e6441ebe0b26a8b5f560

Step 2: the tricky part. Kind of… We need to enable this configuration, which is usually just the matter of a netctl enable MyNet. But without systemd running, we need to do the work by hand. Change to root/etc/systemd/system. There, create the file netctl@MyNet.service and place the following content inside

.include /usr/lib/systemd/system/netctl@.service

[Unit]
Description=MyNet Configuration
BindsTo=sys-subsystem-net-devices-wlan0.device
After=sys-subsystem-net-devices-wlan0.device

Finally, activate the service at boot. This is done by creating a symlink inside the directory that lists all the dependencies for the multi-user target:

cd multi-user.target.wants/
ln -s '/etc/systemd/system/netctl@MyNet.service'

Note: It isn’t a failure that the link path starts with /etc and points to nowhere on our host system. The symlink must point to the path as it will be on the target.

Now, you can unmount the card and boot your Raspberry Pi.

umount root/boot
umount root

Finding The Pi

Of course, the easiest way to find your Pi, would be to have a proper internal DNS resolver. The default hostname is alarmpi, and you then just need to boot the Pi, wait a little and

ssh alarm@alarmpi

If all you get is a ssh: Could not resolve hostname alarmpi: Name or service not known even after some time, then you’ll have to find the Pi’s IP address manually. Several methods are helpful there.

If you can log into your router, just call

# arp
Address                  HWtype  HWaddress           Flags Mask            Iface
192.168.10.98            ether   28:b2:bd:4d:a5:5d   C                     br0
192.168.5.3              ether   00:1c:28:29:be:55   C                     wan0
192.168.10.85            ether   f4:6d:04:ac:f3:e7   C                     br0
192.168.10.79            ether   74:da:38:58:7e:de   C                     br0

to get the list of connected devices.

RaspWiresharkDiscover

Else, you could catch the DHCP discovery call, when the Pi is booting, by listening to your Wifi using e.g. Wireshark.

Finally, you could scan your network with nmap, but you will have to be clever, as the Pi is rather silent by default (somehow avoids nmap host discoveries).

# nmap -sT -Pn -p 22 --open 192.168.10.0/24

Starting Nmap 6.47 ( http://nmap.org ) at 2015-11-23 00:30 CET
Nmap scan report for 192.168.10.1
Host is up (0.0049s latency).
PORT   STATE SERVICE
22/tcp open  ssh

Nmap scan report for 192.168.10.79
Host is up (0.0050s latency).
PORT   STATE SERVICE
22/tcp open  ssh

Nmap scan report for 192.168.10.85
Host is up (0.012s latency).
PORT   STATE SERVICE
22/tcp open  ssh

Nmap done: 256 IP addresses (256 hosts up) scanned in 1.46 seconds

You’re now just a ssh alarm@192.168.10.79 away from having fun!

Featured Image Credits: Sergey Pozhilov / FreeImages.com and the Raspberry Pi Logo