Initial RK1 media-center image project
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
.work/
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
# Armbian base image for Turing RK1
|
||||
|
||||
This directory builds the minimal, remotely manageable base for the RK1 media
|
||||
appliance. It targets Debian 13 (Trixie), Armbian's Rockchip vendor kernel, and
|
||||
the `rk3588-turing-rk1.dtb`. Kodi and the pinned RKMPP/RGA media stack are added
|
||||
by the higher-level project layers.
|
||||
|
||||
## Build
|
||||
|
||||
Use a dedicated administrator public key. Password and root login are disabled
|
||||
in the resulting image.
|
||||
|
||||
```bash
|
||||
./build-image.sh --ssh-public-key /absolute/path/to/id_ed25519.pub
|
||||
```
|
||||
|
||||
Useful non-building checks:
|
||||
|
||||
```bash
|
||||
./tests/lint.sh
|
||||
./build-image.sh --ssh-public-key /absolute/path/to/id_ed25519.pub --prepare-only
|
||||
./build-image.sh --ssh-public-key /absolute/path/to/id_ed25519.pub --config-dump
|
||||
```
|
||||
|
||||
The framework checkout, source caches, build logs, and images live under
|
||||
`.work/armbian-build/`; completed images are in its `output/images/` directory.
|
||||
The build command creates an image and checksum but never flashes a device.
|
||||
|
||||
## What is locked
|
||||
|
||||
`userpatches/source-lock.env` pins the Armbian framework, the 6.1.115 Rockchip
|
||||
kernel source, U-Boot, Rockchip's required binary boot components, and Armbian
|
||||
firmware by commit hash. The custom `rkbin-tools` extension and framework
|
||||
`git_sources.json` override prevent the two stock moving `master` inputs from
|
||||
silently changing.
|
||||
|
||||
Debian and Armbian archive packages are resolved when the image is built, so
|
||||
byte-for-byte reproduction also requires retaining the generated package
|
||||
manifest and a snapshot of the package repositories. Every built image records
|
||||
the resolved package versions in `/usr/share/rk1-media/package-manifest.tsv`.
|
||||
|
||||
## First boot and updates
|
||||
|
||||
- `rkadmin` is created with the supplied SSH public key and passwordless sudo.
|
||||
- Root and user password hashes are replaced with an unusable value.
|
||||
- SSH password, keyboard-interactive, and root authentication are disabled.
|
||||
- Image-time SSH host keys are erased and regenerated before SSH starts.
|
||||
- Ethernet uses Armbian's systemd-networkd DHCP configuration.
|
||||
- Avahi advertises the fixed hostname `rk1-media.local`.
|
||||
- `overlays=panthor-gpu` selects Mesa's Panthor DRM path instead of libMali.
|
||||
- Armbian's independent filesystem-resize service remains enabled.
|
||||
- Debian security updates are automatic; kernel, boot, BSP, and media packages
|
||||
remain held until a rebuilt image passes hardware acceptance tests.
|
||||
|
||||
The raw Armbian image is suitable for eMMC, NVMe, or removable-media flashing.
|
||||
Always identify the destination by model, size, and serial immediately before a
|
||||
write; the build wrapper deliberately contains no flashing operation.
|
||||
Executable
+164
@@ -0,0 +1,164 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
readonly SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||
readonly PROJECT_USERPATCHES="${SCRIPT_DIR}/userpatches"
|
||||
readonly SOURCE_LOCK="${PROJECT_USERPATCHES}/source-lock.env"
|
||||
readonly FRAMEWORK_OVERRIDES="${SCRIPT_DIR}/framework-overrides"
|
||||
|
||||
die() {
|
||||
echo "build-image.sh: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: build-image.sh --ssh-public-key PATH [OPTIONS]
|
||||
|
||||
Build the source-locked Armbian Debian Trixie image for Turing RK1.
|
||||
|
||||
Options:
|
||||
--ssh-public-key PATH Required OpenSSH public-key/authorized_keys file.
|
||||
--work-dir PATH Managed framework/cache directory (default: .work).
|
||||
--prepare-only Clone/stage inputs, but do not invoke Armbian.
|
||||
--config-dump Stage inputs and run Armbian's non-building config dump.
|
||||
-h, --help Show this help.
|
||||
|
||||
The default action performs the full image build. It may ask for sudo through
|
||||
Armbian's normal native-build launcher. No image is flashed by this command.
|
||||
EOF
|
||||
}
|
||||
|
||||
validate_public_keys() {
|
||||
local key_file="${1}"
|
||||
[[ -f "${key_file}" ]] || die "public-key file does not exist: ${key_file}"
|
||||
[[ -s "${key_file}" ]] || die "public-key file is empty: ${key_file}"
|
||||
command -v ssh-keygen >/dev/null || die "ssh-keygen is required to validate the public key"
|
||||
|
||||
awk '
|
||||
/^[[:space:]]*($|#)/ { next }
|
||||
$1 !~ /^(ssh-ed25519|ssh-rsa|ecdsa-sha2-nistp(256|384|521)|[email protected]|[email protected])$/ { exit 1 }
|
||||
{ count++ }
|
||||
END { if (count < 1) exit 1 }
|
||||
' "${key_file}" || die "use plain OpenSSH public keys without authorized_keys options"
|
||||
ssh-keygen -l -f "${key_file}" >/dev/null || die "ssh-keygen rejected the supplied public-key file"
|
||||
}
|
||||
|
||||
prepare_framework() {
|
||||
local work_root="${1}"
|
||||
local framework_dir="${work_root}/armbian-build"
|
||||
local origin
|
||||
|
||||
install -d -m 0755 "${work_root}"
|
||||
work_root="$(cd -- "${work_root}" && pwd -P)"
|
||||
framework_dir="${work_root}/armbian-build"
|
||||
[[ "${work_root}" != "/" ]] || die "refusing to use / as the work directory"
|
||||
|
||||
if [[ ! -e "${framework_dir}" ]]; then
|
||||
git init "${framework_dir}" >/dev/null
|
||||
git -C "${framework_dir}" remote add origin "${RK1_MEDIA_ARMBIAN_BUILD_URL}"
|
||||
install -m 0600 /dev/null "${framework_dir}/.rk1-media-build-root"
|
||||
fi
|
||||
|
||||
[[ -d "${framework_dir}/.git" ]] || die "work path is not a Git checkout: ${framework_dir}"
|
||||
[[ -f "${framework_dir}/.rk1-media-build-root" ]] || die "work checkout is not managed by this script: ${framework_dir}"
|
||||
origin="$(git -C "${framework_dir}" remote get-url origin)"
|
||||
[[ "${origin}" == "${RK1_MEDIA_ARMBIAN_BUILD_URL}" ]] || die "unexpected Armbian origin: ${origin}"
|
||||
|
||||
if git -C "${framework_dir}" rev-parse --verify HEAD >/dev/null 2>&1; then
|
||||
git -C "${framework_dir}" diff --quiet || die "tracked modifications exist in ${framework_dir}"
|
||||
git -C "${framework_dir}" diff --cached --quiet || die "staged modifications exist in ${framework_dir}"
|
||||
fi
|
||||
|
||||
if ! git -C "${framework_dir}" cat-file -e "${RK1_MEDIA_ARMBIAN_BUILD_COMMIT}^{commit}" 2>/dev/null; then
|
||||
git -C "${framework_dir}" fetch --depth=1 origin "${RK1_MEDIA_ARMBIAN_BUILD_COMMIT}"
|
||||
fi
|
||||
git -C "${framework_dir}" checkout --detach "${RK1_MEDIA_ARMBIAN_BUILD_COMMIT}" >/dev/null
|
||||
|
||||
printf '%s\n' "${framework_dir}"
|
||||
}
|
||||
|
||||
stage_userpatches() {
|
||||
local framework_dir="${1}"
|
||||
local public_key="${2}"
|
||||
local destination="${framework_dir}/userpatches"
|
||||
|
||||
[[ -f "${framework_dir}/.rk1-media-build-root" ]] || die "refusing to stage into an unmanaged checkout"
|
||||
[[ "${destination}" == "${framework_dir}/userpatches" ]] || die "internal userpatch path check failed"
|
||||
[[ ! -L "${destination}" ]] || die "refusing to replace a symlinked userpatches directory"
|
||||
if [[ -e "${destination}" ]]; then
|
||||
[[ -f "${destination}/.rk1-media-managed" ]] || die "existing userpatches are not managed by this script"
|
||||
rm -rf -- "${destination}"
|
||||
fi
|
||||
|
||||
install -d -m 0755 "${destination}"
|
||||
cp -a "${PROJECT_USERPATCHES}/." "${destination}/"
|
||||
install -m 0600 /dev/null "${destination}/.rk1-media-managed"
|
||||
install -d -m 0700 "${destination}/overlay/build-input"
|
||||
install -m 0600 "${public_key}" "${destination}/overlay/build-input/authorized_keys"
|
||||
install -m 0644 "${SOURCE_LOCK}" "${destination}/overlay/build-input/source-lock.env"
|
||||
|
||||
# Armbian supports immutable resolutions for otherwise moving branch inputs
|
||||
# through config/sources/git_sources.json. This pins its firmware artifact.
|
||||
cp -a "${FRAMEWORK_OVERRIDES}/." "${framework_dir}/"
|
||||
}
|
||||
|
||||
main() {
|
||||
local public_key=""
|
||||
local work_dir="${SCRIPT_DIR}/.work"
|
||||
local mode="build"
|
||||
local framework_dir
|
||||
|
||||
while (($#)); do
|
||||
case "${1}" in
|
||||
--ssh-public-key)
|
||||
(($# >= 2)) || die "--ssh-public-key requires a path"
|
||||
public_key="${2}"
|
||||
shift 2
|
||||
;;
|
||||
--work-dir)
|
||||
(($# >= 2)) || die "--work-dir requires a path"
|
||||
work_dir="${2}"
|
||||
shift 2
|
||||
;;
|
||||
--prepare-only)
|
||||
mode="prepare"
|
||||
shift
|
||||
;;
|
||||
--config-dump)
|
||||
mode="config-dump"
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*) die "unknown option: ${1}" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -n "${public_key}" ]] || die "--ssh-public-key is required; the image never enables password login"
|
||||
[[ -r "${SOURCE_LOCK}" ]] || die "source lock is missing: ${SOURCE_LOCK}"
|
||||
# shellcheck source=userpatches/source-lock.env
|
||||
source "${SOURCE_LOCK}"
|
||||
validate_public_keys "${public_key}"
|
||||
framework_dir="$(prepare_framework "${work_dir}")"
|
||||
stage_userpatches "${framework_dir}" "${public_key}"
|
||||
|
||||
echo "Prepared Armbian ${RK1_MEDIA_ARMBIAN_BUILD_COMMIT} in ${framework_dir}"
|
||||
case "${mode}" in
|
||||
prepare)
|
||||
echo "Configuration staged; no build was started."
|
||||
;;
|
||||
config-dump)
|
||||
(cd "${framework_dir}" && CONFIG_DEFS_ONLY=yes ./compile.sh rk1-media config-dump)
|
||||
;;
|
||||
build)
|
||||
(cd "${framework_dir}" && ./compile.sh rk1-media build)
|
||||
echo "Images and checksums: ${framework_dir}/output/images"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -0,0 +1,7 @@
|
||||
[
|
||||
{
|
||||
"source": "https://github.com/armbian/firmware",
|
||||
"branch": "master",
|
||||
"sha1": "d9846710f54da5e4383e2d67311819659ac2cf5c"
|
||||
}
|
||||
]
|
||||
Executable
+54
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
readonly ARMBIAN_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd -P)"
|
||||
|
||||
bash -n \
|
||||
"${ARMBIAN_DIR}/build-image.sh" \
|
||||
"${ARMBIAN_DIR}/userpatches/config-rk1-media.conf" \
|
||||
"${ARMBIAN_DIR}/userpatches/customize-image.sh" \
|
||||
"${ARMBIAN_DIR}/userpatches/extensions/rkbin-tools.sh" \
|
||||
"${ARMBIAN_DIR}/userpatches/overlay/rootfs/usr/local/sbin/rk1-media-first-boot"
|
||||
|
||||
# shellcheck source=../userpatches/source-lock.env
|
||||
source "${ARMBIAN_DIR}/userpatches/source-lock.env"
|
||||
for revision in \
|
||||
"${RK1_MEDIA_ARMBIAN_BUILD_COMMIT}" \
|
||||
"${RK1_MEDIA_KERNEL_COMMIT}" \
|
||||
"${RK1_MEDIA_UBOOT_COMMIT}" \
|
||||
"${RK1_MEDIA_RKBIN_COMMIT}" \
|
||||
"${RK1_MEDIA_FIRMWARE_COMMIT}"; do
|
||||
[[ "${revision}" =~ ^[0-9a-f]{40}$ ]] || { echo "Invalid pinned revision: ${revision}" >&2; exit 1; }
|
||||
done
|
||||
|
||||
jq -e --arg revision "${RK1_MEDIA_FIRMWARE_COMMIT}" \
|
||||
'. == [{"source":"https://github.com/armbian/firmware","branch":"master","sha1":$revision}]' \
|
||||
"${ARMBIAN_DIR}/framework-overrides/config/sources/git_sources.json" >/dev/null
|
||||
|
||||
[[ ! -e "${ARMBIAN_DIR}/userpatches/overlay/build-input/authorized_keys" ]] || {
|
||||
echo "A staged administrator key must not be committed to userpatches/overlay/build-input" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
if command -v apt-config >/dev/null; then
|
||||
apt_dump="$(apt-config -c "${ARMBIAN_DIR}/userpatches/overlay/rootfs/etc/apt/apt.conf.d/52rk1-media-unattended-upgrades" dump)"
|
||||
[[ "$(grep -c '^Unattended-Upgrade::Origins-Pattern:: ' <<< "${apt_dump}")" == "1" ]] || {
|
||||
echo "Unattended upgrades must contain exactly one allowed origin" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -q 'codename=${distro_codename}-security' <<< "${apt_dump}" || {
|
||||
echo "Debian security origin is missing from unattended-upgrades policy" >&2
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
|
||||
if command -v shellcheck >/dev/null; then
|
||||
shellcheck --exclude=SC1091,SC2154 \
|
||||
"${ARMBIAN_DIR}/build-image.sh" \
|
||||
"${ARMBIAN_DIR}/userpatches/config-rk1-media.conf" \
|
||||
"${ARMBIAN_DIR}/userpatches/customize-image.sh" \
|
||||
"${ARMBIAN_DIR}/userpatches/extensions/rkbin-tools.sh" \
|
||||
"${ARMBIAN_DIR}/userpatches/overlay/rootfs/usr/local/sbin/rk1-media-first-boot"
|
||||
fi
|
||||
|
||||
echo "Armbian scaffolding checks passed."
|
||||
@@ -0,0 +1,2 @@
|
||||
0.1.0
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# shellcheck shell=bash
|
||||
|
||||
# Armbian image identity and target.
|
||||
BOARD="turing-rk1"
|
||||
BRANCH="vendor"
|
||||
RELEASE="trixie"
|
||||
BUILD_MINIMAL="yes"
|
||||
BUILD_DESKTOP="no"
|
||||
KERNEL_CONFIGURE="no"
|
||||
UBOOT_CONFIGURE="no"
|
||||
INSTALL_HEADERS="no"
|
||||
EXPERT="yes" # Turing RK1 is an Armbian community-supported board.
|
||||
|
||||
# Image layout and deterministic build choices.
|
||||
ROOTFS_TYPE="ext4"
|
||||
EXTRA_ROOTFS_MIB_SIZE="1536"
|
||||
COMPRESS_OUTPUTIMAGE="sha,xz"
|
||||
IMAGE_XZ_COMPRESSION_RATIO="6"
|
||||
NETWORKING_STACK="systemd-networkd"
|
||||
SHARE_LOGS="no"
|
||||
BETA="no"
|
||||
USE_CCACHE="no"
|
||||
|
||||
# Runtime defaults. The temporary build password is overwritten with an
|
||||
# unusable shadow value by customize-image.sh; no password works in the image.
|
||||
HOST="rk1-media"
|
||||
VENDOR="RK1 Media"
|
||||
VENDORURL="https://github.com/armbian/build"
|
||||
ROOTPWD="RK1_IMAGE_LOGIN_DISABLED"
|
||||
CONSOLE_AUTOLOGIN="no"
|
||||
DESKTOP_AUTOLOGIN="no"
|
||||
OPENSSHD_REGENERATE_HOST_KEYS="false"
|
||||
|
||||
# This file is copied with the rest of userpatches by build-image.sh.
|
||||
# shellcheck source=source-lock.env
|
||||
source "${BASH_SOURCE%/*}/source-lock.env"
|
||||
|
||||
# The board and family definitions intentionally use moving branches. Override
|
||||
# them after those definitions have run while retaining Armbian's matching
|
||||
# vendor patch directories.
|
||||
function post_family_config__999_rk1_media_pin_boot_sources() {
|
||||
[[ "${BOARD}" == "turing-rk1" ]] || exit_with_error "RK1 media config used with the wrong board" "${BOARD}"
|
||||
[[ "${BRANCH}" == "vendor" ]] || exit_with_error "RK1 media config requires BRANCH=vendor" "${BRANCH}"
|
||||
|
||||
declare -g KERNELSOURCE="${RK1_MEDIA_KERNEL_URL}"
|
||||
declare -g KERNELBRANCH="commit:${RK1_MEDIA_KERNEL_COMMIT}"
|
||||
declare -g KERNEL_MAJOR_MINOR="${RK1_MEDIA_KERNEL_SERIES}"
|
||||
declare -g KERNELPATCHDIR="${RK1_MEDIA_KERNEL_PATCHSET}"
|
||||
|
||||
declare -g BOOTSOURCE="${RK1_MEDIA_UBOOT_URL}"
|
||||
declare -g BOOTBRANCH="commit:${RK1_MEDIA_UBOOT_COMMIT}"
|
||||
declare -g BOOTPATCHDIR="${RK1_MEDIA_UBOOT_PATCHSET}"
|
||||
}
|
||||
|
||||
function user_config__200_rk1_media_base_packages() {
|
||||
[[ "${RELEASE}" == "trixie" ]] || exit_with_error "RK1 media config requires Debian Trixie" "${RELEASE}"
|
||||
|
||||
add_packages_to_image \
|
||||
openssh-server \
|
||||
sudo \
|
||||
avahi-daemon \
|
||||
libnss-mdns \
|
||||
unattended-upgrades \
|
||||
ca-certificates \
|
||||
curl \
|
||||
jq
|
||||
|
||||
# Do not inherit the build host's locale/time zone.
|
||||
declare -g DEST_LANG="en_US.UTF-8"
|
||||
declare -g TZDATA="Etc/UTC"
|
||||
}
|
||||
|
||||
Executable
+136
@@ -0,0 +1,136 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
RELEASE="${1:?missing Armbian release}"
|
||||
LINUXFAMILY="${2:?missing Linux family}"
|
||||
BOARD="${3:?missing board}"
|
||||
BUILD_DESKTOP="${4:?missing desktop flag}"
|
||||
ARCH="${5:?missing architecture}"
|
||||
|
||||
readonly RELEASE LINUXFAMILY BOARD BUILD_DESKTOP ARCH
|
||||
readonly OVERLAY_ROOT="/tmp/overlay/rootfs"
|
||||
readonly AUTHORIZED_KEYS_INPUT="/tmp/overlay/build-input/authorized_keys"
|
||||
readonly SOURCE_LOCK_INPUT="/tmp/overlay/build-input/source-lock.env"
|
||||
|
||||
fail() {
|
||||
echo "rk1-media customize: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
configure_identity() {
|
||||
printf '%s\n' "rk1-media" > /etc/hostname
|
||||
if grep -Eq '^127\.0\.1\.1[[:space:]]' /etc/hosts; then
|
||||
sed -Ei 's/^127\.0\.1\.1[[:space:]].*$/127.0.1.1 rk1-media/' /etc/hosts
|
||||
else
|
||||
printf '%s\n' '127.0.1.1 rk1-media' >> /etc/hosts
|
||||
fi
|
||||
}
|
||||
|
||||
configure_boot() {
|
||||
local env_file="/boot/armbianEnv.txt"
|
||||
local overlays
|
||||
[[ -f "${env_file}" ]] || fail "Armbian boot environment is missing: ${env_file}"
|
||||
|
||||
if grep -q '^overlays=' "${env_file}"; then
|
||||
overlays="$(sed -n 's/^overlays=//p' "${env_file}" | head -n 1)"
|
||||
case " ${overlays} " in
|
||||
*" panthor-gpu "*) ;;
|
||||
*) sed -i "0,/^overlays=.*/s//overlays=${overlays} panthor-gpu/" "${env_file}" ;;
|
||||
esac
|
||||
else
|
||||
printf '%s\n' 'overlays=panthor-gpu' >> "${env_file}"
|
||||
fi
|
||||
}
|
||||
|
||||
configure_admin() {
|
||||
if ! getent group rkadmin >/dev/null; then
|
||||
groupadd rkadmin
|
||||
fi
|
||||
if ! id rkadmin >/dev/null 2>&1; then
|
||||
useradd --create-home --gid rkadmin --shell /bin/bash --comment "RK1 administrator" rkadmin
|
||||
else
|
||||
usermod --gid rkadmin rkadmin
|
||||
fi
|
||||
|
||||
local group groups_csv
|
||||
local -a groups=(sudo adm systemd-journal audio video render input)
|
||||
local -a available_groups=()
|
||||
for group in "${groups[@]}"; do
|
||||
getent group "${group}" >/dev/null && available_groups+=("${group}")
|
||||
done
|
||||
groups_csv="$(IFS=,; echo "${available_groups[*]}")"
|
||||
[[ -z "${groups_csv}" ]] || usermod --append --groups "${groups_csv}" rkadmin
|
||||
|
||||
install -d -o rkadmin -g rkadmin -m 0700 /home/rkadmin/.ssh
|
||||
install -o rkadmin -g rkadmin -m 0600 "${AUTHORIZED_KEYS_INPUT}" /home/rkadmin/.ssh/authorized_keys
|
||||
install -m 0440 /dev/null /etc/sudoers.d/90-rkadmin
|
||||
printf '%s\n' 'rkadmin ALL=(ALL:ALL) NOPASSWD: ALL' > /etc/sudoers.d/90-rkadmin
|
||||
visudo --check --file=/etc/sudoers.d/90-rkadmin >/dev/null
|
||||
|
||||
# Replace (rather than merely prefix) the build-time password hashes.
|
||||
usermod --password '!' root
|
||||
usermod --password '!' rkadmin
|
||||
rm -f /root/.not_logged_in_yet
|
||||
}
|
||||
|
||||
hold_platform_packages() {
|
||||
local package
|
||||
local -a held=()
|
||||
while IFS= read -r package; do
|
||||
case "${package}" in
|
||||
linux-image-*|linux-dtb-*|linux-u-boot-*|armbian-bsp-*)
|
||||
apt-mark hold "${package}" >/dev/null
|
||||
held+=("${package}")
|
||||
;;
|
||||
esac
|
||||
done < <(dpkg-query --show --showformat='${binary:Package}\n')
|
||||
printf '%s\n' "${held[@]}" | LC_ALL=C sort -u > /usr/share/rk1-media/held-packages.txt
|
||||
}
|
||||
|
||||
configure_services() {
|
||||
install -d -m 0755 /var/lib/rk1-media
|
||||
install -m 0600 /dev/null /var/lib/rk1-media/first-boot.pending
|
||||
|
||||
# Validate the complete SSH configuration, then remove generated host keys so
|
||||
# every flashed module creates a unique set before ssh.service can start.
|
||||
ssh-keygen -A
|
||||
/usr/sbin/sshd -t
|
||||
rm -f /etc/ssh/ssh_host_*
|
||||
|
||||
systemctl enable rk1-media-first-boot.service
|
||||
systemctl enable ssh.service
|
||||
systemctl enable avahi-daemon.service
|
||||
systemctl enable apt-daily.timer
|
||||
systemctl enable apt-daily-upgrade.timer
|
||||
}
|
||||
|
||||
write_build_manifest() {
|
||||
install -d -m 0755 /usr/share/rk1-media
|
||||
install -m 0644 "${SOURCE_LOCK_INPUT}" /usr/share/rk1-media/source-lock.env
|
||||
dpkg-query --show --showformat='${binary:Package}\t${Version}\t${Architecture}\n' \
|
||||
| LC_ALL=C sort > /usr/share/rk1-media/package-manifest.tsv
|
||||
}
|
||||
|
||||
main() {
|
||||
[[ "${RELEASE}" == "trixie" ]] || fail "unexpected release: ${RELEASE}"
|
||||
[[ "${BOARD}" == "turing-rk1" ]] || fail "unexpected board: ${BOARD}"
|
||||
[[ "${BUILD_DESKTOP}" == "no" ]] || fail "desktop images are not supported by this customization"
|
||||
[[ "${ARCH}" == "arm64" ]] || fail "unexpected architecture: ${ARCH}"
|
||||
[[ -d "${OVERLAY_ROOT}" ]] || fail "rootfs overlay is missing"
|
||||
[[ -s "${AUTHORIZED_KEYS_INPUT}" ]] || fail "authorized_keys build input is missing"
|
||||
[[ -s "${SOURCE_LOCK_INPUT}" ]] || fail "source lock build input is missing"
|
||||
|
||||
cp -a "${OVERLAY_ROOT}/." /
|
||||
configure_identity
|
||||
configure_boot
|
||||
configure_admin
|
||||
write_build_manifest
|
||||
hold_platform_packages
|
||||
configure_services
|
||||
|
||||
# systemd creates a unique machine ID on the first real boot.
|
||||
: > /etc/machine-id
|
||||
rm -f /var/lib/dbus/machine-id
|
||||
}
|
||||
|
||||
main "$@"
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Source-locked replacement for Armbian's rkbin-tools extension. The upstream
|
||||
# extension follows branch:master, which makes otherwise pinned builds drift.
|
||||
|
||||
function fetch_sources_tools__rkbin_tools() {
|
||||
: "${RK1_MEDIA_RKBIN_URL:?source-lock.env did not set RK1_MEDIA_RKBIN_URL}"
|
||||
: "${RK1_MEDIA_RKBIN_COMMIT:?source-lock.env did not set RK1_MEDIA_RKBIN_COMMIT}"
|
||||
fetch_from_repo "${RK1_MEDIA_RKBIN_URL}" "rkbin-tools" "commit:${RK1_MEDIA_RKBIN_COMMIT}"
|
||||
}
|
||||
|
||||
function build_host_tools__install_rkbin_tools() {
|
||||
cd "${SRC}/cache/sources/rkbin-tools" || exit
|
||||
if [[ ! -f .commit_id || "$(improved_git rev-parse @ 2>/dev/null)" != "$(< .commit_id)" || ! -f /usr/local/bin/loaderimage ]]; then
|
||||
display_alert "Installing" "source-locked rkbin tools" "info"
|
||||
mkdir -p /usr/local/bin/
|
||||
install -m 0755 tools/loaderimage /usr/local/bin/
|
||||
install -m 0755 tools/trust_merger /usr/local/bin/
|
||||
improved_git rev-parse @ 2>/dev/null > .commit_id
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
APT::Periodic::Update-Package-Lists "1";
|
||||
APT::Periodic::Unattended-Upgrade "1";
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
// Security fixes may install automatically. Platform/media packages remain
|
||||
// pinned until a rebuilt image passes the RK1 hardware acceptance suite.
|
||||
#clear Unattended-Upgrade::Allowed-Origins;
|
||||
#clear Unattended-Upgrade::Origins-Pattern;
|
||||
|
||||
Unattended-Upgrade::Origins-Pattern {
|
||||
"origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
|
||||
};
|
||||
|
||||
Unattended-Upgrade::Package-Blacklist {
|
||||
"^linux-image-.*$";
|
||||
"^linux-dtb-.*$";
|
||||
"^linux-u-boot-.*$";
|
||||
"^armbian-bsp-.*$";
|
||||
"^mesa-.*$";
|
||||
"^kodi.*$";
|
||||
"^rknn.*$";
|
||||
"^rockchip.*$";
|
||||
};
|
||||
|
||||
Unattended-Upgrade::Automatic-Reboot "false";
|
||||
Unattended-Upgrade::Remove-Unused-Kernel-Packages "false";
|
||||
@@ -0,0 +1,8 @@
|
||||
# Generated by rk1-media-image. Administrative access is SSH-key-only.
|
||||
PermitRootLogin no
|
||||
PasswordAuthentication no
|
||||
KbdInteractiveAuthentication no
|
||||
PubkeyAuthentication yes
|
||||
AuthenticationMethods publickey
|
||||
PermitEmptyPasswords no
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=RK1 media image first-boot identity setup
|
||||
After=local-fs.target
|
||||
Before=ssh.service sshd.service
|
||||
ConditionPathExists=/var/lib/rk1-media/first-boot.pending
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/sbin/rk1-media-first-boot
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
[Unit]
|
||||
Requires=rk1-media-first-boot.service
|
||||
After=rk1-media-first-boot.service
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
umask 077
|
||||
|
||||
readonly MARKER="/var/lib/rk1-media/first-boot.pending"
|
||||
[[ -e "${MARKER}" ]] || exit 0
|
||||
|
||||
rm -f /etc/ssh/ssh_host_*
|
||||
ssh-keygen -A
|
||||
|
||||
found_key="no"
|
||||
for private_key in /etc/ssh/ssh_host_*_key; do
|
||||
if [[ -s "${private_key}" ]]; then
|
||||
found_key="yes"
|
||||
break
|
||||
fi
|
||||
done
|
||||
[[ "${found_key}" == "yes" ]] || { echo "No SSH host key was generated" >&2; exit 1; }
|
||||
|
||||
/usr/sbin/sshd -t
|
||||
rm -f "${MARKER}"
|
||||
sync
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Source revisions resolved on 2026-08-16.
|
||||
#
|
||||
# This file is sourced by both build-image.sh and Armbian's user configuration.
|
||||
# Keep values shell-safe (no command substitutions or unquoted whitespace).
|
||||
|
||||
RK1_MEDIA_ARMBIAN_BUILD_URL="https://github.com/armbian/build.git"
|
||||
RK1_MEDIA_ARMBIAN_BUILD_COMMIT="ea18947bed789c829a260df129e815c353c14908"
|
||||
|
||||
RK1_MEDIA_KERNEL_URL="https://github.com/armbian/linux-rockchip.git"
|
||||
RK1_MEDIA_KERNEL_COMMIT="5280f9b4336199c4025c8eed894d2b4e2268dcc6"
|
||||
RK1_MEDIA_KERNEL_VERSION="6.1.115"
|
||||
RK1_MEDIA_KERNEL_SERIES="6.1"
|
||||
RK1_MEDIA_KERNEL_PATCHSET="rk35xx-vendor-6.1"
|
||||
|
||||
RK1_MEDIA_UBOOT_URL="https://github.com/u-boot/u-boot.git"
|
||||
RK1_MEDIA_UBOOT_COMMIT="ece349ade2973e220f524ce59e59711cc919263f"
|
||||
RK1_MEDIA_UBOOT_PATCHSET="v2026.07"
|
||||
|
||||
RK1_MEDIA_RKBIN_URL="https://github.com/armbian/rkbin.git"
|
||||
RK1_MEDIA_RKBIN_COMMIT="452f49a987097d7ca675811e51a873b42ebd101f"
|
||||
|
||||
RK1_MEDIA_FIRMWARE_URL="https://github.com/armbian/firmware"
|
||||
RK1_MEDIA_FIRMWARE_COMMIT="d9846710f54da5e4383e2d67311819659ac2cf5c"
|
||||
Reference in New Issue
Block a user