Skip to content

docker_*.sh: add kvm support, X11 authentication, update README.md instructions. Bump docker image to v.0.2.7 with pinned hash under CircleCI#2036

Merged
tlaurion merged 4 commits into
linuxboot:masterfrom
tlaurion:bugfix-qemu_kvm
Feb 8, 2026

Conversation

@tlaurion

@tlaurion tlaurion commented Dec 15, 2025

Copy link
Copy Markdown
Collaborator

TODO after merge:

  • push v0.2.7 docker image as latest

Docker Workflows and Reproducibility Tooling Refactor

Overview

This changeset introduces comprehensive improvements to Heads' Docker-based build system, focusing on reproducibility, maintainability, and user experience.


Files Changed

Modified Files

.circleci/config.yml

  • Updated all 4 Docker image references from v0.2.5 to digest-pinned v0.2.7
  • Changed from mutable tag format: tlaurion/heads-dev-env:v0.2.5
  • To immutable digest format: tlaurion/heads-dev-env@sha256:5f890f3d1b6b57f9e567191695df003a2ee880f084f5dfe7a5633e3e8f937479
  • Added version comments above each image reference

README.md

Major documentation expansion including:

  • Docker installation and setup guide
  • Comprehensive wrapper scripts reference (docker_repro.sh, docker_local_dev.sh, docker_latest.sh)
  • Environment variables documentation (all HEADS_* variables)
  • QEMU/Docker integration notes (no host-side QEMU install needed)
  • Docker image management commands (inspect, clean, prune)
  • qemu-img snapshot workflow
  • Reproducibility verification guide with examples
  • Maintainer workflow for updating Docker images
  • Digest pinning and supply-chain security guidance
  • Helper script reference (get_digest.sh, pin-and-run.sh, check_reproducibility.sh)

docker_latest.sh

  • Refactored to source docker/common.sh for shared logic
  • Added wrapper-specific usage() function
  • Integrated resolve_docker_image for digest resolution
  • Added SIGINT trap for cleanup
  • Uses require_docker check
  • Supports DOCKER_LATEST_DIGEST override

docker_local_dev.sh

  • Refactored to source docker/common.sh
  • Added wrapper-specific usage() function
  • Integrated maybe_rebuild_local_image for conditional rebuilds
  • Added reproducibility check support (HEADS_CHECK_REPRODUCIBILITY=1)
  • Uses shared ensure_nix_and_flakes infrastructure
  • Added SIGINT trap
  • Supports HEADS_SKIP_DOCKER_REBUILD=1

docker_repro.sh

  • Refactored to source docker/common.sh
  • Added wrapper-specific usage() function
  • Integrated digest pinning via DOCKER_REPRO_DIGEST file/env var
  • Uses resolve_docker_image with digest support
  • Added SIGINT trap
  • Cleaner help output

flake.nix

  • Minor addition (exact change not visible in summary)

initrd/bin/kexec-seal-key

  • Updated LUKS device regex to use POSIX character classes
  • Changed from [ \t] to [[:space:]] for better portability

targets/qemu.md

  • Expanded wrapper scripts documentation
  • Updated help text guidance (wrappers show focused help, common.sh shows full reference)
  • Added environment variable reference
  • Docker/QEMU integration notes
  • USB token passthrough details

New Files

docker/DOCKER_REPRO_DIGEST

  • Pinned digest file for ./docker_repro.sh
  • Contains canonical image digest: sha256:5f890f3d1b6b57f9e567191695df003a2ee880f084f5dfe7a5633e3e8f937479
  • Version comment: v0.2.7
  • Supports multiple digest formats (normalized internally)

docker/check_reproducibility.sh

  • Standalone reproducibility checker
  • Compares local Docker image digest vs remote registry
  • Usage: ./docker/check_reproducibility.sh [local_image] [remote_image]
  • Delegates to compare_image_reproducibility in common.sh
  • Supports HEADS_MAINTAINER_DOCKER_IMAGE override

docker/common.sh

Shared helper library providing:

  • ensure_nix_and_flakes() — Nix installation and flakes setup with interactive prompts
  • resolve_docker_image() — Image reference resolution with digest pinning support
  • maybe_rebuild_local_image() — Conditional Docker image rebuild when flake files are dirty
  • kill_usb_processes() — Automatic USB device cleanup (scdaemon/pcscd)
  • build_docker_opts() — Docker runtime options construction (volumes, X11, USB, etc.)
  • run_docker() — Container execution wrapper with cleanup
  • get_remote_config_digest() — Fetch remote image config digest via skopeo/API
  • get_local_image_id() — Extract local image ID (config digest)
  • compare_image_reproducibility() — Compare local vs remote image digests
  • resolve_repro_remote_image() — Default reproducibility remote image resolution
  • require_docker() — Docker availability check
  • Xauthority temp file handling with cleanup
  • Color support for TTY output
  • Comprehensive usage documentation

docker/fetch_nix_installer.sh

  • Downloads Nix single-user installer with checksum verification
  • Supports --version nix-X.Y.Z or --url <custom-url>
  • Fetches published .sha256 from releases.nixos.org when available
  • Prints sha256 for manual verification
  • Never auto-executes installer (supply-chain safety)
  • Usage: ./docker/fetch_nix_installer.sh --version nix-2.33.2

docker/get_digest.sh

  • Fetches Docker image digests from registry or local Docker
  • Methods: local inspect → skopeo → Docker Hub API → docker pull
  • Supports -y/--yes for auto-pull
  • Interactive prompt when image not local
  • Outputs both repo@digest and raw sha256:... for easy scripting
  • Usage: ./docker/get_digest.sh [-y] <image:tag>
  • Example: ./docker/get_digest.sh tlaurion/heads-dev-env:v0.2.7

docker/pin-and-run.sh

  • Convenience wrapper to pin digest and run command in one step
  • Obtains digest via get_digest.sh and exports DOCKER_LATEST_DIGEST
  • Usage: ./docker/pin-and-run.sh [-y] [-w wrapper] <image:tag> -- <command>
  • Example: ./docker/pin-and-run.sh tlaurion/heads-dev-env:v0.2.7 -- make BOARD=x230
  • Defaults to ./docker_latest.sh if no wrapper specified
  • Supports -y for non-interactive auto-pull

Key Features

1. Reproducibility Infrastructure

  • Digest Pinning: CircleCI and docker_repro.sh now use immutable @sha256:... references
  • Verification Workflow: HEADS_CHECK_REPRODUCIBILITY=1 compares local builds vs published images
  • Supply-Chain Safety: Documented workflows for verifying Docker image integrity

2. Code Consolidation

  • Shared Logic: 1,238 lines of common code extracted from wrapper scripts
  • DRY Principle: USB handling, X11 setup, Nix infrastructure now centralized
  • Maintainable: Single source of truth for Docker runtime configuration

3. Enhanced Documentation

  • Comprehensive Guide: README expanded from basic instructions to full reference
  • All Environment Variables: Complete documentation of HEADS_* and DOCKER_* variables
  • Maintainer Workflows: Step-by-step procedures for updating Docker images
  • Examples: Real commands with expected output for common tasks

4. Developer Tools

  • 4 New Helper Scripts: Digest management, reproducibility checks, Nix installer handling
  • Interactive Prompts: Nix/flakes setup with supply-chain safety guardrails
  • Flexible Overrides: Fork maintainers can override HEADS_MAINTAINER_DOCKER_IMAGE

5. Improved Help System

  • Wrapper-Specific Help: Each script shows only relevant variables (--help)
  • Full Reference: Run docker/common.sh directly for complete environment documentation
  • Contextual Guidance: TTY-aware diagnostics and user-friendly error messages

Older notes
My bad: I always only tested qemu boards under QubesOS (which as of now still doesn't permit nested xen->kvm virtualization)

This change permits to run things under qemu+kvm

Tested

  • installation with media and default partition schemes
  • sealing firmware measurements + setting default boot option + TPM Disk Unlock Key when requested (to add additional LUKS key that is unsealed from TPM when coreboot+heads measurements valid + TPM DUK passphrase)

Note: TPM DUK is mitigation for any OSes not providing efifb in their initramfs, prior of specialized drm+gpu drivers being loaded (at LUKS passphrase prompt early in init/systemd).

ISO tested:

  • ubuntu-25.10-desktop-amd64.iso:
./docker_repro.sh make BOARD=qemu-coreboot-fbwhiptail-tpm2 QEMU_MEMORY_SIZE=16G QEMU_DISK_SIZE=30G INSTALL_IMG=ubuntu-25.10-desktop-amd64.iso
./docker_repro.sh make BOARD=qemu-coreboot-fbwhiptail-tpm2 PUBKEY_ASC=pubkey.asc USB_TOKEN=Nitrokey3NFC inject_gpg
./docker_repro.sh make BOARD=qemu-coreboot-fbwhiptail-tpm2 PUBKEY_ASC=pubkey.asc USB_TOKEN=Nitrokey3NFC run
  • debian-13.2.0-amd64-DVD-1.iso
./docker_repro.sh make BOARD=qemu-coreboot-fbwhiptail-tpm2 QEMU_MEMORY_SIZE=16G QEMU_DISK_SIZE=30G INSTALL_IMG=debian-13.2.0-amd64-DVD-1.iso run
./docker_repro.sh make BOARD=qemu-coreboot-fbwhiptail-tpm2 PUBKEY_ASC=pubkey.asc USB_TOKEN=Nitrokey3NFC inject_gpg
./docker_repro.sh make BOARD=qemu-coreboot-fbwhiptail-tpm2 PUBKEY_ASC=pubkey.asc USB_TOKEN=Nitrokey3NFC run
  • Fedora-Workstation-Live-43-1.6.x86_64.iso
./docker_repro.sh make BOARD=qemu-coreboot-fbwhiptail-tpm2 QEMU_MEMORY_SIZE=16G QEMU_DISK_SIZE=30G INSTALL_IMG=Fedora-Workstation-Live-43-1.6.x86_64.iso run
./docker_repro.sh make BOARD=qemu-coreboot-fbwhiptail-tpm2 PUBKEY_ASC=pubkey.asc USB_TOKEN=Nitrokey3NFC inject_gpg
./docker_repro.sh make BOARD=qemu-coreboot-fbwhiptail-tpm2 PUBKEY_ASC=pubkey.asc USB_TOKEN=Nitrokey3NFC run

Also:

  • Docker image bumped to v0.2.7 to test docker_local_dev.sh and add needed coreboot-utils to use diffoscope on roms from within docker image to test reproducibility issues (none discovered).
  • CircleCI now uses pinned commit, superseeding Use docker "immutable identifier" instead of tag #2013
  • docker_local_dev.sh will help with deploying nix if not present on system, probing user to validate hash and guiding user from where (heuristics). This is useful to maintain docker images.

TODO:

  • make sure builds are reproducible: 404f56fdf6a63226fddc97e0059703f696ad47bfad2881838845647e8b04799a /root/heads/build/x86/EOL_t480-hotp-maximized/heads-EOL_t480-hotp-maximized-v0.2.1-2921-ge931ff1.rom

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants