No description
  • Python 71.4%
  • Shell 28.1%
  • Go Template 0.4%
  • Dockerfile 0.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Entrapta Jones 4467337e8a
All checks were successful
Hello World / hello (push) Successful in 4s
feat: Enable BinFMT-Misc extension
2026-09-17 20:30:10 +00:00
.forgejo fix: Ensure the extension builds to the correct tags 2026-09-16 02:57:35 +00:00
config feat: Enable BinFMT-Misc extension 2026-09-17 20:30:10 +00:00
docs feat: Enable BinFMT-Misc extension 2026-09-17 20:30:10 +00:00
extensions/apple-smc fix: Fix the ARM64 build issue for the installer image 2026-09-16 03:48:37 +00:00
Images feat: Attempt to ensure this publishes the image factory paths correctly and fix the build error 2026-09-11 11:16:50 +00:00
scripts feat: Enable BinFMT-Misc extension 2026-09-17 20:30:10 +00:00
tests feat: Enable BinFMT-Misc extension 2026-09-17 20:30:10 +00:00
.gitignore fix: Ensure we are tagging the releases properly 2026-09-12 13:56:39 +00:00
AGENTS.md feat: Attempt to fix caching, document some things and allow the agent to fetch and monitor the build logs 2026-09-11 13:47:49 +00:00
README.md fix: Fix the ARM64 build issue for the installer image 2026-09-16 03:48:37 +00:00

CoRE Talos Image Factory sources

The Forgejo workflows in .forgejo/workflows/ produce the versioned source artifacts consumed by a self-hosted Talos Image Factory. It does not compose machine images. Image Factory schematics select extensions, kernel arguments, ISO/installer output, and hardware-specific profiles.

The build retains the Talos GCC/GNU ld.bfd/no-LTO workaround and the configurable CONFIG_SENSORS_APPLESMC=m module. Kernel-coupled extensions are rebuilt against that exact kernel; non-kernel Sidero Labs extensions are mirrored by immutable digest. See the kernel-coupled inventory and the Image Factory source contract.

Kernel workaround provenance

The Mac EFI workaround follows mebezac's Talos Mac installer and the associated home-cluster pull request. The underlying Talos investigation is documented in Talos issue #13579, which records the earlier deleted issue #13231 and the LLD/ThinLTO EFI boot failure on Intel Macs. These references were lost when the original installer workflow was replaced by the Image Factory source build; they are restored here.

The implementation removes the upstream LLVM: 1 kernel package override and requires GCC, GNU ld.bfd, CONFIG_LTO_NONE=y, and both Clang LTO symbols to be disabled. Those toolchain/LTO changes apply to every build; only the Mac-specific Kconfig overrides are controlled by mac_kernel_fixes.

Configuration

config/talos-build.yaml describes the kernel and factory source set. The precedence is: non-empty workflow input, selected YAML value, repository default. The fully resolved, secret-free configuration is uploaded as _out/resolved-build-config.yaml.

The normal dispatch inputs are config_file, talos_version, factory_version, extra_factory_extensions, and publish. talos_version accepts any upstream semver-style release tag (for example v1.13.5 or v1.14.0); when factory_version is omitted, it follows the selected Talos version. The mac_kernel_fixes workflow checkbox controls the Mac/iMac-specific kernel overrides and the local apple-smc extension; leave it unchecked for a normal build. apple-smc publishes the signed module on amd64 and an intentionally empty compatibility image on arm64; the Apple-specific Kconfig symbols remain amd64-only while ARM64 receives the common kernel fixes. The original kernel fixes remain enabled for both modes: GCC, GNU ld.bfd, no LTO, and removal of the upstream LLVM override.

Workflow inputs

All inputs are available from the Forgejo Run workflow form. Empty string overrides fall back to the selected YAML configuration.

Input Workflows Default Purpose
config_file all Talos build workflows config/talos-build.yaml Repository-relative build configuration file.
talos_version all Talos build workflows configuration value Upstream Talos release tag to check out and build, such as v1.14.0.
factory_version all Talos build workflows selected Talos version Published source tag for the Image Factory component repositories. It must match talos_version.
mac_kernel_fixes all Talos build workflows true Enables the Mac/iMac Kconfig overrides and the local apple-smc extension. Set false for normal builds.
extra_factory_extensions extensions, core workflows empty Comma-separated additional extensions to expose in the generated catalog.
publish core workflow false Promotes the validated build-tagged manifests to the configured factory_version tag.
kernel_build_tag extensions, core workflows required Immutable kernel package tag from the matching kernel run. latest is rejected.
extensions_build_tag core workflow required Immutable extensions catalog tag from the matching extensions run. latest is rejected.
core_build_tag core workflow generated run tag Immutable tag assigned to the core artifacts produced by that run.

factory_version is a publication and discovery tag for the Talos source set: the validated imager, installer-base, installer, extensions, overlays, and talosctl-all manifests are promoted to that tag when publish is enabled. Image Factory discovers the release through the imager:<factory_version> tag and expects the companion repositories to use the same tag. It is not the deployed Image Factory application version (for example, Image Factory v1.4.0); it must be a Talos release tag compatible with the selected source build.

The talos.architectures and talos.platforms lists describe the source matrix (currently amd64, arm64, and metal). The legacy singular architecture and platform keys remain accepted. SBC targets can be declared under talos.sbc with a target name, architecture, and overlay image; they are normalized into the resolved configuration and must use arm64.

python3 scripts/build-config.py --config config/talos-build.yaml --validate

Published source set

For the Image Factory core namespace forge.core-dc1-talos-prod.dc1.yxl.writemy.codes/kjones/actions-lab/imager, a published factory version contains these upstream-shaped repositories:

siderolabs/imager:<FACTORY_VERSION>
siderolabs/installer-base:<FACTORY_VERSION>
siderolabs/installer:<FACTORY_VERSION>
siderolabs/extensions:<FACTORY_VERSION>
siderolabs/overlays:<FACTORY_VERSION>
siderolabs/talosctl-all:<FACTORY_VERSION>

The kernel package is an internal .../imager/pkgs/kernel dependency. Selected extensions are siblings of the catalog, such as siderolabs/i915:<BUILD_TAG>. The workflow mirrors overlays and talosctl-all, builds all six Image Factory core components, validates the complete build-tagged set and catalog, then adds matching FACTORY_VERSION tags by manifest retagging. Imager is promoted last so Image Factory cannot discover an incomplete version.

Configure Image Factory v1.4 with artifacts.core.registry set to the Forgejo host, namespace set to kjones/actions-lab/imager, and component names set to siderolabs/imager, siderolabs/installer-base, siderolabs/installer, siderolabs/extensions, siderolabs/overlays, and siderolabs/talosctl-all. Image Factory prepends the namespace to pull paths, but extension identities in the catalog remain ghcr.io/siderolabs/<name>; putting the private prefix in image-digests would double-prefix it. Secrets are never written to resolved configuration.

The build exports _out/extensions-image-digests and _out/extensions-descriptions.yaml. scripts/verify-oci.py checks every core artifact and selected extension with crane, including logical-to-physical digest equality.

Every source build also runs scripts/verify-talos-artifacts.py. It checks the alpha.talos.dev/version label and executes /usr/bin/installer from installer-base, installer, and imager; all must report the configured release selected by talos_version. If METAL_INSTALLER_REFERENCE is configured as a Forgejo Action variable, the same checks are applied to that generated Image Factory installer and its embedded UKI .osrel must contain the selected VERSION_ID.

Independent build stages

The pipeline is split into three independently dispatchable workflows:

  • talos-kernel.yml publishes the custom kernel.
  • talos-extensions.yml consumes the required immutable kernel_build_tag and publishes kernel-coupled extensions plus the catalog.
  • talos-core.yml consumes required immutable kernel_build_tag and extensions_build_tag values and publishes the Image Factory core artifacts.

The required build sequence is:

kernel workflow
    ↓ immutable kernel build tag
extensions workflow
    ↓ immutable extensions build tag + recorded kernel digest
core workflow

For example, a historical build can use Talos: v1.13.10, kernel_build_tag: forgejo-131-1, and extensions_build_tag: forgejo-145-1. The extensions stage stores machine-readable provenance in the sibling OCI image siderolabs/extensions-provenance:<extensions-build-tag>. The core stage reads that artifact and requires matching Talos versions, immutable kernel/extension tags, and kernel digests before composing anything. latest must not couple kernel-backed extensions to custom kernels: two builds can have the same uname -r while carrying different module-signing identities.

Every stage uses an immutable Forgejo run tag and can optionally promote its validated result to latest. Promotion is allowed only when the resolved Talos version matches the version in the repository's canonical config/talos-build.yaml; historical release overrides can build and publish immutable tags but cannot move the public latest tag. For reproducible independent runs, pass the run tag explicitly instead of relying on latest.

The standalone kernel workflow uses the talos-kernel-build concurrency group. Forgejo queues a second kernel run instead of running two resource-intensive kernel builds concurrently; queued runs are not canceled.

The Talos workflows register Docker binfmt/QEMU support for arm64 before starting Buildx. This is required because the runners are AMD64; without it, the configuration can request ARM64 while the BuildKit builder advertises only AMD64 platforms.

The stage implementations are scripts/build-kernel.sh, scripts/build-extensions.sh, and scripts/build-core.sh; shared registry, BuildKit, authentication, and manifest setup lives in scripts/lib/build-common.sh.

The staged workflows cache the upstream repositories they need under .cache/upstream, keyed by workflow and Talos version/configuration. Kernel builds cache talos and pkgs; extensions cache talos and extensions; the The helper updates those checkouts when possible and creates each stage's working clone locally from the cache. BuildKit core targets share the stable cache/talos-core registry cache, while retaining the previous per-target caches as import fallbacks.

Invalidating a contaminated generated installer

The affected model is keyed by both schematic and Talos version. For the reported schematic, the generated OCI tag is:

forge.core-dc1-talos-prod.dc1.yxl.writemy.codes/kjones/actions-lab/talos/metal-installer/21cbef3780f9667bbd06c4e7f50584565bdabdeb87c5dff725dac1b92ac15d15:v1.14.0

After publishing corrected source manifests, invalidate or rebuild this exact model in Image Factory: the OCI tag above and the corresponding generated artifact cache entries under /image/21cbef3780f9667bbd06c4e7f50584565bdabdeb87c5dff725dac1b92ac15d15/v1.14.0/, including installer-amd64.tar, installer-arm64.tar, metal ISO, and UKI artifacts. Also invalidate any CDN/S3 objects using those model/path keys. Do not delete registry data from this repository. If the deployment keeps a process-local model cache, restart the Image Factory pod after the corrected v1.14.0 source tags are visible; otherwise use its configured cache purge mechanism. The safe operational sequence is source republish → cache purge or factory restart → pull by the same schematic/version tag → run the artifact validator. A new schematic ID is an alternative cache key only when its canonical schematic intentionally changes; it is not a substitute for fixing the source metadata.

Runner

The job uses the existing Docker/TLS runner setup and requires a Linux AMD64 Docker daemon, privileged BuildKit, GitHub/GHCR access, Image Factory catalog access, and Forgejo package write credentials:

Type Name Value
Secret TALOS_REGISTRY_PASSWORD Forgejo token with package write access
Optional secret TALOS_REGISTRY_USERNAME Token owner's username

For local builds provide Docker buildx, kmod, crane, Python 3 with PyYAML, Git, Make, and curl, then set OCI_REGISTRY, OCI_NAMESPACE, REGISTRY_USERNAME, and REGISTRY_PASSWORD before running the independent stage scripts under scripts/. For this deployment those values are the Forgejo host and kjones/actions-lab/imager.

To stage the Talos package dependencies in the private registry, authenticate Crane to the destination registry and run:

python3 scripts/mirror-talos-packages.py \
  --talos-version v1.14.0 \
  --manifest _out/talos-packages-v1.14.0.json

When OCI_REGISTRY and OCI_NAMESPACE are set by the existing Forgejo build setup, the destination defaults to the same registry namespace used by the build: $OCI_REGISTRY/$OCI_NAMESPACE/pkgs. Use --destination-prefix only when intentionally mirroring elsewhere.

The script reads the package names and default PKGS tag from the selected Talos release Makefile, mirrors the complete OCI indexes for all supported architectures, and verifies every destination digest. Use --dry-run to inspect the 58 references first, --jobs to adjust concurrency, or --pkgs-tag when mirroring a separately pinned package build. It mirrors the stock kernel package too; the custom kernel remains a separate build output and can replace that tag for the source build. The JSON manifest is safe to retain as it contains references and digests, not credentials. Existing tags with the same digest are skipped; existing tags with a different digest cause the mirror to fail rather than be overwritten.

The manual Forgejo workflow Mirror Talos packages performs the same operation using the existing Forgejo registry credentials and uploads the digest manifest as a workflow artifact. The Talos kernel, extensions, and core workflows now consume these mirrored packages from $OCI_REGISTRY/$OCI_NAMESPACE/pkgs; the custom kernel is still passed separately through PKG_KERNEL.

BuildKit imports and exports registry-backed caches. They use stable sibling repositories below forge.../kjones/actions-lab/cache by default: kernel-build, kernel-image, talos-kernel, talos-initramfs, talos-imager, talos-installer-base, talos-installer, ext-<name>, and extensions-catalog. Each build phase owns its cache reference, so later phases do not replace earlier phases cache manifests. A missing cache manifest is non-fatal on the first build; cache export errors do not turn a failed image push into a successful build. Set BUILDKIT_CACHE_PREFIX to use a separate cache namespace.

Image Factory v1.4.0 namespace behavior was introduced by upstream commit beff6e2 and applies to core components plus extension and overlay images discovered through their manifests.