Harden emulated ARM builds
This commit is contained in:
4 files changed
+71
-23
No files matched your search
@@ -32,12 +32,14 @@ The filesystem no longer encodes release policy. Instead:
|
||||
|
||||
The repository host builds every architecture it publishes on the same
|
||||
machine. A foreign architecture runs under QEMU user emulation, which
|
||||
`bin/build` sets up on first use (and re-checks after each reboot by
|
||||
actually running a container for the target platform):
|
||||
`bin/build` checks by actually running a container for the target platform.
|
||||
Rootful Docker registers QEMU on first use. Rootless Podman uses the host's
|
||||
registration and prints the one-time Arch setup commands when it is missing or
|
||||
lacks the credential flag required by `sudo` inside the builder:
|
||||
|
||||
```bash
|
||||
# Verify
|
||||
docker run --rm --platform linux/arm64 alpine:latest uname -m
|
||||
podman run --rm --platform linux/arm64 docker.io/library/alpine:latest uname -m
|
||||
# Should output: aarch64
|
||||
```
|
||||
|
||||
|
||||
@@ -174,10 +174,24 @@ HOST_ARCH=$(uname -m)
|
||||
if [[ "$HOST_ARCH" != "$ARCH" ]]; then
|
||||
PROBE_IMAGE="alpine:3.21"
|
||||
[[ "$CONTAINER_ENGINE" == "podman" ]] && PROBE_IMAGE="docker.io/library/alpine:3.21"
|
||||
if ! "$CONTAINER_ENGINE" run "${CONTAINER_RUN_ARGS[@]}" --rm "$(get_platform_arg "$ARCH")" "$PROBE_IMAGE" /bin/true >/dev/null 2>&1; then
|
||||
print_info "Setting up QEMU for $ARCH emulation on this $HOST_ARCH host..."
|
||||
|
||||
# Rootless Podman cannot repair host binfmt state itself. Validate the flags
|
||||
# before the basic probe, because an F-only registration can start an ARM
|
||||
# container but silently breaks sudo inside it.
|
||||
if [[ "$CONTAINER_ENGINE" == "podman" ]]; then
|
||||
setup_qemu "$ARCH"
|
||||
fi
|
||||
|
||||
if ! "$CONTAINER_ENGINE" run "${CONTAINER_RUN_ARGS[@]}" --rm "$(get_platform_arg "$ARCH")" "$PROBE_IMAGE" /bin/true >/dev/null 2>&1; then
|
||||
if [[ "$CONTAINER_ENGINE" == "podman" ]]; then
|
||||
print_error "QEMU $ARCH is registered, but the container probe failed"
|
||||
print_info "Refresh the registration with: sudo systemctl restart systemd-binfmt"
|
||||
exit 1
|
||||
else
|
||||
print_info "Setting up QEMU for $ARCH emulation on this $HOST_ARCH host..."
|
||||
setup_qemu "$ARCH"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Clean build-output directory to start fresh, unless the caller seeded it
|
||||
|
||||
+35
-15
@@ -5,6 +5,10 @@
|
||||
|
||||
# Setup directories
|
||||
ARCH=${ARCH:-x86_64}
|
||||
# ARCH selects the repository target for this script, but make and Kbuild also
|
||||
# interpret an exported ARCH themselves (Linux calls this target "arm64").
|
||||
# Keep the shell variable local to the orchestrator so PKGBUILDs see CARCH only.
|
||||
export -n ARCH
|
||||
MIRROR=${MIRROR:-edge}
|
||||
DRY_RUN=${DRY_RUN:-false}
|
||||
PKGBUILDS_DIR=${PKGBUILDS_DIR:-/pkgbuilds}
|
||||
@@ -60,14 +64,11 @@ if [[ "$DRY_RUN" != true ]]; then
|
||||
# Configure Omarchy repositories for dependency resolution
|
||||
echo "==> Configuring Omarchy repositories for dependency resolution..."
|
||||
|
||||
# Always add omarchy-build repo (for incremental builds)
|
||||
# Packages in build-output are unsigned, so use SigLevel = Never
|
||||
sudo tee -a /etc/pacman.conf > /dev/null <<EOF
|
||||
|
||||
[omarchy-build]
|
||||
SigLevel = Never
|
||||
Server = file://$BUILD_OUTPUT_DIR
|
||||
EOF
|
||||
# Always add omarchy-build repo first (for incremental builds). Repository
|
||||
# order is pacman's priority order, so this must precede the official repos;
|
||||
# otherwise pacman can select an older official package with the same name.
|
||||
# Packages in build-output are unsigned, so use SigLevel = Never.
|
||||
sudo sed -i "/^\[core\]$/i [omarchy-build]\nSigLevel = Never\nServer = file://$BUILD_OUTPUT_DIR\n" /etc/pacman.conf
|
||||
echo " -> omarchy-build (priority 1): $BUILD_OUTPUT_DIR"
|
||||
|
||||
# Initialize empty build database if it doesn't exist
|
||||
@@ -90,12 +91,7 @@ EOF
|
||||
|
||||
# Add omarchy repo if it has a database (stable packages)
|
||||
if [[ -f "$FINAL_OUTPUT_DIR/omarchy.db.tar.zst" ]] || [[ -f "$FINAL_OUTPUT_DIR/omarchy.db" ]]; then
|
||||
sudo tee -a /etc/pacman.conf > /dev/null <<EOF
|
||||
|
||||
[omarchy]
|
||||
SigLevel = Optional TrustAll
|
||||
Server = file://$FINAL_OUTPUT_DIR
|
||||
EOF
|
||||
sudo sed -i "/^\[core\]$/i [omarchy]\nSigLevel = Optional TrustAll\nServer = file://$FINAL_OUTPUT_DIR\n" /etc/pacman.conf
|
||||
echo " -> omarchy (priority 2): $FINAL_OUTPUT_DIR"
|
||||
fi
|
||||
|
||||
@@ -336,8 +332,14 @@ build_package() {
|
||||
# Ensure output directory exists
|
||||
mkdir -p "$BUILD_OUTPUT_DIR"
|
||||
|
||||
local dependency_pkg_file=""
|
||||
for pkg_file in *.pkg.tar.*; do
|
||||
[[ -f "$pkg_file" ]] && cp "$pkg_file" "$BUILD_OUTPUT_DIR/"
|
||||
[[ -f "$pkg_file" && "$pkg_file" != *.sig ]] || continue
|
||||
cp "$pkg_file" "$BUILD_OUTPUT_DIR/"
|
||||
|
||||
if [[ "$(bsdtar -xOf "$pkg_file" .PKGINFO 2>/dev/null | sed -n 's/^pkgname = //p')" == "$pkg" ]]; then
|
||||
dependency_pkg_file="$BUILD_OUTPUT_DIR/$pkg_file"
|
||||
fi
|
||||
done
|
||||
|
||||
cd "$BUILD_OUTPUT_DIR"
|
||||
@@ -353,6 +355,24 @@ build_package() {
|
||||
|
||||
cd /src/$pkg
|
||||
|
||||
# A lower-priority official repository may contain an older package with
|
||||
# the same name. Install the exact artifact we just built before building
|
||||
# its consumers, so pacman cannot select that older provider instead.
|
||||
if [[ "${INSTALL_PACKAGES[$pkg]:-}" == "1" ]]; then
|
||||
if [[ -z "$dependency_pkg_file" ]]; then
|
||||
echo " Could not find the built $pkg package to install as a dependency"
|
||||
FAILED_PACKAGES="$FAILED_PACKAGES $pkg"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo " Installing freshly built $pkg for dependent packages..."
|
||||
if ! sudo /usr/local/bin/pacman-for-makepkg -U --needed --noconfirm "$dependency_pkg_file"; then
|
||||
echo " Failed to install freshly built dependency $pkg"
|
||||
FAILED_PACKAGES="$FAILED_PACKAGES $pkg"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo " Successfully built $pkg"
|
||||
SUCCESSFUL_PACKAGES="$SUCCESSFUL_PACKAGES $pkg"
|
||||
return 0
|
||||
|
||||
@@ -69,13 +69,25 @@ setup_qemu() {
|
||||
|
||||
if [[ "$CONTAINER_ENGINE" == "podman" ]]; then
|
||||
local registration="/proc/sys/fs/binfmt_misc/qemu-$target_arch"
|
||||
if [[ -r "$registration" ]] && grep -q '^flags:.*F' "$registration"; then
|
||||
local packaged_registration="/usr/lib/binfmt.d/qemu-$target_arch-static.conf"
|
||||
local flags=""
|
||||
|
||||
if [[ -r "$registration" ]]; then
|
||||
flags=$(sed -n 's/^flags: //p' "$registration")
|
||||
fi
|
||||
|
||||
if [[ "$flags" == *F* && "$flags" == *C* ]]; then
|
||||
print_success "QEMU $target_arch emulation is registered"
|
||||
return 0
|
||||
fi
|
||||
|
||||
print_error "Rootless Podman requires host QEMU binfmt registration with the F flag"
|
||||
print_info "Install it with: sudo pacman -S qemu-user-static qemu-user-static-binfmt"
|
||||
print_error "Rootless Podman requires QEMU binfmt registration with the F and C flags"
|
||||
print_info "F keeps the emulator available inside containers; C lets container sudo preserve credentials."
|
||||
print_info "Configure it once with:"
|
||||
echo " sudo pacman -S --needed qemu-user-static qemu-user-static-binfmt"
|
||||
echo " sudo mkdir -p /etc/binfmt.d"
|
||||
echo " sed 's/:FP$/:FPC/' $packaged_registration | sudo tee /etc/binfmt.d/qemu-$target_arch-static.conf >/dev/null"
|
||||
echo " sudo systemctl restart systemd-binfmt"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
Reference in new issue
Block a user