Install Alpine Linux 3.10.2 on a Raspberry PI using macOS

October 1, 2019

Changes from the last Alpine/Pi install post:

The software and hardware used for this HOWTO are:

  1. Alpine Linux 3.10.2, armv7
  2. Raspberry Pi 3 Model B, and:
    1. USB keyboard
    2. TV with HDMI input and an HDMI cable
    3. 5V 2.5A Switching Power Supply with 20AWG MicroUSB Cable
  3. macOS Mojave 10.14.6 (diskutil)
  4. Samsung 32GB microSD
  5. Vivitar microSD card reader

Step 1. Partition the microSD with your Mac and unzip install.

Make sure you know for sure which disk is the microSD. If you're not sure, stop.

You could lose all the data on your Mac.

    $ diskutil list
    /dev/disk0 (internal, physical):
       #:                       TYPE NAME                    SIZE       IDENTIFIER
       0:      GUID_partition_scheme                        *751.3 GB   disk0
       1:                        EFI EFI                     209.7 MB   disk0s1
       2:                 Apple_APFS Container disk1         751.1 GB   disk0s2
    /dev/disk1 (synthesized):
       #:                       TYPE NAME                    SIZE       IDENTIFIER
       0:      APFS Container Scheme -                      +751.1 GB   disk1
                                     Physical Store disk0s2
       1:                APFS Volume Macintosh HD            652.6 GB   disk1s1
       2:                APFS Volume Preboot                 42.1 MB    disk1s2
       3:                APFS Volume Recovery                510.0 MB   disk1s3
       4:                APFS Volume VM                      3.2 GB     disk1s4
    /dev/disk2 (external, physical):
       #:                       TYPE NAME                    SIZE       IDENTIFIER
       0:     FDisk_partition_scheme                        *31.4 GB    disk2
       1:                 DOS_FAT_32 VOL1                    256.0 MB   disk2s1

If you are totally sure you know which disk is the USB stick with the MicroSD (it was disk2 for me), run:

    $ diskutil partitionDisk disk2 MBR FAT32 VOL1 256MB "Free Space" VOL2 R

Download armv7 3.10.2 and untar it onto the partition you just created:

    cd /Volumes/VOL1
    tar xzvf ~/Downloads/alpine-rpi-3.10.2-armv7.tar.gz

Create a usercfg.txt to suit what you will use the Raspberry PI for—mine will be a headless server. For more information on setting up the usercfg.txt, see links 3, 4, and 5 below.

    $ cat>usercfg.txt<<EOF
    > # On the Pi, the GPU and the CPU share RAM. This is a headless install, so 
    > # give the GPU the least amount of RAM it can get by with (16MB).
    > # This also triggers the Pi to use a cutdown version of the firmware (start_cd.elf).
    > gpu_mem=16
    > # Turn off audio and bluetooth. (Note "dt" stands for device tree.)
    > dtparam=audio=off,pi3-disable-bt
    > # Enable mini UART as serial port (/dev/ttyS0). 
    > # Also, fixes VideoCore IV (aka the GPU or the VPU) frequency to 250MHz.
    > enable_uart=1
    > EOF

    $ cd ~

Unmount microSD USB card reader in Finder and take out the microSD card.

Step 2. Create a Linux and a Linux swap partition on the Raspberry Pi.

Since OSX diskutil does not provide the Linux format partition type, so you have to make this partition using the Raspberry Pi. Put the microSD in the Raspberry Pi, then plug in keyboard, TV, ethernet cable and lastly the power supply.

Make the DOS partition bootable.

    # username = root (you won't need a password)
    fdisk /dev/mmcblk0
    # Use the following inputs:
    a     # Mark the DOS partition as bootable.
    Disk /dev/mmcblk0: 29 GB, 31440502784 bytes, 61407232 sectors
    3022 cylinders, 255 heads, 63 sectors/track 
    Units: sectors of 1 * 512 = 512 bytes 
    Device       Boot StartCHS    EndCHS        StartLBA     EndLBA    Sectors  Size Id Type 
    /dev/mmcblk0p1 *  1023,254,63 1023,254,63       2048     502047     500000  244M  b Win95 FAT32

Add the Linux partition. This the big difference from the previous blog post—you don't accept the default first sector (63), and instead add one to the EndLBA of the first partition and use that.

    n        # new partition ... 
    p        # ... is a primary partition
    2        # ... is the 2nd partition
    502048   # ... 1 + EndLBA of first partition
    +27G     # ... This leaves 2GB for the swap partition.
    p        # ... so you can read the EndLBA of the second partition.

Finally, add the swap partition.

    n         # new partition ...
    p         # ... is a primary partition
    3         # ... is the 3rd partition
    57125152  #  ... 1 + EndLBA of first partition
              # ... and a default last sector
    t         # the partition type ... 
    3         # ... of the third partition
    82        # ... is Linux swap
    p         # print the partition table ...
    w         # ... and if it looks good, write it to disk
    # ignore "Resource busy" warning


Run setup-alpine. It has improved since 3.8.

    # login as root again

    # us                # keyboard
    # us
    # palestrina        # hostname
    # eth0
    #     # static IP
    #     # netmask
    #      # gateway
    # done
    # no                # no manual network config
    #   # domain
    #      # DNS server
    # s3cr3t            # new root password
    # s3cr3t
    # US/Eastern        # timezone
    # none              # no proxy
    # chrony            # take the default
    # 1                 # use the CDN mirror
    # openssh

    # none              # don't store configs
    # none              # don't create an apk cache

Create the filesystems.

    mkswap /dev/mmcblk0p3
    apk add e2fsprogs
    # you should see five packages installed: libuuid, libblkid, libcom_err, e2fsprogs-libs, and e2fsprogs.
    mkfs.ext4 /dev/mmcblk0p2

Step 3: Install Alpine on the Linux partition and bind mount /boot directory.

Edit the cmdline.txt After the Linux partition is setup, the Pi still boots from the DOS partition, which means it loads the kernel, initramfs, and modloop images from the DOS /boot directory. When the kernel boots, it reads command line options from cmdline.txt (which you can check with dmesg | grep command), and sets the root filesystem to be the Linux partition. We bind mount the Linux /boot to the DOS /boot so any Alpine upgrade that affects the contents of the /boot directory (for example, a new kernel) will be written to the DOS partition. on the DOS partition (mmcblk0p1) to configure the kernel to use the Linux partition (mmcblk0p2) as the root file system.

    mkdir /stage
    mount /dev/mmcblk0p2 /stage
    setup-disk -m sys /stage
    # ignore all extlinux errors, the Pi doesn't need that program
    # ignore note that you might need to "fix the MBR".

    echo /dev/mmcblk0p1 /media/mmcblk0p1 vfat defaults 0 0 >> /stage/etc/fstab

    # point root to 2nd partition
    mount -o remount,rw /media/mmcblk0p1
    sed -i '$ s/$/ root=\/dev\/mmcblk0p2/' /media/mmcblk0p1/cmdline.txt
    cat /media/mmcblk0p1/cmdline.txt
    modules=loop,squashfs,sd-mod,usb-storage quiet dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2

    echo /media/mmcblk0p1/boot /boot none defaults,bind 0 0 >> /stage/etc/fstab



Step 4: Add a non-privileged user

The default openSSH configuration won't let root connect with a password. Since I'm using this as a headless server, I want a user that I can use to login remotely via SSH. I also want to put that user in the wheel group and edit the sudo config so this user can become root.

    # adduser mark
    Changing password for mark
    New password:
    Retype password:
    passwd: password for mark changed by root

Add user mark to the wheel group.

    # adduser mark wheel
    # groups mark
    mark wheel

Install sudo and let members of wheel to execute any command (with a password).

    # apk add visudo
    # visudo     # uncomment: %wheel ALL=(ALL) ALL

It's good to go—type halt to shutdown Alpine and then plug in the Pi to your server network.



Concise explanation of installing Alpine Linux on the Pi, including the usercfg.txt as well as the bind mount.
bind mount, among other things. Great resource.
usercfg.txt for headless mode