Alpine on RPI1B - hpaluch/hpaluch.github.io GitHub Wiki
Installing Alpine Linux on Raspberry PI 1.B
Alpine Linux (Alpine) is fastest Linux on x86 architecture I know (thanks to not using systemd, using musl instead of glibc and single busybox binary for base system commands).
So it is natural to try it on RPi - I have old model 1B purchased around 2013.
Hardware requirements:
- Host PC with SD Card reader
- RPi 1.B
- SD Card - I use 4GB card
- optional: USB <-> TTL Serial cable (in my case mandatory - I have only VGA monitor but RPi has only HDMI output - I have also HDMI -> VGA converter but it is sometimes tricky
There are two guides on:
- https://wiki.alpinelinux.org/wiki/Raspberry_Pi
- https://wiki.alpinelinux.org/wiki/Classic_install_or_sys_mode_on_Raspberry_Pi
In case of Model PI 1.B we need armhf
(ARM with Hardware Float support - math coprocessor) in my case:
- download page: https://alpinelinux.org/downloads/
- download URL: https://dl-cdn.alpinelinux.org/alpine/v3.20/releases/armhf/alpine-rpi-3.20.3-armhf.img.gz
Downloaded .img contains only boot FAT partition (boot is defined by Broadcom firmware - using MBR partitioning and having FAT partition with specified files).
Preparing SD card
Insert card to SD reader of your Host Linux (I use openSUSE LEAP 15.6 amd64). Verify proper device name (important!):
$ lsblk -S
NAME
HCTL TYPE VENDOR MODEL REV SERIAL TRAN
sda 0:0:0:0 disk ATA Samsung SSD 870 EVO 1TB SVT03B6Q S75CNX0WB29571B sata
sdb 2:0:0:0 disk Generic- SD/MMC/MS PRO 1.00 20120926571200000 usb
In my case target device with SD card is /dev/sdb
WARNING! If you have any "smart" desktop system on your Host PC and card already has FAT partition it will be automatically mounted - you have to unmount it from your File Manager (Thunar in case of Xfce).
Now write Alpine Linux with just boot partition - REPLACE /dev/sdb
with your SD card device!
sudo dd if=alpine-rpi-3.20.3-armhf.img of=/dev/sdb bs=1024k status=progress
In case of Desktop with Thunar the new FAT partition will be again automatically mounted - we can use it to make important changes.
Next edit /run/media/USERNAME/disk/cmdline.txt
and append at the end of line console=ttyAMA0
and remove quiet
Now Unmount and then Eject your SD card from Thunar manager or using commands like:
udisksctl unmount -b /dev/sdb1
udisksctl power-off -b /dev/sdb
Booting
I connected USB <-> TTL Serial adapter to both RPi and PC. On PC with SUSE it appears as /dev/ttyUSB0
I use following command on Host PC to run Minicon on serial console with logging:
$ minicom -C logs/alpine-`date '+%s'`.log -b 115200 -8 -D /dev/ttyUSB0
Cannot create lockfile for /dev/ttyUSB0: Permission denied
I have verified that I have proper permissions:
$ ls -l /dev/ttyUSB0
crw-rw---- 1 root dialout 188, 0 Sep 7 08:57 /dev/ttyUSB
$ groups
users libvirt wireshark dialout wheel
Using strace -f -o xx COMMAND
and grepping for = -
I found:
13266 openat(AT_FDCWD, "/var/lock/LCK...13265", O_WRONLY|O_CREAT|O_TRUNC, 0666) = -1 EACCES (Permission denied)
So:
$ ls -ld /var/lock
lrwxrwxrwx 1 root root 9 Dec 26 2023 /var/lock -> /run/lock
$ ls -ld /run/lock
drwxrwxr-x 5 root root 140 Sep 7 08:37 /run/lock
So thanks to systemd we have to run minicom as root.
Now power-up RPi 1.b - after few seconds you should see kernel messages on serial console and Alpine setup messages:
0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 6.6.49-0-rpi (buildozer@build-3-20-armhf) (gcc (Alpine 13.2.1_git20240309) 13.2.1 202403094
[ 0.000000] CPU: ARMv6-compatible processor [410fb767] revision 7 (ARMv7), cr=00c5387d
[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
[ 0.000000] OF: fdt: Machine model: Raspberry Pi Model B Rev 2
...
[ 5.649022] Loading boot drivers...
* Loading boot drivers: [ 5.701332] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[ 5.720787] Loading boot drivers: ok.
ok.
[ 5.751832] Mounting boot media...
* Mounting boot media: [ 5.873024] usb 1-1.1: new high-speed USB device number 3 using dwc_otg
[ 6.085430] usb 1-1.1: New USB device found, idVendor=0424, idProduct=ec00, bcdDevice= 2.00
[ 6.099270] usb 1-1.1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
...
* Starting firstboot ... [ ok ]
Welcome to Alpine Linux 3.20
Kernel 6.6.49-0-rpi on an armv6l (/dev/ttyAMA0)
localhost login:
Use root
without password.
Persistent disk install
I want to have standard installation on SD card (with read-write filesystem). In that case we have to follow semi-manual process (similar to manual disk setup etc):
- https://wiki.alpinelinux.org/wiki/Raspberry_Pi#Persistent_storage
- https://wiki.alpinelinux.org/wiki/Classic_install_or_sys_mode_on_Raspberry_Pi
First I will add target partitions:
fdisk /dev/mmcblk0
Disk /dev/mmcblk0: 3859 MB, 4046454784 bytes, 7903232 sectors
7840 cylinders, 16 heads, 63 sectors/track
Units: sectors of 1 * 512 = 512 bytes
Device Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type
/dev/mmcblk0p1 * 0,0,1 146,15,63 0 148175 148176 72.3M 6 FAT16
# Adding root filesystem partition:
Command (m for help): n
Partition type
p primary partition (1-4)
e extended
p
Partition number (1-4): 2
First sector (148176-7903231, default 148176):
Using default value 148176
Last sector or +size{,K,M,G,T} (148176-7903231, default 7903231): +3g
Command (m for help): p
Disk /dev/mmcblk0: 3859 MB, 4046454784 bytes, 7903232 sectors
7840 cylinders, 16 heads, 63 sectors/track
Units: sectors of 1 * 512 = 512 bytes
Device Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type
/dev/mmcblk0p1 * 0,0,1 146,15,63 0 148175 148176 72.3M 6 FAT16
/dev/mmcblk0p2 147,0,1 1023,15,63 148176 6439631 6291456 3072M 83 Linux
# Adding swap partition (just as reserve):
Command (m for help): n
Partition type
p primary partition (1-4)
e extended
p
Partition number (1-4): 3
First sector (6439632-7903231, default 6439632):
Using default value 6439632
Last sector or +size{,K,M,G,T} (6439632-7903231, default 7903231):
Using default value 7903231
Command (m for help): p
Disk /dev/mmcblk0: 3859 MB, 4046454784 bytes, 7903232 sectors
7840 cylinders, 16 heads, 63 sectors/track
Units: sectors of 1 * 512 = 512 bytes
Device Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type
/dev/mmcblk0p1 * 0,0,1 146,15,63 0 148175 148176 72.3M 6 FAT16
/dev/mmcblk0p2 147,0,1 1023,15,63 148176 6439631 6291456 3072M 83 Linux
/dev/mmcblk0p3 1023,15,63 1023,15,63 6439632 7903231 1463600 714M 83 Linux
Command (m for help): t
Partition number (1-4): 3
Hex code (type L to list codes): 82
Changed system type of partition 3 to 82 (Linux swap)
Command (m for help): p
Disk /dev/mmcblk0: 3859 MB, 4046454784 bytes, 7903232 sectors
7840 cylinders, 16 heads, 63 sectors/track
Units: sectors of 1 * 512 = 512 bytes
Device Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type
/dev/mmcblk0p1 * 0,0,1 146,15,63 0 148175 148176 72.3M 6 FAT16
/dev/mmcblk0p2 147,0,1 1023,15,63 148176 6439631 6291456 3072M 83 Linux
/dev/mmcblk0p3 1023,15,63 1023,15,63 6439632 7903231 1463600 714M 82 Linux swap
Command (m for help): v
Total allocated sectors 7903233 greater than CHS size 7902720
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table
fdisk: WARNING: rereading partition table failed, kernel still uses old table: Resource busy
WARNING! Because kernel was unable to re-read partition we have to issue reboot
...
After reboot verify that there are new partitions:
fdisk -l
Disk /dev/mmcblk0: 3859 MB, 4046454784 bytes, 7903232 sectors
7840 cylinders, 16 heads, 63 sectors/track
Units: sectors of 1 * 512 = 512 bytes
Device Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type
/dev/mmcblk0p1 * 0,0,1 146,15,63 0 148175 148176 72.3M 6 FAT16
/dev/mmcblk0p2 147,0,1 1023,15,63 148176 6439631 6291456 3072M 83 Linux
/dev/mmcblk0p3 1023,15,63 1023,15,63 6439632 7903231 1463600 714M 82 Linux swap
Disk /dev/mmcblk0p1: 72 MB, 75866112 bytes, 148176 sectors
147 cylinders, 16 heads, 63 sectors/track
Units: sectors of 1 * 512 = 512 bytes
Device Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type
/dev/mmcblk0p1p1 * 0,0,1 146,15,63 0 148175 148176 72.3M 6 FAT16
/dev/mmcblk0p1p2 147,0,1 1023,15,63 148176 6439631 6291456 3072M 83 Linux
Partition 2 has different physical/logical end:
phys=(1023,15,63) logical=(6388,8,24)
/dev/mmcblk0p1p3 1023,15,63 1023,15,63 6439632 7903231 1463600 714M 82 Linux swap
Partition 3 has different physical/logical start (non-Linux?):
phys=(1023,15,63) logical=(6388,8,25)
Partition 3 has different physical/logical end:
phys=(1023,15,63) logical=(7840,8,8)
You may safely ignore CHS mismatch warnings because it is ignored on Raspberry PI - it always uses LBA Addresses (CHS is leftover from old PC BIOS and IDE disks era).
To avoid out of memory, I recommend to format and activate swap:
mkswap -L alpine-swap /dev/mmcblk0p3
swapon /dev/mmcblk0p3
free -m
total used free shared buff/cache available
Mem: 429 15 352 9 62 394
Swap: 715 0 715
WARNING! I will now try my own setup for lazy people (trying to avoid as much manual steps as possible):
apk add e2fsprogs
mkfs.ext4 -L alpine-root /dev/mmcblk0p2
mount /dev/mmcblk0p2 /mnt
# we must fix date to avoid https errors
setup-interfaces
Available interfaces are: eth0.
Enter '?' for help on bridges, bonding and vlans.
Which one do you want to initialize? (or '?' or 'done') [eth0]
Ip address for eth0? (or 'dhcp', 'none', '?') [dhcp]
Do you want to do any manual network configuration? (y/n) [n]
apk add dhcpcd
/sbin/ifup eth0
# now we have working network and can set proper date/time:
ntpd -dnqp ntp.cesnet.cz
Sat Sep 7 07:42:30 UTC 2024
Now run installer (hoping it will not crash):
FORCE_BOOTFS=1 DISKOPTS=/mnt setup-alpine
FORCE_BOOTFS
is required because we fake that /boot
is just directory on
ext4 root filesystem but RPi can boot from FAT only. The problem is that SD
card is both Source device (system booted from it and actively is using its FAT
partition) and also Target device (where we want to install new boot
configuration). Thus `FORCE_BOOTFS' is needed until some better solution will
be possible.
Quick and dirty way to boot installed with minimal changes:
# alpine mounted FAT there as read-only:
mount -o rw,remount /media/mmcblk0p1
vi /media/mmcblk0p1/cmdline.txt
# append to line: root=/dev/mmcblk0p2
# reboot with: reboot
NOTE: Please read https://wiki.alpinelinux.org/wiki/Classic_install_or_sys_mode_on_Raspberry_Pi for clean solution.
After reboot Login as root - and you have to enter also root's password (it is sign that we are really booting installed system).
- after power-up you have to sync clock with
ntpd -nqp ntp.cesnet.cz
(I should add it topost-up
of/etc/network/interfaces
- now edit /etc/apk/repositories and uncomment community line.
- and try to install favorite programs:
apk add vim tmux mc curl lynx wget
If you plan SSH access you can also setup regular user:
adduser -G wheel USRNAME
# will be asked for password
To become root from USERNAME issue command su -
and enter root's password. I found that enough
so I don't use sudo or doas (it is just another layer).
Summary
Alpine Linux again confirmed its fame as very fast and low footprint system. Whole system has really good response and it uses just 20MB of memory to run (including SSH server):
$ free -m
total used free shared buff/cache available
Mem: 429 20 322 0 87 398
Swap: 0 0 0
Disk overview:
apk add lsblk
lsblk -f -o+size
NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS SIZE
mmcblk0 vfat 3.8G
├─mmcblk0p1 vfat 72.4M
├─mmcblk0p2 ext4 alpine-root 78b30ca7-46a1-49d7-b1d2-c26e785d9237 2.4G 12% / 3G
└─mmcblk0p3 swap alpine-swap 96e0886c-de36-4656-bbf5-11fc4f16bdd5 714.6M
Although setup requires few manual steps (unlike NetBSD or other Linux distributions) - it is so far worth it.
Overall, Linux now has reputation of slow and bloated system - and it is mostly true, but Alpine Linux is definitely positive exception - both its disk footprint and speed very well compares to tuned FreeBSD or any other Unix like system. I'm really glad that there are still good examples in Linux world that not just follow rot business crowd (with its systemd and container crap that clashes with interests of community), but rather uses reasonable and sensible solutions.
--hp