#!/usr/bin/env bash # SilverMetal Linux — inner build step. # # Runs *inside* the silvermetal-builder container, as the unprivileged # `user` (uid 1000). build.sh's docker-run cmd chowns the workspace and # sudoes here. The container's PID 1 is systemd (upstream's # systemd-in-container pattern), so any `systemctl` calls derivative- # maker makes — to start approx, daemon-reload, etc. — actually do # what they're supposed to. derivative-maker uses sudo internally for # its privileged ops. # # Why this is its own file: # The previous incarnation lived as a heredoc inside build.sh's docker # run command. Once we needed to drop privileges from root to user, # the nested-heredoc / nested-quoting situation became unreadable; a # plain script with normal quoting is far easier to maintain. # # Required env vars (set by build.sh and forwarded into the container): # REPO_ROOT — absolute path to the SilverMetal repo root # BUILD_DIR — where to drop the resulting *.iso and manifests # SOURCE_DATE_EPOCH — reproducibility timestamp (forwarded to live-build) # SNAPSHOT_TIMESTAMP — apt snapshot pin (forwarded to live-build) set -euo pipefail : "${REPO_ROOT:?REPO_ROOT must be set}" : "${BUILD_DIR:?BUILD_DIR must be set}" # Explicit user_name pin. # derivative-maker/help-steps/variables (lines 80-93) computes user_name # from $SUDO_USER as its first non-empty fallback. We enter this script # via `sudo --preserve-env -u user --` from root, which makes sudo set # SUDO_USER=root (the *calling* user). Variables.sh then picks # user_name="root" and computes HOMEVAR=/home/root — which doesn't exist # (root's home is /root). The first thing that breaks under that path # is the aptgetopt config tee in 1100_sanity-tests: # tee: /home/root/derivative-binary/30_derivative-maker.conf: # No such file or directory # Setting user_name explicitly satisfies the first-priority check in # variables.sh and short-circuits the SUDO_USER fallback. export user_name=user # Create the binary output directory derivative-maker writes into. # variables.sh sets binary_build_folder_dist=$HOMEVAR/derivative-binary # (= /home/user/derivative-binary), and 1100_sanity-tests / later steps # expect it to exist. Upstream's docker-start does the equivalent # `mkdir --parents -- "${HOME}/derivative-binary"`; we replicate that # here so we don't depend on upstream's wrapper. mkdir -p "${HOME}/derivative-binary" # Import Debian developer keys into the user's GPG keyring. # 2100_create-debian-packages calls `dm-reprepro-wrapper includedsc` # on Debian source packages it pulls in (e.g. virtualbox_*.dsc, even # for --target iso — see 2100_create-debian-packages line 114), and # reprepro verifies each .dsc's signature against the user's keyring. # Without this, every dsc with a Debian-uploader signature fails: # Could not check validity of signature with '' in # '...virtualbox_7.2.8-dfsg-1.dsc' as public key missing! # There have been errors! # debian-keyring (~40 MB, snapshot-pinned) provides the developer # keys; importing it once at the start of the build seeds the keyring # reprepro will consult. if [ -d /usr/share/keyrings ]; then for f in /usr/share/keyrings/debian-keyring.gpg \ /usr/share/keyrings/debian-maintainers.gpg \ /usr/share/keyrings/debian-nonupload.gpg; do [ -f "$f" ] || continue gpg --quiet --no-tty --import "$f" 2>/dev/null || true done fi # shellcheck disable=SC1091 source "${REPO_ROOT}/linux/build/config/silvermetal-base.conf" cd "${REPO_ROOT}/linux/build/derivative-maker" # CLI grammar comes from derivative-maker/help-steps/parse-cmd. The # valid options are a closed set; passing anything else (including # --build, --dist, or --config) trips the "unknown option" guard at # parse-cmd line 725. Spelling matters too: upstream uses --flavor # (American), not --flavour. --freedom is mandatory for amd64/i386. # Dist is implicit from --flavor (kicksecure-cli => trixie), and # the silvermetal-base.conf is sourced into the env above rather than # passed as a flag because derivative-maker has no --config option. # # --allow-untagged true / --allow-uncommitted true: the pinned upstream # tag (18.1.7.4-developers-only — name says it all) deliberately ships # with some submodules at intermediate / merge commits. sq-git still # verifies every signature in the chain — these flags only relax the # additional "must be at a release tag" check. Appropriate for a # downstream consumer pinned to a developer tag. ./derivative-maker \ --flavor "${DERIVATIVE_FLAVOUR}" \ --target "${DERIVATIVE_BUILD_TARGET}" \ --arch "${DERIVATIVE_TARGET_ARCH}" \ --freedom "${DERIVATIVE_FREEDOM}" \ --allow-untagged true \ --allow-uncommitted true # derivative-maker writes its outputs into ${HOME}/derivative-binary # (per help-steps/variables: binary_build_folder_dist=$HOMEVAR/derivative-binary), # *not* into the source tree. Collect from there into BUILD_DIR. # Exact upstream output paths can shift between tags — keep this tolerant. find "${HOME}/derivative-binary" -maxdepth 6 -type f -name "*.iso" -print0 \ | xargs -0 -I{} cp -av "{}" "${BUILD_DIR}/" # Manifest of file metadata that lives inside the ISO. Useful when # diagnosing reproducibility regressions without re-extracting. find "${HOME}/derivative-binary" -maxdepth 6 -type f -name "*.manifest" -print0 \ | xargs -0 -I{} cp -av "{}" "${BUILD_DIR}/" 2>/dev/null || true