Installing Alpine Linux on OrangePi RV2: Difference between revisions

From Alpine Linux
mNo edit summary
No edit summary
Tag: Manual revert
Line 1: Line 1:
{{TOC left}}
{{Draft}}
{{Draft}}
[[Main Page]] > [[:Category:Architectures|Architectures]] > [[Riscv64]] > Installing Alpine Linux on OrangePi RV2
[[Main Page]] > [[:Category:Architectures|Architectures]] > [[Riscv64]] > Installing Alpine Linux on OrangePi RV2

Revision as of 04:02, 10 April 2026

This material is work-in-progress ...

Do not follow instructions here until this notice is removed.
(Last edited by Aarch0x40 on 10 Apr 2026.)

Main Page > Architectures > Riscv64 > Installing Alpine Linux on OrangePi RV2

Warning: The contributors to the Alpine Linux project are not responsible for any damage/loss experienced by using the following guide. This article is provided as a general reference. It is assumed that the implementer will have the knowledge and ability to close the gap between what is described here and their specific setup.


The OrangePi RV2 is a credit-card sized development board with a Ky X1 8-Core SoC. The Ky X1 is for all intents and purposes a SpacemiT K1 SoC. The remainder of this guide is more likely to use the terms SpacemiT or K1 as is prevalent throughout the Linux community. Please understand that these terms all refer to the same RISC-V ISA implementation.

This guide assumes that the manufacturer provided OpenSBI and U-Boot binaries have been applied to the SPI Flash device. This stock bootloader will look for an extlinux/extlinux.conf which will be used to configure the boot process.

Those following this guide may find it useful to have a USB UART serial cable available to debug kernel loading.

This guide borrows heavily from the article install Alpine Linux riscv64 under qemu with u-boot loader by Milan P. Stanić and posted to Riscv64 by User:AnIDFB.

Known issues


Warning: The following are the issues that are known to exist between the result of this guide and the manufacturer provided image


  • Wireless (Wi-Fi & Bluetooth) is not functional
  • Some kernel sources have an issue with starting the framebuffer
  • Manufacturer tools are not included

This guide was assembled as a dumping of my personal notes. It's being updated as I come across new information. Alpine does run on the RV2 albeit not directly out of the box. Will do my best to reference external materials so that this article may provide some insight to others while still under development. The above may not be the only issues but hopefully there's enough information here to get you going.

Kernel and Firmware

There are a few different options for kernels. The extent of coverage documented here is largely due to my initial ignorance. I have found a few sources for mostly workable kernels. None of them works 100%. SpacemiT is still in the process upstreaming functionality.

Obtaining the ESOS firmware

The processor being used on the RV2 requires a firmware to function properly. This file is available from the vendor images, in third party distributions and in the orangepi-xunlong/orangepi-build GitHub repository. The subdirectory containing the required file is external/packages/bsp/ky/usr/lib/firmware. Download the file esos.elf. Keep the download in a safe place and also /lib/firmware. The /lib/firmware directory is also where you'll find this file within the vendor's image or an initrd image.

Note: Changes to mkinitfs will be needed in order for this firmware to be included. More information on that will be provided further down the document

Obtaining the Vendor kernel

Open a browser to the OrangePI RV2 Download page.

Click on the "Downloads" button for the Ubuntu Image. This will take you to a Google Drive folder. Download the Orangepirv2_1.0.0_ubuntu_noble_server_linux6.6.63.7z.

Decompress this file after downloading using your favorite archive utility. It will expand to a directory containing Orangepirv2_1.0.0_ubuntu_noble_server_linux6.6.63.img and shasum file.

Attach the image to a loop device and mount the root partition.

# Find the first available loop device
doas losetup --find

# Assuming the first found available device is /dev/loop0
doas losetup -P /dev/loop0 Orangepirv2_1.0.0_ubuntu_noble_server_linux6.6.63.img

# Mount the root slice
doas mount /dev/loop0p1 /mnt

Archive the vendor kernel

cd /mnt
tar czf /var/tmp/linux-6.6.63-ky.tgz boot/vmlinuz-6.6.63-ky boot/System.map-6.6.63-ky boot/config-6.6.63-ky boot/dtb-6.6.63-ky lib/modules/6.6.63-ky
Note: You probably want to put the resulting archive in a safer place than /var/tmp at this point. There's a bit to do before we'll need it.

Unmount and detach the vendor image

cd -
doas umount /mnt
doas losetup -d /dev/loop0

Will Alpine's kernel work? (TBD)

Note: Need to revisit this

Building from source

There have been 2 main repositories for patched kernel sources.

The linux-spacemit repository is used by RedHat employee Jason Montleon in building out their RISCV64 support. The linux-bredos repository is used by the BredOS project which supports the RV2 and has provides downloadable images for the board. There is cross contribution between these two repositories. A lot of what I've learned to assemble this guide is attributed to these projects.

Setting up a workspace

Begin by setting up a RISC-V workspace by following Running Alpine riscv64 in QEMU. You'll need to establish a build environment in this QEMU guest.

doas apk add alpine-sdk bison flex openssl-dev ncurses ncurses-dev
Note: ncurses and ncurses-dev aren't a hard requirements but are useful if you want to run make menuconfig

Cloning the source, configuring and building the kernel

Note: This is needs a redo.

Preparing the media

Partition and setup the filesystems

Install parted package

doas apk add parted

Insert, partition and format the boot media

The media can be either an SD card or USB drive. An 2280 PCIe NVMe is also possibly if you have the ability to write it from the host setting up the media. For the purposes of this guide we will refer to our boot media as /dev/sdb. The following section requires a root shell.

alias p="parted -sa optimal /dev/sdb"
p mklabel gpt
p mkpart boot ext4 0G 512M
p set 1 boot
p mkpart root ext4 512M 100%
p p

The final command should produce output to confirm the result of the executed commands. It should look something like the following.

Model: Generic STORAGE DEVICE (scsi)
Disk /dev/sdb: 15.5GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: 

Number  Start   End     Size    File system  Name  Flags
 1      1049kB  512MB   511MB   ext4         boot  boot, esp
 2      512MB   15.5GB  15.0GB               root

If all looks good, then we can proceed with formatting the partitions

mkfs.ext4 /dev/sdb1 && mkfs.ext4 /dev/sdb2

Mount the filesystems and lay some preliminary groundwork.

# Mount the target root slice
mount /dev/sdb2 /mnt

# Create mount point for boot slice
[ ! -d /mnt/boot ] && mkdir -vp /mnt/boot

# Mount boot slice
mount /dev/sdb1 /mnt/boot

# Create directory for extlinux config
[ ! -d /mnt/boot/extlinux ] && mkdir -vp /mnt/boot/extlinux

# Create directory for apk config
[ ! -d /mnt/etc/apk ] && mkdir -vp /mnt/etc/apk

# Create mount point for devfs
[ ! -d /mnt/dev ] && mkdir -vp /mnt/dev

# Create mount point for procfs
[ ! -d /mnt/proc ] && mkdir -vp /mnt/proc

# Create mount point for sysfs
[ ! -d /mnt/sys ] && mkdir -vp /mnt/sys

# Use bind mounts for dev proc and sys within the target device
mount -o bind /dev /mnt/dev && mount -o bind /proc /mnt/proc && mount -o bind /sys /mnt/sys

# Configure apk package manager
cat <<EOF > /mnt/etc/apk/repositories
#/media/vda1/apks
http://dl-cdn.alpinelinux.org/alpine/edge/main
http://dl-cdn.alpinelinux.org/alpine/edge/community
http://dl-cdn.alpinelinux.org/alpine/edge/testing
EOF

Install Alpine from an Alpine host

Install Alpine with apk

Some of what is going to be installed is up to your choosing. This should be enough to get you going and demonstrate how to target an apk installation.

apk --root /mnt --arch riscv64 --allow-untrusted --initdb add \
    alpine-base alpine-baselayout alpine-conf alpine-keys alpine-release alpine-baselayout-data \
    kmod openrc dbus util-linux blkid chrony sysfsutils ssl_client openssh ca-certificates-bundle \
    alpine-keys ethtool e2fsprogs e2fsprogs-extra libudev-zero libudev-zero-helper parted grep \
    busybox-mdev-openrc procps-ng net-tools coreutils doas sed gawk findutils bash shadow pciutils \
    mkinitfs

Setup openrc services

for rc in boot/bootmisc boot/hostname boot/modules boot/sysctl boot/urandom boot/networking \
	sysinit/devfs sysinit/hwdrivers sysinit/mdev sysinit/modules \
	shutdown/mount-ro shutdown/killprocs \
	default/dbus default/networking default/chronyd default/local; do
	ln -s /etc/init.d/"${rc##*/}" /mnt/etc/runlevels/"$rc"
done

Setup fstab

cp /mnt/etc/fstab /mnt/etc/fstab.orig
echo $(blkid /dev/sdb2 | sed 's/.*: //;s/ .*//;s/"//g') / \ \ \ \ ext4 rw,relatime 0 1 > /mnt/etc/fstab.new
echo $(blkid /dev/sdb1 | sed 's/.*: //;s/ .*//;s/"//g') /boot ext4 rw,relatime 0 2 >> /mnt/etc/fstab.new
cat /mnt/etc/fstab.orig >> /mnt/etc/fstab.new
cp /mnt/etc/fstab.new /mnt/etc/fstab

Setup networking

[ ! -d /mnt/etc/network ] mkdir -vp /mnt/etc/networking
cat <<EOF > /mnt/etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

EOF

Set the root password

When the system boots it will require a root password. This differs from Alpine install media but that's not the objective of this guide. This guide is installing a ready system.

passwd -R /mnt root

Enable login on UART

sed -i 's/^#ttyS0/ttyS0/' /mnt/etc/inittab

Install Alpine from an non-Alpine RISC-V Linux host

Download a minirootfs to run apk within a chroot

cd /var/tmp
wget https://dl-cdn.alpinelinux.org/edge/releases/riscv64/alpine-minirootfs-20260127-riscv64.tar.gz

Unzip in /mnt

cd /mnt
tar xfpz /var/tmp/alpine-minirootfs-20260127-riscv64.tar.gz
Note: If installing from a non-Alpine host, you may want to install the kernel image and modules first. Come back to this part to chroot and run the apk step and finish up with mkinitfs

Chroot into /mnt and run apk add

chroot /mnt /bin/sh
apk --arch riscv64 --allow-untrusted --initdb add \
    alpine-base alpine-baselayout alpine-conf alpine-keys alpine-release alpine-baselayout-data \
    kmod openrc dbus util-linux blkid chrony sysfsutils ssl_client openssh ca-certificates-bundle \
    alpine-keys ethtool e2fsprogs e2fsprogs-extra libudev-zero libudev-zero-helper parted grep \
    busybox-mdev-openrc procps-ng net-tools coreutils doas sed gawk findutils bash shadow pciutils \
    mkinitfs

Setup openrc services

for rc in boot/bootmisc boot/hostname boot/modules boot/sysctl boot/urandom boot/networking \
	sysinit/devfs sysinit/hwdrivers sysinit/mdev sysinit/modules \
	shutdown/mount-ro shutdown/killprocs \
	default/dbus default/networking default/chronyd default/local; do
	ln -s /etc/init.d/"${rc##*/}" /etc/runlevels/"$rc"
done

Setup fstab within the chroot

cp /etc/fstab /etc/fstab.orig
echo $(blkid /dev/sdb2 | sed 's/.*: //;s/ .*//;s/"//g') / \ \ \ \ ext4 rw,relatime 0 1 > /etc/fstab.new
echo $(blkid /dev/sdb1 | sed 's/.*: //;s/ .*//;s/"//g') /boot ext4 rw,relatime 0 2 >> /etc/fstab.new
cat /etc/fstab.orig >> /etc/fstab.new
cp /etc/fstab.new /etc/fstab

Setup networking

[ ! -d /etc/network ] mkdir -vp /etc/networking
cat <<EOF > /etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

EOF

Set the root password

When the system boots it will require a root password. This differs from Alpine install media but that's not the objective of this guide. This guide is installing a ready system.

passwd

Enable login on UART

sed -i 's/^#ttyS0/ttyS0/' /etc/inittab

Setting up the boot environment

All of the effort up to this point has come down to this. This portion of the guide will assume the kernel being installed is version 6.6.63-ky from the vendor.

Install the kernel

Install the esos.elf firmware

Creating the initrd image

Configuring and fixing mkinitfs

Add esos.elf to mkinitfs/features.d/base.files
echo "/lib/firmware/esos.elf" >> /etc/mkinitfs/features.d/base.files
Add the wireless-regdb database files to base.files
Note: You may not need this. If you see a kernel message regarding failure to load regulatory.db with error -2, this will resolve it
echo "/lib/firmware/regulatory.*" >> /etc/mkinitfs/features.d/base.files
Add jdb2 to ext4

The ext4 module depends on the jdb2 module for filesystem journaling. The Alpine kernel does not have ext4 or jbd2 as kernel builtins. If you're using the Alpine provided kernel then you'll need this on the initramfs.

echo "kernel/fs/jbd2" >> /etc/mkinitfs/features.d/ext4.modules
Prevent mkinitfs from deleting needed firmware

The mkinitfs script will delete a directory that shouldn't exist. The files assembled from the features.d includes will have already been staged prior to mkinitfs assembling firmware needed by included modules. We need this not to happen and below is the simplest workaround I could pull together. Make a copy of mkinitfs

cp /sbin/mkinitfs /sbin/mkinitfs-rv2

In the initfs_firmware function of /sbin/mkinitfs-rv2 you will find the following lines

        rm -rf "$tmpdir"/lib/firmware
        mkdir -p "$tmpdir"/lib/firmware

Change them to be

        #rm -rf "$tmpdir"/lib/firmware
        [ ! -d "$tmpdir"/lib/firmware ] && mkdir -p "$tmpdir"/lib/firmware

Using mkinitfs-rv2 to create an initrd image

Configure extlinux

Basic usability options

The above should get your OrangePi RV2 booting Alpine Linux. Below are some additional configurations to help make growing your install a little easier. The following assumes you're still chroot /mnt or have booted the system.

Add a local user for yourself with escalation privileges

Create a user account for yourself with a secondary group of wheel

# Create your account
useradd -G wheel -s /bin/bash -d /home/myuser -m -c "My User" myuser
# Set your password
passwd myuser

Add a configuration to doas.d for group wheel

echo permit persist :wheel > /etc/doas.d/00-wheel.conf

Install Avahi for mdns broadcasts

Avahi can broadcast names for services provided by your host. The default config in the Alpine package provides a configuration for sshd.

# First setup the hostname
setup-hostname myhost

# Set the hostname
hostname `cat /etc/hostname`

# Install the avahi apk
apk add avahi

# Enable and start the avahi daemon
rc-update add avahi-daemon && rc-service avahi-daemon start