- Python 71.4%
- Shell 28.1%
- Go Template 0.4%
- Dockerfile 0.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| .forgejo | ||
| config | ||
| docs | ||
| extensions/apple-smc | ||
| Images | ||
| scripts | ||
| tests | ||
| .gitignore | ||
| AGENTS.md | ||
| README.md | ||
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.ymlpublishes the custom kernel.talos-extensions.ymlconsumes the required immutablekernel_build_tagand publishes kernel-coupled extensions plus the catalog.talos-core.ymlconsumes required immutablekernel_build_tagandextensions_build_tagvalues 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.