10 KiB
10 KiB
Zero-OS Builder – Working Notes and Repository Map
Purpose
- This document captures operational knowledge of this repository: build flow, key files, flags, and recent behavior decisions (e.g., passwordless root).
- Links below point to exact functions and files for fast triage, using code navigation-friendly anchors.
Repository Overview
- Build entrypoint: scripts/build.sh
- Orchestrates incremental stages using stage markers.
- Runs inside a container defined by Dockerfile for reproducibility.
- Common utilities and config loading: bash.common.sh
- Loads config/build.conf, normalizes directory paths, provides logging and safe execution wrappers.
- Initramfs assembly and finalization: bash.initramfs_* functions
- Copies components, sets up zinit configs, finalizes branding, creates CPIO archive, validates contents.
- Kernel integration (optional embedded initramfs): bash.kernel_* functions
- Downloads/configures/builds kernel and modules, embeds initramfs, runs depmod.
- zinit configuration: config/zinit/
- YAML service definitions and init scripts used by zinit inside the initramfs rootfs.
- RFS tooling (modules/firmware flists): scripts/rfs/
- Packs module/firmware flists and embeds them into initramfs at /etc/rfs.
Container Tooling (dev-container)
- Base image: Alpine 3.22 in Dockerfile
- Tools:
- shadow (passwd/chpasswd): required for root password management in initramfs.
- openssl, openssl-dev: kept for other build steps and potential hashing utilities.
- build-base, rustup, kmod, upx, etc.: required by various build stages.
- Removed: perl, not required for password handling after switching to passwd/chpasswd workflow.
Configuration – build.conf
- File: config/build.conf
- Key variables:
- Versions: ALPINE_VERSION, KERNEL_VERSION
- Directories (relative in config, normalized to absolute during runtime):
- INSTALL_DIR="initramfs"
- COMPONENTS_DIR="components"
- KERNEL_DIR="kernel"
- DIST_DIR="dist"
- Flags:
- ZEROOS_BRANDING="true"
- ZEROOS_REBRANDING="true"
- Branding behavior:
- ZEROOS_PASSWORDLESS_ROOT="true" (default for branded builds in current policy)
- ZEROOS_ROOT_PASSWORD_HASH / ROOT_PASSWORD_HASH (not used in current policy)
- ZEROOS_ROOT_PASSWORD / ROOT_PASSWORD (not used in current policy)
- FIRMWARE_TAG optional for reproducible firmware flist naming.
Absolute Path Normalization
- Location: bash.common.sh
- After sourcing build.conf, the following variables are normalized to absolute paths anchored at PROJECT_ROOT:
- INSTALL_DIR, COMPONENTS_DIR, KERNEL_DIR, DIST_DIR
- Rationale: Prevents path resolution errors when CWD changes (e.g., when kernel build operates in /workspace/kernel/current, validation now resolves to /workspace/initramfs instead of /workspace/kernel/current/initramfs).
Build Pipeline – High Level
- Orchestrator: bash.main_build_process()
- Stage list:
- alpine_extract
- alpine_configure
- alpine_packages
- alpine_firmware
- components_build
- components_verify
- kernel_modules
- init_script
- components_copy
- zinit_setup
- modules_setup
- modules_copy
- cleanup
- rfs_flists
- validation
- initramfs_create
- initramfs_test
- kernel_build
- boot_tests
- Each stage wrapped with bash.stage_run() and tracked under .build-stages/
- Stage list:
- Container use:
- Always run in container for stable toolchain (podman/docker auto-detected).
- Inside container, CWD normalized to PROJECT_ROOT.
Initramfs Assembly – Key Functions
- zinit setup: bash.initramfs_setup_zinit()
- Copies config/zinit into /etc/zinit, fixes perms, removes OpenRC remnants.
- Install init script: bash.initramfs_install_init_script()
- Installs config/init as /init in initramfs root.
- Components copy: bash.initramfs_copy_components()
- Installs built components (zinit/rfs/mycelium/corex) into proper locations, strips/UPX where applicable.
- Modules setup: bash.initramfs_setup_modules()
- Reads config/modules.conf, resolves deps via bash.initramfs_resolve_module_dependencies(), generates stage1 list with firmware correlation.
- Create module scripts: bash.initramfs_create_module_scripts()
- Writes /etc/zinit/init/stage1-modules.sh and stage2-modules.sh for zinit to load modules.
- Binary size optimization: bash.initramfs_strip_and_upx()
- Final customization: bash.initramfs_finalize_customization()
- See “Branding behavior” below.
- Create archive: bash.initramfs_create_cpio()
- Calls finalize, runs sanity checks, and creates initramfs.cpio.xz.
- Validate: bash.initramfs_validate()
- Ensures essential items exist, logs debug info:
- Prints “Validation debug:” lines showing input, PWD, PROJECT_ROOT, INSTALL_DIR, and resolved path.
- Ensures essential items exist, logs debug info:
Kernel Integration
- Get full kernel version: bash.kernel_get_full_version()
- Apply config (embed initramfs): bash.kernel_apply_config()
- Updates CONFIG_INITRAMFS_SOURCE to the archive’s absolute path via bash.kernel_modify_config_for_initramfs().
- Build kernel: bash.kernel_build_with_initramfs()
- Build and install modules in container: bash.kernel_build_modules()
- Installs modules to /lib/modules/$FULL_VERSION in container, runs depmod -a.
RFS Flists (modules/firmware)
- Packing scripts:
- Modules: bash.pack-modules.sh
- Firmware: bash.pack-firmware.sh
- Integrated in stage_rfs_flists:
- Embeds /etc/rfs/modules-<FULL_KERNEL_VERSION>.fl
- Embeds /etc/rfs/firmware-latest.fl (or tagged by FIRMWARE_TAG)
- See bash.main_build_process() — stage_rfs_flists
Branding Behavior (Passwordless Root, motd/issue)
- Finalization hook: bash.initramfs_finalize_customization()
- Behavior (current policy):
- Passwordless root enforced using passwd for shadow-aware deletion:
- bash.initramfs_finalize_customization():
- passwd -d -R "${initramfs_dir}" root
- Ensures /etc/shadow has root:: (empty password) inside initramfs root, not host.
- bash.initramfs_finalize_customization():
- Branding toggles: ZEROOS_BRANDING and ZEROOS_REBRANDING (branding guard printed in logs).
- Branding also updates /etc/motd and /etc/issue to Zero-OS.
- Passwordless root enforced using passwd for shadow-aware deletion:
Console and getty
- Serial and console getty configs (zinit service YAML):
- Optional ash login loop (not enabled unless referenced):
Validation Diagnostics and Triage
- Common error previously observed:
- “Initramfs directory not found: initramfs (resolved: /workspace/kernel/current/initramfs)”
- Root cause:
- INSTALL_DIR re-sourced in a different CWD and interpreted as relative.
- Fix:
- Absolute path normalization of INSTALL_DIR/COMPONENTS_DIR/KERNEL_DIR/DIST_DIR after sourcing build.conf in bash.common.sh.
- Additional “Validation debug” prints added in bash.initramfs_validate().
- Expected logs now:
- “Validation debug: input='initramfs' PWD=/workspace PROJECT_ROOT=/workspace INSTALL_DIR=/workspace/initramfs”
- Resolves correctly even if called from a different stage CWD.
How to Verify Passwordless Root
- After build, check archive:
- mkdir -p dist/_inspect && cd dist/_inspect
- xz -dc ../initramfs.cpio.xz | cpio -idmv
- grep '^root:' ./etc/shadow
- Expect root:: (empty field) indicating passwordless root.
- At runtime on console:
- When prompted for root’s password, press Enter.
Stage System and Incremental Rebuilds
- Stage markers stored in .build-stages/ (one file per stage).
- To minimally rebuild:
- Remove relevant .done files, e.g.:
- initramfs_create.done initramfs_test.done validation.done
- Rerun: DEBUG=1 ./scripts/build.sh --skip-tests
- Remove relevant .done files, e.g.:
- Show status:
- ./scripts/build.sh --show-stages
Key Decisions (current)
- Branding enforces passwordless root via passwd -d -R inside initramfs finalization, avoiding direct edits of passwd/shadow files.
- Directory paths normalized to absolute after loading config to avoid CWD-sensitive behavior.
- Container image contains shadow suite to ensure passwd/chpasswd availability; perl removed.
File Pointers (quick jump)
- Orchestrator: scripts/build.sh
- Common and config loading: bash.common.sh
- Finalization hook: bash.initramfs_finalize_customization()
- Passwordless deletion: bash.initramfs_finalize_customization()
- Validation entry: bash.initramfs_validate()
- CPIO creation: bash.initramfs_create_cpio()
- Kernel embed config: bash.kernel_modify_config_for_initramfs()
- RFS packers: bash.pack-modules.sh, bash.pack-firmware.sh
Change Log
- 2025-09-09:
- Enforce passwordless root using passwd -d -R in finalization.
- Normalize INSTALL_DIR/COMPONENTS_DIR/KERNEL_DIR/DIST_DIR to absolute paths post-config load.
- Add validation diagnostics prints (input/PWD/PROJECT_ROOT/INSTALL_DIR/resolved).
- Ensure shadow package in container for passwd/chpasswd; keep openssl and openssl-dev; remove perl earlier.