Skip to content

Instantly share code, notes, and snippets.

@mrled
Last active December 6, 2020 02:21
Show Gist options
  • Save mrled/87c90a2e3412a184e1ce63e57079899d to your computer and use it in GitHub Desktop.
Save mrled/87c90a2e3412a184e1ce63e57079899d to your computer and use it in GitHub Desktop.

Raspberry Pi 4 Alpine chroot scripts

🚨🚨🚨 I don't recommend this 🚨🚨🚨

I'm keeping it here so I can remember what I did, but I think a Docker container is a better way to go about it. I wrote a Dockerfile for this over here: https://github.com/mrled/alpine-rpi4-aports-docker

Scripts for building an Alpine chroot for building Alpine packages.

Who/what is this for?

If you have a Raspberry Pi 4 running something other than Alpine, and you want to build Alpine packages (including a kernel) using Alpine tools, this is designed to let you do that.

Does it have any problems?

Yes, it shouldn't be used out of the box. The Makefile is bad because I'm an idiot at make.

It's a starting point if you want to do the same thing in a chroot, maybe. Idk. It's also just here so I can find it again if I need it.

Setup

You must have an abuild key

abuild-keygen -a -i

Building a kernel

https://wiki.alpinelinux.org/wiki/Custom_Kernel

Here's how I'm building a Raspberry Pi kerenl (from Ubuntu on a real rpi 4)

# Get branch for your version
basever=3.12-stable
cd aports
git checkout -b $basever origin/$basever

# Now get a branch for your custom kernel config
git checkout -b alpine-preboot-kernel origin/$basever

# Note that on rpi, the kernel dir is main/linux-rpi, not main/linux-vanilla.

# Build the kernel with Alpine's normal configuration
cd main/linux-rpi
abuild -rKd

... although you might want to break abuild into separate steps, so you can troubleshoot if something goes wronng... Instead of abuild -rKd, you can do this:

abuild deps # Install build dependencies through the pseudo-package .makedepends-linux-hardened, that you can remove later
abuild unpack # Extract sources to src/
abuild prepare # Apply patches
abuild build # The actual build. Will ask about new kernel options
# .... runs 'make config'; hold down enter for 10 minutes for all defaults, lol

# save that config for later
cp src/build/.config config-alldefaults

abuild package # "Install" the kernel into pkg/
abuild rootpkg # Assemble the package, will appear in ~/packages

Further reading

This post shows someone patching the kernel and building the result, and also breaking down the larger abuild -rK into individual steps. https://strfry.github.io/blog/building-alpine-kernel.html

CHROOT_UID=1001
CHROOT_GID=1001
ALPINE_PACKAGER="Micah R Ledbetter <me@micahrl.com>"
#!/bin/sh
set -eu
chroot alpine-minirootfs-3.12.1-aarch64 \
su - builder \
-c "/usr/bin/env TERM='$TERM' /bin/bash -li"
# Make a chroot environment
chroot_home := $(chroot)/home/$(chroot_user)
alpine_ver := 3.12
alpine_ver_full := $(alpine_ver).1
alpine_arch := aarch64
miniroot_basename := alpine-minirootfs-$(alpine_ver_full)-$(alpine_arch)
chroot := $(miniroot_basename)
miniroot_tarball := $(chroot).tar.gz
miniroot_tarball_uri := http://dl-cdn.alpinelinux.org/alpine/v$(alpine_ver)/releases/$(alpine_arch)/$(miniroot_tarball)
chroot_busybox := $(chroot)/bin/busybox
chroot_resolv := $(chroot)/etc/resolv.conf
chroot_mounted := $(chroot).mounted
chroot_env := $(chroot)/.chroot.env
chroot_profile := $(chroot)/etc/profile.d/chroot.sh
chroot_postinstaller := $(chroot)/usr/local/bin/postinstall.sh
chroot_postinstalled := $(chroot)/.postinstalled
.PHONY: cleanlocal cleanall mount umount default
default: $(chroot_postinstalled)
$(chroot_postinstalled): $(chroot_env) $(chroot_resolv) $(chroot_postinstaller) $(chroot_profile)
chroot $(chroot) /usr/local/bin/postinstall.sh
$(chroot_profile): $(chroot_busybox)
cp profile.d.chroot.sh $(chroot_profile)
$(chroot_postinstaller): postinstall.sh $(chroot_busybox) $(chroot_mounted)
install postinstall.sh $(chroot_postinstaller)
$(chroot_env): $(chroot_busybox) chroot.env
cp chroot.env $(chroot_env)
$(chroot_resolv): $(chroot_busybox) resolv.conf
install resolv.conf $(chroot_resolv)
$(chroot_busybox): $(miniroot_tarball)
mount | grep '$(chroot)' && exit 1 || true
mkdir -p $(chroot)
cd $(chroot); tar -zxf ../$(miniroot_tarball)
# Touch it because it'll extract it with an old timestamp
touch $(chroot)
$(miniroot_tarball):
wget $(miniroot_tarball_uri)
cleanlocal:
mount | grep '$(chroot)' && exit 1 || true
rm -rf $(chroot)
cleanall:
mount | grep '$(chroot)' && exit 1 || true
rm -rf $(chroot) $(miniroot_tarball)
# Mounts section. Note that these all must be done as root
mount: $(chroot_mounted)
$(chroot_mounted): $(chroot_busybox)
mount --bind /dev $(chroot)/dev
mount -t devpts devpts $(chroot)/dev/pts -o nosuid,noexec
mount -t tmpfs shm $(chroot)/dev/shm -o mode=1777,nosuid,nodev
mount -t sysfs sys $(chroot)/sys -o nosuid,nodev,noexec,ro
mount -t proc proc $(chroot)/proc -o nosuid,nodev,noexec
mount -t tmpfs tmp $(chroot)/tmp -o mode=1777,nosuid,nodev,strictatime
mount -t tmpfs run $(chroot)/run -o mode=0755,nosuid,nodev
mkdir -p $(chroot)/home/builder
mount --bind ./chroot-homedir $(chroot)/home/builder
touch $(chroot_mounted)
# Unmount section. All must be done as root
umount:
umount -l $(chroot)/dev/pts || true
umount -l $(chroot)/dev/shm || true
umount -l $(chroot)/home/builder || true
sleep 1
umount -l $(chroot)/* || true
rm -f $(chroot_mounted)
@echo "======== Any remaining mounts listed below ========"
mount | grep '$(chroot)' || true
@echo "======== Mounts list complete ========"
# OLD MOUNTS SECTION - DELETEME
# chroot_dev := $(chroot)/dev
# chroot_devpts := $(chroot)/dev/pts
# chroot_devpts_mounted :$(chroot).devpts.mounted
# chroot_sysfs := $(chroot)/sys
# chroot_procfs := $(chroot)/proc
# chroot_tmpfs := $(chroot)/tmp
# chroot_runfs := $(chroot)/run
# chroot_devshm := $(chroot)/dev/shm
# chroot_devshm_mounted :$(chroot).devshm.mounted
# mount: $(chroot_dev).mounted $(chroot_devpts_mounted) $(chroot_sysfs).mounted $(chroot_procfs).mounted $(chroot_tmpfs).mounted $(chroot_runfs).mounted $(chroot_devshm_mounted)
# echo "Mounted chroot filesystems"
# $(chroot_devpts_mounted): $(chroot_dev).mounted
# umount $(chroot_devpts) || true
# mount -t devpts devpts $(chroot_devpts)
# touch $(chroot_devpts_mounted)
# $(chroot_devshm_mounted): $(chroot_dev).mounted
# umount $(chroot_devshm) || true
# mount -t tmpfs shm $(chroot_devshm) -o mode=1777,nosuid,nodev
# touch $(chroot_devshm_mounted)
# $(chroot_dev).mounted: $(chroot_busybox)
# umount $(chroot_dev) || true
# mount --bind /dev $(chroot_dev)
# touch $(chroot_dev).mounted
# $(chroot_sysfs).mounted: $(chroot_busybox)
# umount $(chroot_sysfs) || true
# mount -t sysfs sys $(chroot_sysfs) -o nosuid,nodev,noexec,ro
# touch $(chroot_sysfs).mounted
# $(chroot_procfs).mounted: $(chroot_busybox)
# umount $(chroot_procfs) || true
# mount -t proc proc $(chroot_procfs) -o nosuid,nodev,noexec
# touch $(chroot_procfs).mounted
# $(chroot_tmpfs).mounted: $(chroot_busybox)
# umount $(chroot_tmpfs) || true
# mount -t tmpfs tmp $(chroot_tmpfs) -o mode=1777,nosuid,nodev,strictatime
# touch $(chroot_tmpfs).mounted
#!/bin/sh
set -e
# Must be run from within the chroot
# .chroot.env comes from Makefile
. /.chroot.env
# Install user-related prereqs
apk add bash sudo alpine-sdk
# Install nice-to-haves
apk add mandoc man-pages mandoc-apropos less less-doc
# Install prereqs for building the kernel
apk add gcc make autoconf automake g++ musl-dev libc-dev git linux-headers linux-rpi build-base mkinitfs perl gmp-dev elfutils-dev bash sed installkernel bc linux-firmware bison flex openssl-dev linux-rpi-dev abuild-doc ncurses-dev
# Add our user
getent passwd ${CHROOT_UID} || adduser -u ${CHROOT_UID} -s /bin/bash -D -H builder
# Add our user to their own group
addgroup builder builder
# Add our user to the abuild group for building Alpine packages
addgroup builder abuild
# Useful when chrooted, so we can build as non-root but still sudo to add a package if necessary
echo "builder ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/chroot_user
# Configure the Alpine package builder scripts
echo "PACKAGER=\"$ALPINE_PACKAGER\"" | tee /etc/abuild.conf
echo 'MAINTAINER="$PACKAGER"' | tee /etc/abuild.conf
# Get the Alpine abuild source
test -d ~builder/aports ||
sudo -u builder git clone git://git.alpinelinux.org/aports ~builder/aports
# Let Make know we're finished
touch /.postinstalled
NORMAL="\[\e[0m\]"
RED="\[\e[1;31m\]"
GREEN="\[\e[1;32m\]"
if [ "$USER" = root ]; then
PS1="(chroot) $RED\h [$NORMAL\w$RED]# $NORMAL"
else
PS1="(chroot) $GREEN\h [$NORMAL\w$GREEN]\$ $NORMAL"
fi
nameserver 8.8.8.8
nameserver 8.8.4.4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment