From cdb59659f5bb993aa1c8ccf946bd92a1a6d800e0 Mon Sep 17 00:00:00 2001 From: kpiyush17 Date: Mon, 30 Jun 2025 17:30:26 +0530 Subject: [PATCH 01/40] inital commit --- .github/workflows/base-images.yaml | 181 +++++- .github/workflows/pr.yaml | 15 - .github/workflows/release.yaml | 48 -- .github/workflows/test-workflow.yml | 14 + Makefile | 50 ++ docker-bake-kairosify.hcl | 41 ++ docker-bake.hcl | 579 +++++++++++++++++++ dockerfiles/Dockerfile.base-image | 135 +++++ dockerfiles/Dockerfile.build-iso | 65 +++ dockerfiles/Dockerfile.build-uki-iso | 73 +++ dockerfiles/Dockerfile.download-sbctl | 7 + dockerfiles/Dockerfile.install-k8s | 55 ++ dockerfiles/Dockerfile.iso-image | 21 + dockerfiles/Dockerfile.kairos-provider-image | 3 + dockerfiles/Dockerfile.provider-image | 99 ++++ dockerfiles/Dockerfile.slink | 33 ++ dockerfiles/Dockerfile.stylus-image | 3 + dockerfiles/Dockerfile.stylus-image-pack | 18 + dockerfiles/Dockerfile.third-party | 23 + dockerfiles/Dockerfile.trustedboot-image | 23 + dockerfiles/Dockerfile.uki-byok | 71 +++ dockerfiles/Dockerfile.uki-genkey | 65 +++ dockerfiles/Dockerfile.uki-provider-image | 34 ++ dockerfiles/Dockerfile.validate-ud | 16 + dockerfiles/kairosify/Dockerfile.kairosify | 24 + 25 files changed, 1630 insertions(+), 66 deletions(-) delete mode 100644 .github/workflows/pr.yaml delete mode 100644 .github/workflows/release.yaml create mode 100644 .github/workflows/test-workflow.yml create mode 100644 Makefile create mode 100644 docker-bake-kairosify.hcl create mode 100644 docker-bake.hcl create mode 100644 dockerfiles/Dockerfile.base-image create mode 100644 dockerfiles/Dockerfile.build-iso create mode 100644 dockerfiles/Dockerfile.build-uki-iso create mode 100644 dockerfiles/Dockerfile.download-sbctl create mode 100644 dockerfiles/Dockerfile.install-k8s create mode 100644 dockerfiles/Dockerfile.iso-image create mode 100644 dockerfiles/Dockerfile.kairos-provider-image create mode 100644 dockerfiles/Dockerfile.provider-image create mode 100644 dockerfiles/Dockerfile.slink create mode 100644 dockerfiles/Dockerfile.stylus-image create mode 100644 dockerfiles/Dockerfile.stylus-image-pack create mode 100644 dockerfiles/Dockerfile.third-party create mode 100644 dockerfiles/Dockerfile.trustedboot-image create mode 100644 dockerfiles/Dockerfile.uki-byok create mode 100644 dockerfiles/Dockerfile.uki-genkey create mode 100644 dockerfiles/Dockerfile.uki-provider-image create mode 100644 dockerfiles/Dockerfile.validate-ud create mode 100644 dockerfiles/kairosify/Dockerfile.kairosify diff --git a/.github/workflows/base-images.yaml b/.github/workflows/base-images.yaml index 2af0979d..5427caf4 100644 --- a/.github/workflows/base-images.yaml +++ b/.github/workflows/base-images.yaml @@ -2,11 +2,186 @@ name: Build Kairos Init Base Images on: workflow_dispatch: + inputs: + base_os_image: + description: "Base OS Image" + required: false + type: string + default: "" + kairos_init_image: + description: "Kairos Init Image" + required: false + type: string + default: "quay.io/kairos/kairos-init:v0.5.1" + arch: + description: "Architecture" + required: false + type: choice + options: + - amd64 + - arm64 + default: "amd64" + model: + description: "Model" + required: false + type: string + default: "generic" + kairos_version: + description: "Kairos Version" + required: false + type: string + default: "v3.4.2" + trusted_boot: + description: "Trusted Boot" + required: false + type: boolean + default: false + registry_prefix: + description: "Registry prefix for output images" + required: false + type: string + default: "us-east1-docker.pkg.dev/spectro-images/dev/piyush-1/edge" jobs: generate-matrix: - runs-on: ubuntu-latest + runs-on: Luet-BigRunner + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - - name: Generate Matrix + - name: Generate build matrix + id: set-matrix run: | - echo "Hello" + python3 << 'EOF' + import json + import os + + base_os_image = "${{ github.event.inputs.base_os_image }}" + registry_prefix = "${{ github.event.inputs.registry_prefix }}" + arch = "${{ github.event.inputs.arch }}" + model = "${{ github.event.inputs.model }}" + kairos_version = "${{ github.event.inputs.kairos_version }}" + trusted_boot = "${{ github.event.inputs.trusted_boot }}" == "true" + + matrix = [] + + if base_os_image: + # Custom base OS image + simple_name = base_os_image.split('/')[-1].replace(':', '-') + tag = f"{registry_prefix}/kairos-custom:{simple_name}-core-{arch}-{model}-{kairos_version}" + if trusted_boot: + tag += "-uki" + + matrix.append({ + "base_os": base_os_image, + "tag": tag + }) + + elif trusted_boot: + # UKI builds - only Ubuntu 24.04 + tag = f"{registry_prefix}/kairos-ubuntu:24.04-core-{arch}-{model}-{kairos_version}-uki" + matrix.append({ + "base_os": "ubuntu:24.04", + "tag": tag + }) + + else: + # Standard builds - all combinations + combinations = [ + ("ubuntu:20.04", "kairos-ubuntu:20.04-core"), + ("ubuntu:22.04", "kairos-ubuntu:22.04-core"), + ("ubuntu:24.04", "kairos-ubuntu:24.04-core"), + ("opensuse/leap:15.6", "kairos-opensuse:leap-15.6-core") + ] + + for base_os, tag_prefix in combinations: + tag = f"{registry_prefix}/{tag_prefix}-{arch}-{model}-{kairos_version}" + matrix.append({ + "base_os": base_os, + "tag": tag + }) + + matrix_json = json.dumps(matrix) + print(f"Generated matrix: {matrix_json}") + + with open(os.environ['GITHUB_OUTPUT'], 'a') as f: + f.write(f"matrix={matrix_json}\n") + EOF + + kairosify: + needs: generate-matrix + runs-on: Luet-BigRunner + strategy: + matrix: + include: ${{ fromJson(needs.generate-matrix.outputs.matrix) }} + fail-fast: false + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to registry + run: echo "${{ secrets.US_EAST_JSON_KEY_B64 }}" | base64 -d | docker login -u _json_key --password-stdin us-east1-docker.pkg.dev + + - name: Build and push kairosify image + uses: docker/bake-action@v6 + with: + files: docker-bake-kairosify.hcl + targets: kairosify + push: true + set: | + kairosify.platform=linux/${{ github.event.inputs.arch }} + kairosify.args.BASE_OS_IMAGE=${{ matrix.base_os }} + kairosify.args.KAIROS_INIT_IMAGE=${{ github.event.inputs.kairos_init_image }} + kairosify.args.KAIROS_VERSION=${{ github.event.inputs.kairos_version }} + kairosify.args.TRUSTED_BOOT=${{ github.event.inputs.trusted_boot }} + kairosify.args.MODEL=${{ github.event.inputs.model }} + kairosify.tags=${{ matrix.tag }} + env: + DOCKER_BUILD_SUMMARY: false + + - name: Save build result + run: | + mkdir -p /tmp/results + echo "${{ matrix.tag }}" >> /tmp/results/built_tags.txt + + - name: Upload build results + uses: actions/upload-artifact@v4 + with: + name: build-result-${{ strategy.job-index }}-${{ hashFiles('**/matrix.*') }} + path: /tmp/results/built_tags.txt + + collect-outputs: + needs: kairosify + runs-on: Luet-BigRunner + outputs: + built_tags: ${{ steps.combine-tags.outputs.tags }} + steps: + - name: Download all build results + uses: actions/download-artifact@v4 + with: + pattern: build-result-* + path: /tmp/results + + - name: Combine all tags + id: combine-tags + run: | + ALL_TAGS=$(find /tmp/results -name "*.txt" -type f -exec cat {} \; | grep -v '^$' | jq -R -s -c 'split("\n") | map(select(length > 0))') + echo "tags=$ALL_TAGS" >> $GITHUB_OUTPUT + echo "All built tags: $ALL_TAGS" + + - name: Summary + run: | + echo "## Kairosify Build Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Input Parameters:**" >> $GITHUB_STEP_SUMMARY + echo "- Base OS Image: ${{ github.event.inputs.base_os_image || 'Default combinations' }}" >> $GITHUB_STEP_SUMMARY + echo "- Kairos Init Image: ${{ github.event.inputs.kairos_init_image }}" >> $GITHUB_STEP_SUMMARY + echo "- Architecture: ${{ github.event.inputs.arch }}" >> $GITHUB_STEP_SUMMARY + echo "- Model: ${{ github.event.inputs.model }}" >> $GITHUB_STEP_SUMMARY + echo "- Kairos Version: ${{ github.event.inputs.kairos_version }}" >> $GITHUB_STEP_SUMMARY + echo "- Trusted Boot: ${{ github.event.inputs.trusted_boot }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Built Images:**" >> $GITHUB_STEP_SUMMARY + echo '${{ steps.combine-tags.outputs.tags }}' | jq -r '.[] | "- " + .' >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml deleted file mode 100644 index 72877e90..00000000 --- a/.github/workflows/pr.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# name: Pr - -# on: [pull_request] - -# concurrency: -# group: ${{ github.pr_workflow }}-${{ github.ref }} -# cancel-in-progress: true - -# permissions: -# contents: read - -# jobs: -# build: -# uses: ./.github/workflows/release.yaml -# secrets: inherit \ No newline at end of file diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml deleted file mode 100644 index c50d3d68..00000000 --- a/.github/workflows/release.yaml +++ /dev/null @@ -1,48 +0,0 @@ -# name: Release - -# on: -# push: -# tags: -# - v* - -# permissions: -# contents: write - -# concurrency: -# group: ${{ github.workflow }}-${{ github.ref }} -# cancel-in-progress: true - - -# jobs: -# release-iso-image: -# runs-on: ubuntu-latest -# steps: -# - name: Login to Docker Hub -# uses: docker/login-action@v2 -# with: -# username: ${{ secrets.DOCKERHUB_USERNAME }} -# password: ${{ secrets.DOCKERHUB_TOKEN }} -# - uses: actions/checkout@v3 -# - name: create .netrc file -# env: -# REPO_USER: ${{ secrets.REPO_USER }} -# REPO_TOKEN: ${{ secrets.REPO_TOKEN }} -# shell: bash -# run: | -# echo "machine github.com" > .netrc -# echo " login $REPO_USER" >> .netrc -# echo " password $REPO_TOKEN" >> .netrc -# echo "machine api.github.com" >> .netrc -# echo " login $REPO_USER" >> .netrc -# echo " password $REPO_TOKEN" >> .netrc -# - uses: earthly/actions-setup@v1 -# - run: ./earthly --ci --push -P --output +build-all-images --PE_VERSION=${{ github.ref_name }} -# - run: | -# if [[ "${{ github.ref }}" =~ .*-.*$ ]]; then -# echo "IS_PRERELEASE=true" > $GITHUB_ENV -# fi -# - uses: softprops/action-gh-release@v1 -# with: -# files: build/* -# prerelease: ${{ env.IS_PRERELEASE }} -# generate_release_notes: true \ No newline at end of file diff --git a/.github/workflows/test-workflow.yml b/.github/workflows/test-workflow.yml new file mode 100644 index 00000000..f68679c0 --- /dev/null +++ b/.github/workflows/test-workflow.yml @@ -0,0 +1,14 @@ +name: Test Dispatch +on: + workflow_dispatch: + inputs: + test_input: + description: 'Test input' + required: false + type: string + default: 'hello' +jobs: + test: + runs-on: ubuntu-latest + steps: + - run: echo "Input was ${{ github.event.inputs.test_input }}" \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..be43990d --- /dev/null +++ b/Makefile @@ -0,0 +1,50 @@ +-include .arg +export + +.PHONY: base-image build-iso build-provider-images + +PUSH ?= true +IS_UKI ?= false + +build-all-images: + $(MAKE) build-provider-images + @if [ "$(ARCH)" = "arm64" ]; then \ + docker buildx bake iso-image --set iso-image.platforms=linux/arm64; \ + elif [ "$(ARCH)" = "amd64" ]; then \ + docker buildx bake iso-image --set iso-image.platforms=linux/amd64; \ + fi + $(MAKE) build-iso + +base-image: + docker buildx bake base-image + +iso: + @if [ "$(IS_UKI)" = "true" ]; then \ + docker buildx bake build-uki-iso; \ + else \ + docker buildx bake build-iso; \ + fi + +build-provider-images: + @if [ -z "$(K8S_DISTRIBUTION)" ]; then \ + echo "K8S_DISTRIBUTION is not set. Please set K8S_DISTRIBUTION to kubeadm, kubeadm-fips, k3s, nodeadm, rke2 or canonical." && exit 1; \ + fi + @if [ "$(IS_UKI)" = "true" ]; then \ + TARGET=uki-provider-image; \ + else \ + TARGET=provider-image; \ + fi; \ + if [ -z "$(K8S_VERSION)" ]; then \ + VERSIONS=$$(jq -r --arg key "$(K8S_DISTRIBUTION)" 'if .[$key] then .[$key][] else empty end' k8s_version.json); \ + if [ -z "$$VERSIONS" ]; then \ + echo "No versions found for K8S_DISTRIBUTION=$(K8S_DISTRIBUTION) in k8s_version.json"; \ + exit 1; \ + fi; \ + for version in $$VERSIONS; do \ + docker buildx bake $$TARGET \ + --set *.args.K8S_VERSION=$$version; \ + done; \ + else \ + docker buildx bake $$TARGET \ + --set *.args.K8S_VERSION=$(K8S_VERSION); \ + fi \ No newline at end of file diff --git a/docker-bake-kairosify.hcl b/docker-bake-kairosify.hcl new file mode 100644 index 00000000..c591c763 --- /dev/null +++ b/docker-bake-kairosify.hcl @@ -0,0 +1,41 @@ +variable "KAIROS_INIT_IMAGE" { + default = "quay.io/kairos/kairos-init:v0.5.1" +} + +variable "ARCH" { + default = "amd64" +} + +variable "BASE_OS_IMAGE" { + default = "ubuntu:20.04" +} + +variable "MODEL" { + default = "generic" +} + +variable "KAIROS_VERSION" { + default = "v3.4.2" +} + +variable "TRUSTED_BOOT" { + type = bool + default = false +} + +variable "TAG" { + default = "kairosify:latest" +} + +target "kairosify" { + dockerfile = "dockerfiles/kairosify/Dockerfile.kairosify" + platforms = ["linux/${ARCH}"] + args = { + BASE_OS_IMAGE = BASE_OS_IMAGE + KAIROS_INIT_IMAGE = KAIROS_INIT_IMAGE + KAIROS_VERSION = KAIROS_VERSION + TRUSTED_BOOT = TRUSTED_BOOT + MODEL = MODEL + } + tags = [TAG] +} \ No newline at end of file diff --git a/docker-bake.hcl b/docker-bake.hcl new file mode 100644 index 00000000..ac331ec4 --- /dev/null +++ b/docker-bake.hcl @@ -0,0 +1,579 @@ +variable "FIPS_ENABLED" { + type = bool + default = false +} + +variable "ARCH" { + default = "amd64" +} + +variable "SPECTRO_PUB_REPO" { + default = FIPS_ENABLED ? "us-east1-docker.pkg.dev/spectro-images-fips/dev/piyush" : "us-east1-docker.pkg.dev/spectro-images/dev/piyush" +} + +variable "SPECTRO_THIRD_PARTY_IMAGE" { + default = "us-east1-docker.pkg.dev/spectro-images/third-party/spectro-third-party:4.6" +} + +variable "ALPINE_TAG" { + default = "3.20" +} + +variable "ALPINE_IMG" { + default = "${SPECTRO_PUB_REPO}/edge/canvos/alpine:${ALPINE_TAG}" +} + +variable "SPECTRO_LUET_REPO" { + default = "us-docker.pkg.dev/palette-images/edge" +} + +variable "LUET_PROJECT" { + default = "luet-repo" +} + +variable "PE_VERSION" { + default = "v4.6.21" +} + +variable "SPECTRO_LUET_VERSION" { + default = "v4.7.0-rc.1" +} + +variable "KAIROS_VERSION" { + default = "v3.4.2" +} + +variable AURORABOOT_IMAGE { + default = "quay.io/kairos/auroraboot:v0.8.7" +} + +variable "K3S_PROVIDER_VERSION" { + default = "v4.6.0" +} + +variable "KUBEADM_PROVIDER_VERSION" { + default = "v4.6.3" +} + +variable "RKE2_PROVIDER_VERSION" { + default = "v4.6.0" +} + +variable "NODEADM_PROVIDER_VERSION" { + default = "v4.6.0" +} + +variable "CANONICAL_PROVIDER_VERSION" { + default = "v1.1.0-rc.1" +} + +variable "K3S_FLAVOR_TAG" { + default = "k3s1" +} + +variable "RKE2_FLAVOR_TAG" { + default = "rke2r1" +} + +variable OS_DISTRIBUTION {} +variable OS_VERSION {} + +variable K8S_DISTRIBUTION {} +variable K8S_VERSION {} + +variable IMAGE_REGISTRY {} +variable IMAGE_REPO { + default = OS_DISTRIBUTION +} + +variable "ISO_NAME" { + default = "installer" +} + +variable "CLUSTERCONFIG" {} + +variable EDGE_CUSTOM_CONFIG { + default = ".edge-custom-config.yaml" +} + +variable "CUSTOM_TAG" {} + +variable "DISABLE_SELINUX" { + type = bool + default = true +} + +variable "CIS_HARDENING" { + type = bool + default = false +} + +variable UBUNTU_PRO_KEY {} + +variable HTTP_PROXY {} +variable HTTPS_PROXY {} +variable NO_PROXY {} +variable PROXY_CERT_PATH {} + +variable http_proxy { + default = HTTP_PROXY +} +variable https_proxy { + default = HTTPS_PROXY +} +variable no_proxy { + default = NO_PROXY +} + +variable "UPDATE_KERNEL" { + type = bool + default = false +} + +variable KINE_VERSION { + default = "0.11.4" +} + +variable "TWO_NODE" { + type = bool + default = false +} + +variable "IS_UKI" { + type = bool + default = false +} + +variable "INCLUDE_MS_SECUREBOOT_KEYS" { + type = bool + default = true +} + +variable "AUTO_ENROLL_SECUREBOOT_KEYS" { + type = bool + default = false +} + +variable "CMDLINE" { + default = "stylus.registration" +} + +variable "BRANDING" { + default = "Palette eXtended Kubernetes Edge" +} + +variable "DEBUG" { + type = bool + default = false +} + +variable "UKI_BRING_YOUR_OWN_KEYS" { + type = bool + default = false +} + +variable "MY_ORG" { + default = "ACME Corp" +} + +variable "EXPIRATION_IN_DAYS" { + default = 5475 +} + +variable "CMDLINE" { + default = "stylus.registration" +} + +variable "BRANDING" { + default = "Palette eXtended Kubernetes Edge" +} + +variable "EFI_MAX_SIZE" { + default = "2048" +} + +variable "EFI_IMG_SIZE" { + default = "2200" +} + +variable "GOLANG_VERSION" { + default = "1.23" +} + +variable "BASE_IMAGE" { + default = "" +} + +variable "OSBUILDER_IMAGE" {} + +variable "IS_JETSON" { + type = bool + default = length(regexall("nvidia-jetson-agx-orin", BASE_IMAGE)) > 0 +} + +variable "STYLUS_BASE" { + default = "${SPECTRO_PUB_REPO}/edge/stylus-framework-linux-${ARCH}:${PE_VERSION}" +} + +variable "STYLUS_PACKAGE_BASE" { + default = "${SPECTRO_PUB_REPO}/edge/stylus-linux-${ARCH}:${PE_VERSION}" +} + +variable "BIN_TYPE" { + default = FIPS_ENABLED ? "vertex" : "palette" +} + +variable "CLI_IMAGE" { + default = FIPS_ENABLED ? "${SPECTRO_PUB_REPO}/edge/palette-edge-cli-fips-${ARCH}:${PE_VERSION}" : "${SPECTRO_PUB_REPO}/edge/palette-edge-cli-${ARCH}:${PE_VERSION}" +} + +variable "IMAGE_TAG" { + default = CUSTOM_TAG != "" ? "${PE_VERSION}-${CUSTOM_TAG}" : PE_VERSION +} + +variable "IMAGE_PATH" { + default = "${IMAGE_REGISTRY}/${IMAGE_REPO}:${K8S_DISTRIBUTION}-${K8S_VERSION}-${IMAGE_TAG}" +} + +function "get_ubuntu_image" { + params = [fips_enabled, spectro_pub_repo] + result = fips_enabled ? "${spectro_pub_repo}/third-party/ubuntu-fips:22.04" : "${spectro_pub_repo}/third-party/ubuntu:22.04" +} + +function "get_base_image" { + params = [base_image, os_distribution, os_version, is_uki] + result = base_image != "" ? base_image : ( + + os_distribution == "ubuntu" && os_version == "20" ? + "${SPECTRO_PUB_REPO}/edge/kairos-${OS_DISTRIBUTION}:${OS_VERSION}.04-core-${ARCH}-generic-${KAIROS_VERSION}" : + + os_distribution == "ubuntu" && os_version == "22" ? + "${SPECTRO_PUB_REPO}/edge/kairos-${OS_DISTRIBUTION}:${OS_VERSION}.04-core-${ARCH}-generic-${KAIROS_VERSION}" : + + os_distribution == "ubuntu" && os_version == "24" && is_uki ? + "${SPECTRO_PUB_REPO}/edge/kairos-${OS_DISTRIBUTION}:${OS_VERSION}.04-core-${ARCH}-generic-${KAIROS_VERSION}-uki" : + + os_distribution == "opensuse" && os_version == "15.6" ? + "${SPECTRO_PUB_REPO}/edge/kairos-opensuse:leap-${OS_VERSION}-core-${ARCH}-generic-${KAIROS_VERSION}" : + + "" + ) +} + +target "stylus-image" { + dockerfile = "dockerfiles/Dockerfile.stylus-image" + target = "stylus-image" + args = { + STYLUS_BASE = STYLUS_BASE + ARCH = ARCH + } + platforms = ["linux/${ARCH}"] +} + +target "base" { + dockerfile = "Dockerfile" + args = { + BASE = get_base_image(BASE_IMAGE, OS_DISTRIBUTION, OS_VERSION, IS_UKI) + OS_DISTRIBUTION = OS_DISTRIBUTION + PROXY_CERT_PATH = PROXY_CERT_PATH + HTTP_PROXY = HTTP_PROXY + HTTPS_PROXY = HTTPS_PROXY + NO_PROXY = NO_PROXY + } +} + +target "base-image" { + dockerfile = "dockerfiles/Dockerfile.base-image" + contexts = { + base = "target:base" + } + args = { + OS_DISTRIBUTION = OS_DISTRIBUTION + OS_VERSION = OS_VERSION + IS_JETSON = IS_JETSON + IS_UKI = IS_UKI + UBUNTU_PRO_KEY = UBUNTU_PRO_KEY + UPDATE_KERNEL = UPDATE_KERNEL + CIS_HARDENING = CIS_HARDENING + KAIROS_VERSION = KAIROS_VERSION + DISABLE_SELINUX = DISABLE_SELINUX + ARCH = ARCH + } +} + +function "get_provider_base" { + params = [k8s_distribution, spectro_pub_repo, kubeadm_version, k3s_version, rke2_version, nodeadm_version, canonical_version] + result = ( + k8s_distribution == "kubeadm" ? "${spectro_pub_repo}/edge/kairos-io/provider-kubeadm:${kubeadm_version}" : + k8s_distribution == "kubeadm-fips" ? "${spectro_pub_repo}/edge/kairos-io/provider-kubeadm:${kubeadm_version}" : + k8s_distribution == "k3s" ? "${spectro_pub_repo}/edge/kairos-io/provider-k3s:${k3s_version}" : + k8s_distribution == "rke2" ? "${spectro_pub_repo}/edge/kairos-io/provider-rke2:${rke2_version}" : + k8s_distribution == "nodeadm" ? "${spectro_pub_repo}/edge/kairos-io/provider-nodeadm:${nodeadm_version}" : + k8s_distribution == "canonical" ? "${spectro_pub_repo}/edge/kairos-io/provider-canonical:${canonical_version}" : + "" + ) +} + +target "kairos-provider-image" { + dockerfile = "dockerfiles/Dockerfile.kairos-provider-image" + target = "kairos-provider-image" + platforms = ["linux/${ARCH}"] + args = { + PROVIDER_BASE = get_provider_base( + K8S_DISTRIBUTION, + SPECTRO_PUB_REPO, + KUBEADM_PROVIDER_VERSION, + K3S_PROVIDER_VERSION, + RKE2_PROVIDER_VERSION, + NODEADM_PROVIDER_VERSION, + CANONICAL_PROVIDER_VERSION, + ) + } +} + +target "install-k8s" { + dockerfile = "dockerfiles/Dockerfile.install-k8s" + target = "install-k8s" + platforms = ["linux/${ARCH}"] + contexts = { + third-party-luet = "target:third-party-luet" + } + args = { + BASE_ALPINE_IMAGE = ALPINE_IMG + ARCH = ARCH + K8S_DISTRIBUTION = K8S_DISTRIBUTION + K8S_VERSION = K8S_VERSION + K3S_FLAVOR_TAG = K3S_FLAVOR_TAG + RKE2_FLAVOR_TAG = RKE2_FLAVOR_TAG + LUET_PROJECT = LUET_PROJECT + LUET_REPO = ARCH == "arm64" ? "${LUET_PROJECT}-arm" : LUET_PROJECT + SPECTRO_LUET_REPO = SPECTRO_LUET_REPO + SPECTRO_LUET_VERSION = SPECTRO_LUET_VERSION + } +} + +target "provider-image" { + dockerfile = "dockerfiles/Dockerfile.provider-image" + target = "provider-image" + platforms = ["linux/${ARCH}"] + contexts = { + base-image = "target:base-image" + kairos-provider-image = "target:kairos-provider-image" + stylus-image = "target:stylus-image" + install-k8s = "target:install-k8s" + third-party-luet = "target:third-party-luet" + third-party-etcdctl = "target:third-party-etcdctl" + internal-slink = "target:internal-slink" + } + args = { + ARCH = ARCH + IMAGE_REPO = IMAGE_REPO + K8S_DISTRIBUTION = K8S_DISTRIBUTION + K8S_VERSION = K8S_VERSION + K3S_FLAVOR_TAG = K3S_FLAVOR_TAG + RKE2_FLAVOR_TAG = RKE2_FLAVOR_TAG + OS_DISTRIBUTION = OS_DISTRIBUTION + EDGE_CUSTOM_CONFIG = EDGE_CUSTOM_CONFIG + TWO_NODE = TWO_NODE + KINE_VERSION = KINE_VERSION + IMAGE_PATH = IMAGE_PATH + IS_UKI = IS_UKI + } + tags = [IMAGE_PATH] + output = ["type=image,push=true"] +} + +target "uki-provider-image" { + dockerfile = "dockerfiles/Dockerfile.uki-provider-image" + platforms = ["linux/${ARCH}"] + contexts = { + third-party-luet = "target:third-party-luet" + install-k8s = "target:install-k8s" + trustedboot-image = "target:trustedboot-image" + } + args = { + BASE_IMAGE = get_base_image(BASE_IMAGE, OS_DISTRIBUTION, OS_VERSION, IS_UKI) + UBUNTU_IMAGE = get_ubuntu_image(FIPS_ENABLED, SPECTRO_PUB_REPO) + EDGE_CUSTOM_CONFIG = EDGE_CUSTOM_CONFIG + IMAGE_PATH = IMAGE_PATH + } + tags = [IMAGE_PATH] + output = ["type=image,push=true"] +} + +target "trustedboot-image" { + dockerfile = "dockerfiles/Dockerfile.trustedboot-image" + platforms = ["linux/${ARCH}"] + target = "output" + context = "." + contexts = { + provider-image = "target:provider-image" + } + args = { + AURORABOOT_IMAGE = AURORABOOT_IMAGE + } + output = ["type=local,dest=./trusted-boot/"] +} + +target "validate-user-data" { + dockerfile = "dockerfiles/Dockerfile.validate-ud" + target = "validate-user-data" + args = { + CLI_IMAGE = CLI_IMAGE + ARCH = ARCH + } + platforms = ["linux/${ARCH}"] +} + +target "iso-image" { + dockerfile = "dockerfiles/Dockerfile.iso-image" + target = "iso-image" + platforms = ["linux/${ARCH}"] + contexts = { + base-image = "target:base-image" + stylus-image = "target:stylus-image" + } + args = { + ARCH = ARCH + IS_UKI = IS_UKI + } + tags = ["palette-installer-image:${IMAGE_TAG}"] +} + +target "build-iso" { + dockerfile = "dockerfiles/Dockerfile.build-iso" + platforms = ["linux/${ARCH}"] + target = "output" + contexts = { + validate-user-data = "target:validate-user-data" + iso-image = "target:iso-image" + } + args = { + ARCH = ARCH + ISO_NAME = ISO_NAME + CLUSTERCONFIG = CLUSTERCONFIG + EDGE_CUSTOM_CONFIG = EDGE_CUSTOM_CONFIG + AURORABOOT_IMAGE = AURORABOOT_IMAGE + CONTAINER_IMAGE = "palette-installer-image:${IMAGE_TAG}" + } + output = ["type=local,dest=./build"] +} + +target "build-uki-iso" { + dockerfile = "dockerfiles/Dockerfile.build-uki-iso" + target = "output" + platforms = ["linux/${ARCH}"] + contexts = { + validate-user-data = "target:validate-user-data" + stylus-image-pack = "target:stylus-image-pack" + third-party-luet = "target:third-party-luet" + iso-image = "target:iso-image" + } + args = { + AURORABOOT_IMAGE = AURORABOOT_IMAGE + ARCH = ARCH + ISO_NAME = ISO_NAME + CLUSTERCONFIG = CLUSTERCONFIG + EDGE_CUSTOM_CONFIG = EDGE_CUSTOM_CONFIG + AUTO_ENROLL_SECUREBOOT_KEYS = AUTO_ENROLL_SECUREBOOT_KEYS + DEBUG = DEBUG + CMDLINE = CMDLINE + BRANDING = BRANDING + } + output = ["type=local,dest=./iso-output/"] +} + +target "stylus-image-pack" { + dockerfile = "dockerfiles/Dockerfile.stylus-image-pack" + target = "output" + platforms = ["linux/${ARCH}"] + contexts = { + third-party-luet = "target:third-party-luet" + } + args = { + STYLUS_PACKAGE_BASE = STYLUS_PACKAGE_BASE + STYLUS_BASE = STYLUS_BASE + ARCH = ARCH + } + output = ["type=local,dest=./build/"] +} + +target "uki-genkey" { + dockerfile = "dockerfiles/Dockerfile.uki-genkey" + context = "." + target = "output" + platforms = ["linux/${ARCH}"] + contexts = UKI_BRING_YOUR_OWN_KEYS ? { + uki-byok = "target:uki-byok" + } : {} + args = { + MY_ORG = MY_ORG + EXPIRATION_IN_DAYS = EXPIRATION_IN_DAYS + UKI_BRING_YOUR_OWN_KEYS = UKI_BRING_YOUR_OWN_KEYS + INCLUDE_MS_SECUREBOOT_KEYS = INCLUDE_MS_SECUREBOOT_KEYS + AURORABOOT_IMAGE = AURORABOOT_IMAGE + ARCH = ARCH + } + output = ["type=local,dest=./secure-boot/"] +} + +target "download-sbctl" { + dockerfile = "dockerfiles/Dockerfile.download-sbctl" + platforms = ["linux/${ARCH}"] + args = { + ALPINE_IMG = ALPINE_IMG + } +} + +target "uki-byok" { + dockerfile = "dockerfiles/Dockerfile.uki-byok" + platforms = ["linux/${ARCH}"] + contexts = { + download-sbctl = "target:download-sbctl" + } + args = { + UBUNTU_IMAGE = get_ubuntu_image(FIPS_ENABLED, SPECTRO_PUB_REPO) + INCLUDE_MS_SECUREBOOT_KEYS = INCLUDE_MS_SECUREBOOT_KEYS + } +} + +target "internal-slink" { + dockerfile = "dockerfiles/Dockerfile.slink" + context = "." + args = { + SPECTRO_PUB_REPO = SPECTRO_PUB_REPO + GOLANG_VERSION = GOLANG_VERSION + BIN = "slink" + SRC = "cmd/slink/slink.go" + GOOS = "linux" + GOARCH = "amd64" + } + tags = ["internal-slink:latest"] + output = ["type=local,dest=build"] +} + +target "third-party-luet" { + dockerfile = "dockerfiles/Dockerfile.third-party" + target = "third-party" + args = { + SPECTRO_THIRD_PARTY_IMAGE = SPECTRO_THIRD_PARTY_IMAGE + ALPINE_IMG = ALPINE_IMG + binary = "luet" + BIN_TYPE = BIN_TYPE + ARCH = ARCH + TARGETPLATFORM = "linux/${ARCH}" + } +} + +target "third-party-etcdctl" { + dockerfile = "dockerfiles/Dockerfile.third-party" + target = "third-party" + args = { + SPECTRO_THIRD_PARTY_IMAGE = SPECTRO_THIRD_PARTY_IMAGE + ALPINE_IMG = ALPINE_IMG + binary = "etcdctl" + BIN_TYPE = BIN_TYPE + ARCH = ARCH + TARGETPLATFORM = "linux/${ARCH}" + } +} diff --git a/dockerfiles/Dockerfile.base-image b/dockerfiles/Dockerfile.base-image new file mode 100644 index 00000000..c502b9b3 --- /dev/null +++ b/dockerfiles/Dockerfile.base-image @@ -0,0 +1,135 @@ +FROM base + +ARG OS_DISTRIBUTION +ARG OS_VERSION + +ARG IS_JETSON +ARG IS_UKI +ARG UBUNTU_PRO_KEY +ARG UPDATE_KERNEL +ARG CIS_HARDENING +ARG KAIROS_VERSION +ARG DISABLE_SELINUX +ARG ARCH + +COPY . /tmp/build-context +RUN if [ "$IS_JETSON" = "true" ]; then \ + cp /tmp/build-context/cloudconfigs/mount.yaml /system/oem/mount.yaml; \ + fi +RUN if [ "$IS_UKI" = "true" ]; then \ + cp /tmp/build-context/cloudconfigs/80_stylus_uki.yaml /system/oem/80_stylus_uki.yaml; \ + fi + +RUN if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ]; then \ + apt-get update && \ + apt-get install --no-install-recommends kbd zstd vim iputils-ping bridge-utils curl tcpdump ethtool rsyslog logrotate -y; \ + fi + +RUN if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ]; then \ + if [ "$UPDATE_KERNEL" = "false" ]; then \ + if dpkg -l "linux-image-generic-hwe-$OS_VERSION" > /dev/null 2>&1; then \ + apt-mark hold "linux-image-generic-hwe-$OS_VERSION" "linux-headers-generic-hwe-$OS_VERSION" "linux-generic-hwe-$OS_VERSION"; \ + fi && \ + if dpkg -l linux-image-generic > /dev/null 2>&1; then \ + apt-mark hold linux-image-generic linux-headers-generic linux-generic; \ + fi; \ + fi; \ + fi + +RUN if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ] && [ "$IS_UKI" = "false" ]; then \ + APT_UPGRADE_FLAGS="-y"; \ + if [ "$UPDATE_KERNEL" != "false" ]; then \ + APT_UPGRADE_FLAGS="-y --with-new-pkgs"; \ + fi && \ + DEBIAN_FRONTEND=noninteractive apt-get update && \ + apt-get upgrade $APT_UPGRADE_FLAGS && \ + latest_kernel=$(ls /lib/modules | tail -n1 | awk -F '-' '{print $1"-"$2}') && \ + apt-get purge -y $(dpkg -l | awk '/^ii\s+linux-(image|headers|modules)/ {print $2}' | grep -v "${latest_kernel}") && \ + rm -rf /var/lib/apt/lists/*; \ + fi + +RUN if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ] && [ "$IS_UKI" = "false" ]; then \ + kernel=$(ls /boot/vmlinuz-* | tail -n1) && \ + ln -sf "${kernel#/boot/}" /boot/vmlinuz && \ + kernel=$(ls /lib/modules | tail -n1); \ + dracut -f "/boot/initrd-${kernel}" "${kernel}"; \ + ln -sf "initrd-${kernel}" /boot/initrd && \ + depmod -a "${kernel}" && \ + if [ ! -f /usr/bin/grub2-editenv ]; then \ + ln -s /usr/sbin/grub-editenv /usr/bin/grub2-editenv; \ + fi; \ + fi + +RUN if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ] && [ "$CIS_HARDENING" = "true" ]; then \ + cp /tmp/build-context/cis-harden/harden.sh /tmp/harden.sh && \ + /tmp/harden.sh && rm /tmp/harden.sh; \ + fi + +RUN if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ] && [ ! -z "$UBUNTU_PRO_KEY" ]; then \ + pro detach --assume-yes; \ + fi + +RUN if [ "$OS_DISTRIBUTION" = "opensuse-leap" ] && [ "$ARCH" = "amd64" ]; then \ + if [ "$UPDATE_KERNEL" = "false" ]; then \ + zypper al kernel-de*; \ + fi && \ + zypper refresh && zypper update -y && \ + if [ -e "/usr/bin/dracut" ]; then \ + kernel=$(ls /lib/modules | tail -n1) && depmod -a "${kernel}" && \ + dracut -f "/boot/initrd-${kernel}" "${kernel}" && ln -sf "initrd-${kernel}" /boot/initrd; \ + fi && \ + zypper install -y zstd vim iputils bridge-utils curl ethtool tcpdump && \ + zypper cc && \ + zypper clean; \ + fi + +RUN if [ "$OS_DISTRIBUTION" = "opensuse-leap" ]; then \ + zypper install -y apparmor-parser apparmor-profiles rsyslog logrotate && \ + zypper cc && \ + zypper clean && \ + if [ ! -e /usr/bin/apparmor_parser ]; then \ + cp /sbin/apparmor_parser /usr/bin/apparmor_parser; \ + fi; \ + fi + +RUN if [ "$OS_DISTRIBUTION" = "rhel" ]; then \ + yum install -y openssl rsyslog logrotate; \ + fi + +RUN if [ "$OS_DISTRIBUTION" = "sles" ]; then \ + if [ ! -e /usr/bin/apparmor_parser ]; then \ + cp /sbin/apparmor_parser /usr/bin/apparmor_parser; \ + fi; \ + fi + +RUN export OS_ID=${OS_DISTRIBUTION} && \ + export OS_VERSION=${OS_VERSION} && \ + export OS_LABEL=latest && \ + export VARIANT=${OS_DISTRIBUTION} && \ + export FLAVOR=${OS_DISTRIBUTION} && \ + export BUG_REPORT_URL=https://github.com/spectrocloud/CanvOS/issues && \ + export HOME_URL=https://github.com/spectrocloud/CanvOS && \ + export OS_REPO=spectrocloud/CanvOS && \ + export OS_NAME=${kairos-core-${OS_DISTRIBUTION}} && \ + export ARTIFACT=${kairos-core-${OS_DISTRIBUTION}-${OS_VERSION}} && \ + export KAIROS_RELEASE=${OS_VERSION} && \ + envsubst >>/etc/os-release < /tmp/build-context/overlay/files/usr/lib/os-release.tmpl + +RUN rm -rf /var/cache/* && \ + journalctl --vacuum-size=1K && \ + rm -rf /etc/machine-id && \ + rm -rf /var/lib/dbus/machine-id && \ + touch /etc/machine-id && \ + chmod 444 /etc/machine-id && \ + rm /tmp/* -rf + +RUN if [ "$DISABLE_SELINUX" = "true" ]; then \ + if grep "security=selinux" /etc/cos/bootargs.cfg > /dev/null 2>&1; then \ + sed -i 's/security=selinux //g' /etc/cos/bootargs.cfg; \ + fi && \ + if grep "selinux=1" /etc/cos/bootargs.cfg > /dev/null 2>&1; then \ + sed -i 's/selinux=1/selinux=0/g' /etc/cos/bootargs.cfg; \ + fi; \ + fi + +RUN rm -rf /tmp/build-context \ No newline at end of file diff --git a/dockerfiles/Dockerfile.build-iso b/dockerfiles/Dockerfile.build-iso new file mode 100644 index 00000000..cf21da89 --- /dev/null +++ b/dockerfiles/Dockerfile.build-iso @@ -0,0 +1,65 @@ +ARG AURORABOOT_IMAGE + +FROM ${AURORABOOT_IMAGE} AS builder + +ARG ARCH +ARG ISO_NAME +ARG CLUSTERCONFIG +ARG EDGE_CUSTOM_CONFIG +ARG CONTAINER_IMAGE + +COPY overlay/files-iso/ /overlay/ + +COPY --from=validate-user-data /tmp/context /tmp/validate-context +RUN if [ -f /tmp/validate-context/user-data ]; then \ + cp /tmp/validate-context/user-data /cloud-config.yaml; \ + fi + +COPY --from=iso-image / /iso-source/ + +COPY . /tmp/build-context/ + +RUN mkdir -p /overlay/opt/spectrocloud/content +RUN if [ -d /tmp/build-context/content-* ]; then \ + find /tmp/build-context -name "content-*" -type d -exec cp -r {}/*.zst /overlay/opt/spectrocloud/content/ \; 2>/dev/null || true; \ + fi + +RUN if [ -n "$EDGE_CUSTOM_CONFIG" ] && [ -f /tmp/build-context/"$EDGE_CUSTOM_CONFIG" ]; then \ + cp /tmp/build-context/"$EDGE_CUSTOM_CONFIG" /overlay/.edge_custom_config.yaml; \ + fi + +RUN if [ -n "$(ls /overlay/opt/spectrocloud/content/*.zst 2>/dev/null)" ]; then \ + for file in /overlay/opt/spectrocloud/content/*.zst; do \ + split --bytes=3GB --numeric-suffixes "$file" /overlay/opt/spectrocloud/content/$(basename "$file")_part; \ + done; \ + rm -f /overlay/opt/spectrocloud/content/*.zst; \ + fi + +RUN if [ "$CLUSTERCONFIG" != "" ] && [ -f /tmp/build-context/"$CLUSTERCONFIG" ]; then \ + mkdir -p /overlay/opt/spectrocloud/clusterconfig && \ + cp /tmp/build-context/"$CLUSTERCONFIG" /overlay/opt/spectrocloud/clusterconfig/spc.tgz; \ + fi + +RUN if [ -f /tmp/build-context/local-ui.tar ]; then \ + mkdir -p /overlay/opt/spectrocloud && \ + tar -xf /tmp/build-context/local-ui.tar -C /overlay/opt/spectrocloud; \ + fi + +RUN mkdir -p /output + +RUN sudo /usr/bin/auroraboot \ + --debug build-iso \ + --output /output \ + --override-name ${ISO_NAME} \ + --overlay-iso /overlay \ + $(if [ -f /cloud-config.yaml ] && [ -s /cloud-config.yaml ]; then echo "--cloud-config /cloud-config.yaml"; fi) \ + dir:/iso-source + +RUN mkdir -p /iso && \ + cp /output/${ISO_NAME}.iso /iso/ && \ + cp /output/config.yaml /iso/ && \ + cd /iso && \ + sha256sum "${ISO_NAME}.iso" > "${ISO_NAME}.iso.sha256" + +FROM scratch AS output +COPY --from=builder /iso/ / \ No newline at end of file diff --git a/dockerfiles/Dockerfile.build-uki-iso b/dockerfiles/Dockerfile.build-uki-iso new file mode 100644 index 00000000..bfd339b4 --- /dev/null +++ b/dockerfiles/Dockerfile.build-uki-iso @@ -0,0 +1,73 @@ +ARG AURORABOOT_IMAGE +FROM ${AURORABOOT_IMAGE} AS builder + +ARG ARCH +ARG ISO_NAME +ARG CLUSTERCONFIG +ARG EDGE_CUSTOM_CONFIG +ARG AUTO_ENROLL_SECUREBOOT_KEYS +ARG DEBUG +ARG CMDLINE +ARG BRANDING="Palette eXtended Kubernetes Edge" + +ENV ISO_NAME=${ISO_NAME} + +COPY overlay/files-iso/ /overlay/ + +COPY --from=validate-user-data /tmp/context /tmp/validate-context +RUN if [ -f /tmp/validate-context/user-data ]; then \ + cp /tmp/validate-context/user-data /overlay/cloud-config.yaml; \ + fi + +COPY --from=stylus-image-pack /stylus-image.tar /overlay/stylus-image.tar +COPY --from=third-party-luet /WORKDIR/luet /overlay/luet + +ARG EDGE_CUSTOM_CONFIG +RUN if [ -n "$EDGE_CUSTOM_CONFIG" ] && [ -f "$EDGE_CUSTOM_CONFIG" ]; then \ + cp "$EDGE_CUSTOM_CONFIG" /overlay/.edge_custom_config.yaml; \ + fi + +RUN mkdir -p /overlay/opt/spectrocloud/content && \ + (cp content-*/*.zst /overlay/opt/spectrocloud/content/ 2>/dev/null || echo "No content files found") && \ + if ls /overlay/opt/spectrocloud/content/*.zst >/dev/null 2>&1; then \ + for file in /overlay/opt/spectrocloud/content/*.zst; do \ + split --bytes=3GB --numeric-suffixes "$file" /overlay/opt/spectrocloud/content/$(basename "$file")_part; \ + done && \ + rm -f /overlay/opt/spectrocloud/content/*.zst; \ + fi + +RUN if [ -n "$CLUSTERCONFIG" ] && [ -f "$CLUSTERCONFIG" ]; then \ + cp "$CLUSTERCONFIG" /overlay/opt/spectrocloud/clusterconfig/spc.tgz; \ + fi + +RUN if [ -f "local-ui.tar" ]; then \ + cp local-ui.tar /overlay/opt/spectrocloud/ && \ + tar -xf /overlay/opt/spectrocloud/local-ui.tar -C /overlay/opt/spectrocloud && \ + rm -f /overlay/opt/spectrocloud/local-ui.tar; \ + fi + +WORKDIR /build + +COPY --from=iso-image / /iso-source/ + +COPY secure-boot/enrollment/ /keys/ +COPY secure-boot/private-keys/ /keys/ +COPY secure-boot/public-keys/ /keys/ + +RUN if [ "$ARCH" = "amd64" ]; then \ + mkdir -p /iso && \ + /usr/bin/auroraboot build-uki \ + --output-type iso \ + --name "${ISO_NAME}" \ + --output-dir /iso \ + --overlay-iso /overlay \ + --keys /keys \ + --boot-branding "${BRANDING}" \ + $([ -n "$CMDLINE" ] && echo "--extend-cmdline \"$CMDLINE\"") \ + $([ "$AUTO_ENROLL_SECUREBOOT_KEYS" = "true" ] && echo "--secure-boot-enroll") \ + $([ "$DEBUG" = "true" ] && echo "--debug") \ + dir:/iso-source; \ + fi + +FROM scratch as output +COPY --from=builder /iso/ / \ No newline at end of file diff --git a/dockerfiles/Dockerfile.download-sbctl b/dockerfiles/Dockerfile.download-sbctl new file mode 100644 index 00000000..ce65863c --- /dev/null +++ b/dockerfiles/Dockerfile.download-sbctl @@ -0,0 +1,7 @@ +ARG ALPINE_IMG +FROM ${ALPINE_IMG} + +RUN apk add --no-cache curl tar + +RUN curl -Ls https://github.com/Foxboron/sbctl/releases/download/0.13/sbctl-0.13-linux-amd64.tar.gz | tar -xvzf - && \ + mv sbctl/sbctl /usr/bin/sbctl \ No newline at end of file diff --git a/dockerfiles/Dockerfile.install-k8s b/dockerfiles/Dockerfile.install-k8s new file mode 100644 index 00000000..0938403a --- /dev/null +++ b/dockerfiles/Dockerfile.install-k8s @@ -0,0 +1,55 @@ +ARG ARCH +ARG BASE_ALPINE_IMAGE + +FROM --platform=linux/${ARCH} ${BASE_ALPINE_IMAGE} AS install-k8s + +ARG K8S_DISTRIBUTION +ARG K8S_VERSION +ARG K3S_FLAVOR_TAG +ARG RKE2_FLAVOR_TAG +ARG LUET_PROJECT +ARG SPECTRO_LUET_REPO +ARG SPECTRO_LUET_VERSION +ARG ARCH +ARG LUET_REPO + +RUN [ -d "certs" ] && cp -r certs/. /etc/ssl/certs/ || true +RUN update-ca-certificates +RUN apk add curl + +COPY --from=third-party-luet /WORKDIR/luet /usr/bin/luet + +RUN if [ "$K8S_DISTRIBUTION" = "kubeadm" ] || [ "$K8S_DISTRIBUTION" = "kubeadm-fips" ] || [ "$K8S_DISTRIBUTION" = "nodeadm" ] || [ "$K8S_DISTRIBUTION" = "canonical" ]; then \ + BASE_K8S_VERSION="$K8S_VERSION"; \ + elif [ "$K8S_DISTRIBUTION" = "k3s" ]; then \ + K8S_DISTRIBUTION_TAG="$K3S_FLAVOR_TAG"; \ + BASE_K8S_VERSION="$K8S_VERSION-$K8S_DISTRIBUTION_TAG"; \ + elif [ "$K8S_DISTRIBUTION" = "rke2" ]; then \ + K8S_DISTRIBUTION_TAG="$RKE2_FLAVOR_TAG"; \ + BASE_K8S_VERSION="$K8S_VERSION-$K8S_DISTRIBUTION_TAG"; \ + fi + +WORKDIR /output + +RUN mkdir -p /etc/luet/repos.conf.d && \ + luet repo add spectro --type docker --url $SPECTRO_LUET_REPO/$LUET_REPO/$SPECTRO_LUET_VERSION --priority 1 -y + +COPY . /tmp/build-context/ +RUN if [ -f /tmp/build-context/spectro-luet-auth.yaml ]; then \ + cp /tmp/build-context/spectro-luet-auth.yaml spectro-luet-auth.yaml && \ + cat spectro-luet-auth.yaml >> /etc/luet/repos.conf.d/spectro.yaml; \ + fi + +RUN luet repo update + +RUN if [ "$K8S_DISTRIBUTION" = "kubeadm" ]; then \ + luet install -y container-runtime/containerd --system-target /output; \ + fi + +RUN if [ "$K8S_DISTRIBUTION" = "kubeadm-fips" ]; then \ + luet install -y container-runtime/containerd-fips --system-target /output; \ + fi + +RUN luet install -y k8s/$K8S_DISTRIBUTION@$BASE_K8S_VERSION --system-target /output && luet cleanup + +RUN rm -rf /output/var/cache/* \ No newline at end of file diff --git a/dockerfiles/Dockerfile.iso-image b/dockerfiles/Dockerfile.iso-image new file mode 100644 index 00000000..bb28f3d9 --- /dev/null +++ b/dockerfiles/Dockerfile.iso-image @@ -0,0 +1,21 @@ +ARG ARCH +ARG IS_UKI + +FROM base-image AS iso-image + +COPY --from=stylus-image / / + +RUN if [ "$IS_UKI" = "true" ]; then \ + find /opt/spectrocloud/bin/. ! -name 'agent-provider-stylus' -type f -exec rm -f {} + && \ + rm -f /usr/bin/luet; \ + fi + +COPY overlay/files/ / + +RUN if [ -f /etc/logrotate.d/stylus.conf ]; then \ + chmod 644 /etc/logrotate.d/stylus.conf; \ + fi + +RUN rm -f /etc/ssh/ssh_host_* /etc/ssh/moduli && \ + touch /etc/machine-id && \ + chmod 444 /etc/machine-id \ No newline at end of file diff --git a/dockerfiles/Dockerfile.kairos-provider-image b/dockerfiles/Dockerfile.kairos-provider-image new file mode 100644 index 00000000..1cd58a0b --- /dev/null +++ b/dockerfiles/Dockerfile.kairos-provider-image @@ -0,0 +1,3 @@ +ARG PROVIDER_BASE + +FROM ${PROVIDER_BASE} AS kairos-provider-image \ No newline at end of file diff --git a/dockerfiles/Dockerfile.provider-image b/dockerfiles/Dockerfile.provider-image new file mode 100644 index 00000000..60237eaf --- /dev/null +++ b/dockerfiles/Dockerfile.provider-image @@ -0,0 +1,99 @@ +ARG ARCH + +FROM base-image AS provider-image + +ARG IMAGE_REPO +ARG K8S_DISTRIBUTION +ARG K8S_VERSION +ARG K3S_FLAVOR_TAG +ARG RKE2_FLAVOR_TAG +ARG OS_DISTRIBUTION +ARG EDGE_CUSTOM_CONFIG +ARG TWO_NODE +ARG KINE_VERSION +ARG IMAGE_PATH +ARG IS_UKI +ARG ARCH + +RUN if [ "$K8S_DISTRIBUTION" = "kubeadm" ] || [ "$K8S_DISTRIBUTION" = "kubeadm-fips" ] || [ "$K8S_DISTRIBUTION" = "nodeadm" ]; then \ + BASE_K8S_VERSION="$K8S_VERSION"; \ + if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ] && [ "$K8S_DISTRIBUTION" = "kubeadm" ]; then \ + kernel=$(ls /lib/modules | tail -n1) && if ! ls /usr/src | grep linux-headers-$kernel; then apt-get update && apt-get install -y "linux-headers-${kernel}"; fi; \ + fi; \ + elif [ "$K8S_DISTRIBUTION" = "k3s" ]; then \ + K8S_DISTRIBUTION_TAG="$K3S_FLAVOR_TAG"; \ + BASE_K8S_VERSION="$K8S_VERSION-$K8S_DISTRIBUTION_TAG"; \ + elif [ "$K8S_DISTRIBUTION" = "rke2" ]; then \ + K8S_DISTRIBUTION_TAG="$RKE2_FLAVOR_TAG"; \ + BASE_K8S_VERSION="$K8S_VERSION-$K8S_DISTRIBUTION_TAG"; \ + fi + +COPY overlay/files/etc/ /etc/ + +RUN if [ -f /etc/logrotate.d/stylus.conf ]; then \ + chmod 644 /etc/logrotate.d/stylus.conf; \ + fi + +COPY --from=kairos-provider-image / / +COPY --from=stylus-image /etc/kairos/branding /etc/kairos/branding +COPY --from=stylus-image /oem/stylus_config.yaml /etc/kairos/branding/stylus_config.yaml +COPY --from=stylus-image /etc/elemental/config.yaml /etc/elemental/config.yaml + +COPY . /tmp/build-context/ +RUN if [ -f /tmp/build-context/"$EDGE_CUSTOM_CONFIG" ]; then \ + cp /tmp/build-context/"$EDGE_CUSTOM_CONFIG" /oem/.edge_custom_config.yaml; \ + fi + +COPY --from=install-k8s /output/ /tmp/k8s-output/ +COPY --from=internal-slink /slink /usr/bin/slink + +RUN if [ "$IS_UKI" = "true" ]; then \ + mkdir -p /k8s && cp -r /tmp/k8s-output/* /k8s/ && \ + slink --source /k8s/ --target /opt/k8s && \ + rm -f /usr/bin/slink && \ + rm -rf /k8s && \ + ln -sf /opt/spectrocloud/bin/agent-provider-stylus /usr/local/bin/agent-provider-stylus; \ + else \ + cp -r /tmp/k8s-output/* /; \ + fi && \ + rm -rf /tmp/k8s-output + +RUN rm -f /etc/ssh/ssh_host_* /etc/ssh/moduli + +COPY --from=third-party-etcdctl /WORKDIR/etcdctl /usr/bin/ + +RUN touch /etc/machine-id && \ + chmod 444 /etc/machine-id + +RUN if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$K8S_DISTRIBUTION" = "nodeadm" ]; then \ + apt-get update -y && apt-get install -y gnupg && \ + /opt/nodeadmutil/bin/nodeadm install -p iam-ra $K8S_VERSION --skip validate && \ + /opt/nodeadmutil/bin/nodeadm install -p ssm $K8S_VERSION --skip validate && \ + find /opt/ssm -type f -name "amazon-ssm-agent.deb" -exec sudo dpkg -i {} \; && \ + apt-get remove gnupg -y && apt autoremove -y && \ + mv /usr/local/bin/aws-iam-authenticator /usr/bin && \ + mv /usr/local/bin/aws_signing_helper /usr/bin && \ + cp /lib/systemd/system/amazon-ssm-agent.service /etc/systemd/system/snap.amazon-ssm-agent.amazon-ssm-agent.service; \ + fi + +RUN if [ "$TWO_NODE" = "true" ]; then \ + if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ]; then \ + apt install -y ca-certificates curl && \ + install -d /usr/share/postgresql-common/pgdg && \ + curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc && \ + echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list && \ + apt update && \ + apt install -y postgresql-16 postgresql-contrib-16 iputils-ping; \ + elif [ "$OS_DISTRIBUTION" = "opensuse-leap" ] && [ "$ARCH" = "amd64" ]; then \ + zypper --non-interactive --quiet addrepo --refresh -p 90 http://download.opensuse.org/repositories/server:database:postgresql/openSUSE_Tumbleweed/ PostgreSQL && \ + zypper --gpg-auto-import-keys ref && \ + zypper install -y postgresql-16 postgresql-server-16 postgresql-contrib iputils; \ + fi && \ + mkdir -p /opt/spectrocloud/bin && \ + curl -L https://github.com/k3s-io/kine/releases/download/v${KINE_VERSION}/kine-amd64 | install -m 755 /dev/stdin /opt/spectrocloud/bin/kine && \ + su postgres -c 'echo "export PERL5LIB=/usr/share/perl/5.34:/etc/perl:/usr/lib/x86_64-linux-gnu/perl5/5.34:/usr/share/perl5:/usr/lib/x86_64-linux-gnu/perl/5.34:/usr/lib/x86_64-linux-gnu/perl-base" > ~/.bash_profile' && \ + sed -i 's/After=network.target/After=network-online.target/' /lib/systemd/system/postgresql@.service && \ + systemctl disable postgresql; \ + fi + +RUN rm -rf /tmp/build-context \ No newline at end of file diff --git a/dockerfiles/Dockerfile.slink b/dockerfiles/Dockerfile.slink new file mode 100644 index 00000000..b69cb2bb --- /dev/null +++ b/dockerfiles/Dockerfile.slink @@ -0,0 +1,33 @@ +ARG SPECTRO_PUB_REPO +ARG GOLANG_VERSION + +FROM ${SPECTRO_PUB_REPO}/third-party/golang:${GOLANG_VERSION}-alpine AS go-deps + +RUN apk add libc-dev binutils-gold clang + +FROM go-deps AS build + +WORKDIR /build + +COPY internal internal + +ARG BUILD_DIR=/build/internal +WORKDIR ${BUILD_DIR} + +ARG VERSION +ARG BIN +ARG SRC +ARG GOOS +ARG GOARCH + +ENV GOOS=${GOOS} +ENV GOARCH=${GOARCH} +ENV GO_LDFLAGS="-X github.com/spectrocloud/stylus/pkg/version.Version=${VERSION} -w -s" +ENV CC=clang + +RUN go mod download + +RUN go-build-static.sh -a -o ${BIN} ./${SRC} + +FROM scratch AS export +COPY --from=build /build/internal/${BIN} /${BIN} \ No newline at end of file diff --git a/dockerfiles/Dockerfile.stylus-image b/dockerfiles/Dockerfile.stylus-image new file mode 100644 index 00000000..448b5d4d --- /dev/null +++ b/dockerfiles/Dockerfile.stylus-image @@ -0,0 +1,3 @@ +ARG STYLUS_BASE +ARG ARCH +FROM --platform=linux/${ARCH} ${STYLUS_BASE} AS stylus-image \ No newline at end of file diff --git a/dockerfiles/Dockerfile.stylus-image-pack b/dockerfiles/Dockerfile.stylus-image-pack new file mode 100644 index 00000000..c6777425 --- /dev/null +++ b/dockerfiles/Dockerfile.stylus-image-pack @@ -0,0 +1,18 @@ +ARG STYLUS_PACKAGE_BASE +FROM ${STYLUS_PACKAGE_BASE} AS stylus-package + +FROM alpine AS packer + +ARG STYLUS_BASE +ARG ARCH + +COPY --from=third-party-luet /WORKDIR/luet /usr/bin/luet + +COPY --from=stylus-package / /stylus/ + +RUN cd /stylus && \ + tar -czf /stylus.tar * && \ + luet util pack "$STYLUS_BASE" /stylus.tar /stylus-image.tar + +FROM scratch as output +COPY --from=packer /stylus-image.tar / \ No newline at end of file diff --git a/dockerfiles/Dockerfile.third-party b/dockerfiles/Dockerfile.third-party new file mode 100644 index 00000000..dd6e0b43 --- /dev/null +++ b/dockerfiles/Dockerfile.third-party @@ -0,0 +1,23 @@ +ARG SPECTRO_THIRD_PARTY_IMAGE +ARG TARGETPLATFORM +ARG ALPINE_IMG + +FROM --platform=${TARGETPLATFORM} ${SPECTRO_THIRD_PARTY_IMAGE} AS source +FROM --platform=${TARGETPLATFORM} ${ALPINE_IMG} AS download-third-party + +ARG ARCH +ARG BIN_TYPE +ARG binary + +COPY --from=source /binaries/${binary}/latest/${BIN_TYPE}/${ARCH}/${binary} /artifacts/${binary} +COPY --from=source /binaries/${binary}/latest/${BIN_TYPE}/${ARCH}/${binary}.version /artifacts/${binary}.version + +FROM ${ALPINE_IMG} AS third-party + +ARG ARCH +ARG binary + +WORKDIR /WORKDIR +COPY --from=download-third-party /artifacts/${binary} /WORKDIR/${binary} +COPY --from=download-third-party /artifacts/${binary}.version /WORKDIR/${binary}.version +RUN upx -1 /WORKDIR/${binary} \ No newline at end of file diff --git a/dockerfiles/Dockerfile.trustedboot-image b/dockerfiles/Dockerfile.trustedboot-image new file mode 100644 index 00000000..c33181c4 --- /dev/null +++ b/dockerfiles/Dockerfile.trustedboot-image @@ -0,0 +1,23 @@ +ARG AURORABOOT_IMAGE + +FROM provider-image AS provider-image-rootfs + +FROM ${AURORABOOT_IMAGE} AS builder + +COPY --from=provider-image-rootfs / /build/image/ + +COPY secure-boot/enrollment/ /keys/ +COPY secure-boot/private-keys/ /keys/ +COPY secure-boot/public-keys/ /keys/ + +RUN mkdir -p /output + +RUN /usr/bin/auroraboot build-uki \ + --output-dir /output \ + --keys /keys \ + --output-type container \ + --boot-branding "Palette eXtended Kubernetes Edge" \ + dir:/build/image + +FROM scratch AS output +COPY --from=builder /output/ / \ No newline at end of file diff --git a/dockerfiles/Dockerfile.uki-byok b/dockerfiles/Dockerfile.uki-byok new file mode 100644 index 00000000..598923d3 --- /dev/null +++ b/dockerfiles/Dockerfile.uki-byok @@ -0,0 +1,71 @@ +ARG UBUNTU_IMAGE + +FROM ${UBUNTU_IMAGE} + +ARG INCLUDE_MS_SECUREBOOT_KEYS=false + +RUN apt-get update && apt-get install -y efitools curl + +COPY --from=download-sbctl /usr/bin/sbctl /usr/bin/sbctl + +RUN mkdir -p /exported-keys /keys +RUN if [ -d "secure-boot/private-keys" ]; then \ + cp -r secure-boot/private-keys/ /keys/ ; \ + fi + +RUN if [ -d "secure-boot/public-keys" ]; then \ + cp -r secure-boot/public-keys/* /keys/ ; \ + fi + +RUN if [ -d "secure-boot/exported-keys" ]; then \ + cp -r secure-boot/exported-keys/* /exported-keys/ ; \ + fi + +WORKDIR /keys + +RUN sbctl import-keys \ + --pk-key /keys/PK.key \ + --pk-cert /keys/PK.pem \ + --kek-key /keys/KEK.key \ + --kek-cert /keys/KEK.pem \ + --db-key /keys/db.key \ + --db-cert /keys/db.pem + +RUN sbctl create-keys + +RUN if [ "$INCLUDE_MS_SECUREBOOT_KEYS" = "false" ]; then \ + sbctl enroll-keys --export esl --yes-this-might-brick-my-machine; \ + else \ + sbctl enroll-keys --export esl --yes-this-might-brick-my-machine --microsoft; \ + fi + +RUN mkdir -p /output + +RUN cp PK.esl /output/PK.esl 2>/dev/null || true && \ + cp KEK.esl /output/KEK.esl 2>/dev/null || true && \ + cp db.esl /output/db.esl 2>/dev/null || true + +RUN if [ -f dbx.esl ]; then \ + cp dbx.esl /output/dbx.esl; \ + else \ + touch /output/dbx.esl; \ + fi + +RUN [ -f /exported-keys/KEK ] && cat /exported-keys/KEK >> /output/KEK.esl || true && \ + [ -f /exported-keys/db ] && cat /exported-keys/db >> /output/db.esl || true && \ + [ -f /exported-keys/dbx ] && cat /exported-keys/dbx >> /output/dbx.esl || true + +WORKDIR /output + +RUN sign-efi-sig-list -c /keys/PK.pem -k /keys/PK.key PK PK.esl PK.auth && \ + sign-efi-sig-list -c /keys/PK.pem -k /keys/PK.key KEK KEK.esl KEK.auth && \ + sign-efi-sig-list -c /keys/KEK.pem -k /keys/KEK.key db db.esl db.auth && \ + sign-efi-sig-list -c /keys/KEK.pem -k /keys/KEK.key dbx dbx.esl dbx.auth + +RUN sig-list-to-certs 'PK.esl' 'PK' && \ + sig-list-to-certs 'KEK.esl' 'KEK' && \ + sig-list-to-certs 'db.esl' 'db' + +RUN cp PK-0.der PK.der 2>/dev/null || true && \ + cp KEK-0.der KEK.der 2>/dev/null || true && \ + cp db-0.der db.der 2>/dev/null || true \ No newline at end of file diff --git a/dockerfiles/Dockerfile.uki-genkey b/dockerfiles/Dockerfile.uki-genkey new file mode 100644 index 00000000..ffcabb1a --- /dev/null +++ b/dockerfiles/Dockerfile.uki-genkey @@ -0,0 +1,65 @@ +ARG MY_ORG +ARG EXPIRATION_IN_DAYS +ARG UKI_BRING_YOUR_OWN_KEYS +ARG INCLUDE_MS_SECUREBOOT_KEYS +ARG AURORABOOT_IMAGE +ARG ARCH + +FROM ${AURORABOOT_IMAGE} AS builder + +RUN if [ "$UKI_BRING_YOUR_OWN_KEYS" != "true" ]; then \ + mkdir -p /custom-keys && \ + if [ -d "secure-boot/exported-keys" ]; then \ + cp -r secure-boot/exported-keys/* /custom-keys/ 2>/dev/null || true; \ + fi && \ + \ + if [ "$INCLUDE_MS_SECUREBOOT_KEYS" != "true" ]; then \ + if [[ -f /custom-keys/KEK && -f /custom-keys/db ]]; then \ + echo "Generating Secure Boot keys, including exported UEFI keys..." && \ + /usr/bin/auroraboot genkey \ + "$MY_ORG" \ + --custom-cert-dir /custom-keys \ + --skip-microsoft-certs-I-KNOW-WHAT-IM-DOING \ + --expiration-days $EXPIRATION_IN_DAYS \ + --output /keys; \ + else \ + echo "Generating Secure Boot keys..." && \ + /usr/bin/auroraboot genkey \ + "$MY_ORG" \ + --skip-microsoft-certs-I-KNOW-WHAT-IM-DOING \ + --expiration-days $EXPIRATION_IN_DAYS \ + --output /keys; \ + fi; \ + else \ + if [[ -f /custom-keys/KEK && -f /custom-keys/db ]]; then \ + echo "Generating Secure Boot keys, including exported UEFI keys and Microsoft keys..." && \ + /usr/bin/auroraboot genkey \ + "$MY_ORG" \ + --custom-cert-dir /custom-keys \ + --expiration-days $EXPIRATION_IN_DAYS \ + --output /keys; \ + else \ + echo "Generating Secure Boot keys, including Microsoft keys..." && \ + /usr/bin/auroraboot genkey \ + "$MY_ORG" \ + --expiration-days $EXPIRATION_IN_DAYS \ + --output /keys; \ + fi; \ + fi && \ + \ + ls -ltrh /keys && \ + mkdir -p /private-keys /public-keys && \ + cd /keys && mv *.key tpm2-pcr-private.pem /private-keys/ 2>/dev/null || true && \ + cd /keys && mv *.pem /public-keys/ 2>/dev/null || true; \ + else \ + mkdir -p /keys && \ + if [ -d "uki-byok" ]; then \ + cp -r uki-byok/* /keys/ 2>/dev/null || true; \ + fi; \ + fi + +FROM scratch as output + +COPY --from=builder /keys/ /enrollment/ +COPY --from=builder /private-keys/ /private-keys/ +COPY --from=builder /public-keys/ /public-keys/ \ No newline at end of file diff --git a/dockerfiles/Dockerfile.uki-provider-image b/dockerfiles/Dockerfile.uki-provider-image new file mode 100644 index 00000000..1c127325 --- /dev/null +++ b/dockerfiles/Dockerfile.uki-provider-image @@ -0,0 +1,34 @@ +ARG UBUNTU_IMAGE +ARG BASE_IMAGE +ARG OSBUILDER_IMAGE + +FROM ${BASE_IMAGE} AS kairos-agent +RUN mkdir -p /output +RUN cp /usr/bin/kairos-agent /output/kairos-agent + +FROM ${UBUNTU_IMAGE} AS trust-boot-unpack + +COPY --from=third-party-luet /WORKDIR/luet /usr/bin/luet +COPY --from=trustedboot-image / /image/ + +RUN FILE="file:/$(find /image -type f -name "*.tar" | head -n 1)" && \ + luet util unpack $FILE /trusted-boot + +FROM ${UBUNTU_IMAGE} AS uki-provider-image + +ARG EDGE_CUSTOM_CONFIG + +RUN apt-get update && apt-get install -y rsync + +WORKDIR / +COPY overlay/files/etc/ /etc/ +RUN if [ -f /etc/logrotate.d/stylus.conf ]; then chmod 644 /etc/logrotate.d/stylus.conf; fi + +COPY --from=third-party-luet /WORKDIR/luet /usr/bin/luet +COPY --from=kairos-agent /output/kairos-agent /usr/bin/kairos-agent +COPY --from=trust-boot-unpack /trusted-boot/ /trusted-boot/ +COPY --from=install-k8s /output/ /k8s/ + +RUN if [ -f "$EDGE_CUSTOM_CONFIG" ]; then \ + cp "$EDGE_CUSTOM_CONFIG" /oem/.edge_custom_config.yaml; \ + fi \ No newline at end of file diff --git a/dockerfiles/Dockerfile.validate-ud b/dockerfiles/Dockerfile.validate-ud new file mode 100644 index 00000000..7c110507 --- /dev/null +++ b/dockerfiles/Dockerfile.validate-ud @@ -0,0 +1,16 @@ +ARG CLI_IMAGE +ARG ARCH +FROM --platform=linux/${ARCH} ${CLI_IMAGE} AS validate-user-data +COPY . /tmp/context +RUN if [ -f /tmp/context/user-data ]; then \ + cp /tmp/context/user-data /user-data; \ + else \ + echo "user-data file does not exist (skipping copy)"; \ + fi + +RUN chmod +x /usr/local/bin/palette-edge-cli +RUN if [ -f /user-data ]; then \ + /usr/local/bin/palette-edge-cli validate -f /user-data; \ + else \ + echo "user-data file does not exist."; \ + fi \ No newline at end of file diff --git a/dockerfiles/kairosify/Dockerfile.kairosify b/dockerfiles/kairosify/Dockerfile.kairosify new file mode 100644 index 00000000..8e2afe3e --- /dev/null +++ b/dockerfiles/kairosify/Dockerfile.kairosify @@ -0,0 +1,24 @@ +ARG KAIROS_INIT_IMAGE +ARG BASE_OS_IMAGE + +FROM ${KAIROS_INIT_IMAGE} AS kairos-init +FROM ${BASE_OS_IMAGE} AS baseos + +ARG MODEL +ARG KAIROS_VERSION +ARG TRUSTED_BOOT +ARG BASE_OS_IMAGE + +COPY --from=kairos-init /kairos-init /kairos-init +RUN /kairos-init -l debug -m "${MODEL}" -t "${TRUSTED_BOOT}" --version "${KAIROS_VERSION}" && rm /kairos-init + +RUN if echo "${BASE_OS_IMAGE}" | grep -q ubuntu; then \ + apt-get update && apt-get install -y --no-install-recommends \ + dracut dracut-network isc-dhcp-common isc-dhcp-client cloud-guest-utils \ + $([ "$BASE_OS_IMAGE" != "ubuntu:20.04" ] && echo "dracut-live"); \ + fi + +RUN if echo "${BASE_OS_IMAGE}" | grep -q opensuse; then \ + zypper refresh && zypper update -y && \ + zypper install -y dracut dhcp-client squashfs; \ + fi \ No newline at end of file From c3d45d61bb46f92b525bf42299dd7c3c4db36920 Mon Sep 17 00:00:00 2001 From: kpiyush17 Date: Wed, 23 Jul 2025 22:56:53 +0530 Subject: [PATCH 02/40] added ubuntu 24 --- docker-bake.hcl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docker-bake.hcl b/docker-bake.hcl index ac331ec4..57f2fc49 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -249,6 +249,9 @@ function "get_base_image" { os_distribution == "ubuntu" && os_version == "22" ? "${SPECTRO_PUB_REPO}/edge/kairos-${OS_DISTRIBUTION}:${OS_VERSION}.04-core-${ARCH}-generic-${KAIROS_VERSION}" : + + os_distribution == "ubuntu" && os_version == "24" ? + "${SPECTRO_PUB_REPO}/edge/kairos-${OS_DISTRIBUTION}:${OS_VERSION}.04-core-${ARCH}-generic-${KAIROS_VERSION}" : os_distribution == "ubuntu" && os_version == "24" && is_uki ? "${SPECTRO_PUB_REPO}/edge/kairos-${OS_DISTRIBUTION}:${OS_VERSION}.04-core-${ARCH}-generic-${KAIROS_VERSION}-uki" : From a01cb795e635a0ed88e255aac2957ab989b71e27 Mon Sep 17 00:00:00 2001 From: kpiyush17 Date: Fri, 25 Jul 2025 10:47:22 +0530 Subject: [PATCH 03/40] removed sudo --- dockerfiles/Dockerfile.build-iso | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dockerfiles/Dockerfile.build-iso b/dockerfiles/Dockerfile.build-iso index cf21da89..6140c8ae 100644 --- a/dockerfiles/Dockerfile.build-iso +++ b/dockerfiles/Dockerfile.build-iso @@ -47,7 +47,7 @@ RUN if [ -f /tmp/build-context/local-ui.tar ]; then \ RUN mkdir -p /output -RUN sudo /usr/bin/auroraboot \ +RUN /usr/bin/auroraboot \ --debug build-iso \ --output /output \ --override-name ${ISO_NAME} \ @@ -57,7 +57,6 @@ RUN sudo /usr/bin/auroraboot \ RUN mkdir -p /iso && \ cp /output/${ISO_NAME}.iso /iso/ && \ - cp /output/config.yaml /iso/ && \ cd /iso && \ sha256sum "${ISO_NAME}.iso" > "${ISO_NAME}.iso.sha256" From d72b5b83c940449f759101d85273d1d2aca9ef32 Mon Sep 17 00:00:00 2001 From: kpiyush17 Date: Tue, 29 Jul 2025 11:44:35 +0530 Subject: [PATCH 04/40] fips rhel ubuntu --- docker-bake.hcl | 13 +-- dockerfiles/Dockerfile.base-image | 109 ++++++++++++++------------ dockerfiles/Dockerfile.download-sbctl | 7 -- dockerfiles/Dockerfile.uki-byok | 4 +- ubuntu-fips/20.04/build.sh | 2 +- 5 files changed, 64 insertions(+), 71 deletions(-) delete mode 100644 dockerfiles/Dockerfile.download-sbctl diff --git a/docker-bake.hcl b/docker-bake.hcl index 57f2fc49..769129b1 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -44,7 +44,7 @@ variable "KAIROS_VERSION" { } variable AURORABOOT_IMAGE { - default = "quay.io/kairos/auroraboot:v0.8.7" + default = "quay.io/kairos/auroraboot:v0.10.0" } variable "K3S_PROVIDER_VERSION" { @@ -520,20 +520,9 @@ target "uki-genkey" { output = ["type=local,dest=./secure-boot/"] } -target "download-sbctl" { - dockerfile = "dockerfiles/Dockerfile.download-sbctl" - platforms = ["linux/${ARCH}"] - args = { - ALPINE_IMG = ALPINE_IMG - } -} - target "uki-byok" { dockerfile = "dockerfiles/Dockerfile.uki-byok" platforms = ["linux/${ARCH}"] - contexts = { - download-sbctl = "target:download-sbctl" - } args = { UBUNTU_IMAGE = get_ubuntu_image(FIPS_ENABLED, SPECTRO_PUB_REPO) INCLUDE_MS_SECUREBOOT_KEYS = INCLUDE_MS_SECUREBOOT_KEYS diff --git a/dockerfiles/Dockerfile.base-image b/dockerfiles/Dockerfile.base-image index c502b9b3..f3ced693 100644 --- a/dockerfiles/Dockerfile.base-image +++ b/dockerfiles/Dockerfile.base-image @@ -21,72 +21,81 @@ RUN if [ "$IS_UKI" = "true" ]; then \ fi RUN if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ]; then \ + if [ ! -z "$UBUNTU_PRO_KEY" ]; then \ + sed -i '/^[[:space:]]*$/d' /etc/os-release && \ + apt update && apt-get install -y snapd && \ + pro attach $UBUNTU_PRO_KEY; \ + fi && \ + \ apt-get update && \ - apt-get install --no-install-recommends kbd zstd vim iputils-ping bridge-utils curl tcpdump ethtool rsyslog logrotate -y; \ - fi - -RUN if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ]; then \ + apt-get install --no-install-recommends kbd zstd vim iputils-ping bridge-utils curl tcpdump ethtool rsyslog logrotate -y && \ + \ + APT_UPGRADE_FLAGS="-y" && \ if [ "$UPDATE_KERNEL" = "false" ]; then \ - if dpkg -l "linux-image-generic-hwe-$OS_VERSION" > /dev/null 2>&1; then \ + if dpkg -l "linux-image-generic-hwe-$OS_VERSION" > /dev/null; then \ apt-mark hold "linux-image-generic-hwe-$OS_VERSION" "linux-headers-generic-hwe-$OS_VERSION" "linux-generic-hwe-$OS_VERSION"; \ fi && \ - if dpkg -l linux-image-generic > /dev/null 2>&1; then \ + if dpkg -l linux-image-generic > /dev/null; then \ apt-mark hold linux-image-generic linux-headers-generic linux-generic; \ fi; \ - fi; \ - fi - -RUN if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ] && [ "$IS_UKI" = "false" ]; then \ - APT_UPGRADE_FLAGS="-y"; \ - if [ "$UPDATE_KERNEL" != "false" ]; then \ + else \ APT_UPGRADE_FLAGS="-y --with-new-pkgs"; \ fi && \ - DEBIAN_FRONTEND=noninteractive apt-get update && \ - apt-get upgrade $APT_UPGRADE_FLAGS && \ - latest_kernel=$(ls /lib/modules | tail -n1 | awk -F '-' '{print $1"-"$2}') && \ - apt-get purge -y $(dpkg -l | awk '/^ii\s+linux-(image|headers|modules)/ {print $2}' | grep -v "${latest_kernel}") && \ - rm -rf /var/lib/apt/lists/*; \ - fi - -RUN if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ] && [ "$IS_UKI" = "false" ]; then \ - kernel=$(ls /boot/vmlinuz-* | tail -n1) && \ - ln -sf "${kernel#/boot/}" /boot/vmlinuz && \ - kernel=$(ls /lib/modules | tail -n1); \ - dracut -f "/boot/initrd-${kernel}" "${kernel}"; \ - ln -sf "initrd-${kernel}" /boot/initrd && \ - depmod -a "${kernel}" && \ - if [ ! -f /usr/bin/grub2-editenv ]; then \ - ln -s /usr/sbin/grub-editenv /usr/bin/grub2-editenv; \ - fi; \ - fi - -RUN if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ] && [ "$CIS_HARDENING" = "true" ]; then \ - cp /tmp/build-context/cis-harden/harden.sh /tmp/harden.sh && \ - /tmp/harden.sh && rm /tmp/harden.sh; \ - fi - -RUN if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ] && [ ! -z "$UBUNTU_PRO_KEY" ]; then \ - pro detach --assume-yes; \ - fi - -RUN if [ "$OS_DISTRIBUTION" = "opensuse-leap" ] && [ "$ARCH" = "amd64" ]; then \ - if [ "$UPDATE_KERNEL" = "false" ]; then \ - zypper al kernel-de*; \ + \ + if [ "$IS_UKI" = "false" ]; then \ + DEBIAN_FRONTEND=noninteractive apt-get update && \ + apt-get upgrade $APT_UPGRADE_FLAGS && \ + latest_kernel=$(ls /lib/modules | tail -n1 | awk -F '-' '{print $1"-"$2}') && \ + apt-get purge -y $(dpkg -l | awk '/^ii\s+linux-(image|headers|modules)/ {print $2}' | grep -v "${latest_kernel}") && \ + apt-get autoremove -y && \ + rm -rf /var/lib/apt/lists/* && \ + \ + kernel=$(ls /boot/vmlinuz-* | tail -n1) && \ + ln -sf "${kernel#/boot/}" /boot/vmlinuz && \ + kernel=$(ls /lib/modules | tail -n1) && \ + dracut -f "/boot/initrd-${kernel}" "${kernel}" && \ + ln -sf "initrd-${kernel}" /boot/initrd && \ + depmod -a "${kernel}" && \ + \ + if [ ! -f /usr/bin/grub2-editenv ]; then \ + ln -s /usr/sbin/grub-editenv /usr/bin/grub2-editenv; \ + fi; \ fi && \ - zypper refresh && zypper update -y && \ - if [ -e "/usr/bin/dracut" ]; then \ - kernel=$(ls /lib/modules | tail -n1) && depmod -a "${kernel}" && \ - dracut -f "/boot/initrd-${kernel}" "${kernel}" && ln -sf "initrd-${kernel}" /boot/initrd; \ + \ + if [ "$CIS_HARDENING" = "true" ]; then \ + cp /tmp/build-context/cis-harden/harden.sh /tmp/harden.sh && \ + /tmp/harden.sh && rm /tmp/harden.sh; \ fi && \ - zypper install -y zstd vim iputils bridge-utils curl ethtool tcpdump && \ - zypper cc && \ - zypper clean; \ + \ + if [ ! -z "$UBUNTU_PRO_KEY" ]; then \ + pro detach --assume-yes; \ + fi; \ fi RUN if [ "$OS_DISTRIBUTION" = "opensuse-leap" ]; then \ + if [ "$ARCH" = "amd64" ]; then \ + if [ "$UPDATE_KERNEL" = "false" ]; then \ + zypper al kernel-de*; \ + fi && \ + \ + zypper refresh && zypper update -y && \ + \ + if [ -e "/usr/bin/dracut" ]; then \ + kernel=$(ls /lib/modules | tail -n1) && \ + depmod -a "${kernel}" && \ + dracut -f "/boot/initrd-${kernel}" "${kernel}" && \ + ln -sf "initrd-${kernel}" /boot/initrd; \ + fi && \ + \ + zypper install -y zstd vim iputils bridge-utils curl ethtool tcpdump && \ + zypper cc && \ + zypper clean; \ + fi && \ + \ zypper install -y apparmor-parser apparmor-profiles rsyslog logrotate && \ zypper cc && \ zypper clean && \ + \ if [ ! -e /usr/bin/apparmor_parser ]; then \ cp /sbin/apparmor_parser /usr/bin/apparmor_parser; \ fi; \ diff --git a/dockerfiles/Dockerfile.download-sbctl b/dockerfiles/Dockerfile.download-sbctl deleted file mode 100644 index ce65863c..00000000 --- a/dockerfiles/Dockerfile.download-sbctl +++ /dev/null @@ -1,7 +0,0 @@ -ARG ALPINE_IMG -FROM ${ALPINE_IMG} - -RUN apk add --no-cache curl tar - -RUN curl -Ls https://github.com/Foxboron/sbctl/releases/download/0.13/sbctl-0.13-linux-amd64.tar.gz | tar -xvzf - && \ - mv sbctl/sbctl /usr/bin/sbctl \ No newline at end of file diff --git a/dockerfiles/Dockerfile.uki-byok b/dockerfiles/Dockerfile.uki-byok index 598923d3..47628307 100644 --- a/dockerfiles/Dockerfile.uki-byok +++ b/dockerfiles/Dockerfile.uki-byok @@ -6,7 +6,9 @@ ARG INCLUDE_MS_SECUREBOOT_KEYS=false RUN apt-get update && apt-get install -y efitools curl -COPY --from=download-sbctl /usr/bin/sbctl /usr/bin/sbctl +RUN apk add --no-cache curl tar && \ + curl -Ls https://github.com/Foxboron/sbctl/releases/download/0.13/sbctl-0.13-linux-amd64.tar.gz | tar -xvzf - && \ + mv sbctl/sbctl /usr/bin/sbctl RUN mkdir -p /exported-keys /keys RUN if [ -d "secure-boot/private-keys" ]; then \ diff --git a/ubuntu-fips/20.04/build.sh b/ubuntu-fips/20.04/build.sh index 38e31411..ed577966 100755 --- a/ubuntu-fips/20.04/build.sh +++ b/ubuntu-fips/20.04/build.sh @@ -1,3 +1,3 @@ BASE_IMAGE="${1:-ubuntu-focal-fips}" -DOCKER_BUILDKIT=1 docker build . --secret id=pro-attach-config,src=pro-attach-config.yaml -t "$BASE_IMAGE" \ No newline at end of file +DOCKER_BUILDKIT=1 docker build . --no-cache --secret id=pro-attach-config,src=pro-attach-config.yaml -t "$BASE_IMAGE" \ No newline at end of file From 56b01399386679da275f5512d39da2dff3b9cd57 Mon Sep 17 00:00:00 2001 From: kpiyush17 Date: Mon, 4 Aug 2025 16:51:31 +0530 Subject: [PATCH 05/40] bug fixes --- docker-bake-kairosify.hcl | 4 +- docker-bake.hcl | 34 +++ dockerfiles/Dockerfile.build-uki-iso | 12 +- dockerfiles/Dockerfile.trustedboot-image | 12 +- ubuntu-kairos-base/Dockerfile | 360 ----------------------- 5 files changed, 54 insertions(+), 368 deletions(-) delete mode 100644 ubuntu-kairos-base/Dockerfile diff --git a/docker-bake-kairosify.hcl b/docker-bake-kairosify.hcl index c591c763..8742074b 100644 --- a/docker-bake-kairosify.hcl +++ b/docker-bake-kairosify.hcl @@ -1,5 +1,5 @@ variable "KAIROS_INIT_IMAGE" { - default = "quay.io/kairos/kairos-init:v0.5.1" + default = "quay.io/kairos/kairos-init:v0.5.4" } variable "ARCH" { @@ -15,7 +15,7 @@ variable "MODEL" { } variable "KAIROS_VERSION" { - default = "v3.4.2" + default = "v3.5.0" } variable "TRUSTED_BOOT" { diff --git a/docker-bake.hcl b/docker-bake.hcl index 769129b1..139f1af8 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -412,6 +412,23 @@ target "trustedboot-image" { contexts = { provider-image = "target:provider-image" } + secret = [ + { + type = "file" + id = "enrollment" + src = "secure-boot/enrollment/" + }, + { + type = "file" + id = "private-keys" + src = "secure-boot/private-keys/" + }, + { + type = "file" + id = "public-keys" + src = "secure-boot/public-keys/" + } + ] args = { AURORABOOT_IMAGE = AURORABOOT_IMAGE } @@ -483,6 +500,23 @@ target "build-uki-iso" { CMDLINE = CMDLINE BRANDING = BRANDING } + secret = [ + { + type = "file" + id = "enrollment" + src = "secure-boot/enrollment/" + }, + { + type = "file" + id = "private-keys" + src = "secure-boot/private-keys/" + }, + { + type = "file" + id = "public-keys" + src = "secure-boot/public-keys/" + } + ] output = ["type=local,dest=./iso-output/"] } diff --git a/dockerfiles/Dockerfile.build-uki-iso b/dockerfiles/Dockerfile.build-uki-iso index bfd339b4..d664784e 100644 --- a/dockerfiles/Dockerfile.build-uki-iso +++ b/dockerfiles/Dockerfile.build-uki-iso @@ -50,9 +50,15 @@ WORKDIR /build COPY --from=iso-image / /iso-source/ -COPY secure-boot/enrollment/ /keys/ -COPY secure-boot/private-keys/ /keys/ -COPY secure-boot/public-keys/ /keys/ +RUN --mount=type=secret,id=enrollment,target=/tmp/enrollment \ + mkdir -p /keys && \ + cp -r /tmp/enrollment/* /keys/ + +RUN --mount=type=secret,id=private-keys,target=/tmp/private-keys \ + cp -r /tmp/private-keys/* /keys/ + +RUN --mount=type=secret,id=public-keys,target=/tmp/public-keys \ + cp -r /tmp/public-keys/* /keys/ RUN if [ "$ARCH" = "amd64" ]; then \ mkdir -p /iso && \ diff --git a/dockerfiles/Dockerfile.trustedboot-image b/dockerfiles/Dockerfile.trustedboot-image index c33181c4..fc4f480f 100644 --- a/dockerfiles/Dockerfile.trustedboot-image +++ b/dockerfiles/Dockerfile.trustedboot-image @@ -6,9 +6,15 @@ FROM ${AURORABOOT_IMAGE} AS builder COPY --from=provider-image-rootfs / /build/image/ -COPY secure-boot/enrollment/ /keys/ -COPY secure-boot/private-keys/ /keys/ -COPY secure-boot/public-keys/ /keys/ +RUN --mount=type=secret,id=enrollment,target=/tmp/enrollment \ + mkdir -p /keys && \ + cp -r /tmp/enrollment/* /keys/ + +RUN --mount=type=secret,id=private-keys,target=/tmp/private-keys \ + cp -r /tmp/private-keys/* /keys/ + +RUN --mount=type=secret,id=public-keys,target=/tmp/public-keys \ + cp -r /tmp/public-keys/* /keys/ RUN mkdir -p /output diff --git a/ubuntu-kairos-base/Dockerfile b/ubuntu-kairos-base/Dockerfile deleted file mode 100644 index df8aadf0..00000000 --- a/ubuntu-kairos-base/Dockerfile +++ /dev/null @@ -1,360 +0,0 @@ -# This file is auto-generated with the command: earthly +kairos-dockerfile --FAMILY=ubuntu -############################################################### -#### ARGS #### -############################################################### -ARG FAMILY=ubuntu -# Currently supported flavors are: -# - ubuntu -ARG FLAVOR -# - 20.04 -# - 22.04 -# - 23.04 -ARG FLAVOR_RELEASE -# Currently supported models are: -# - generic -# - rpi4 -# - rpi3 -ARG MODEL=generic -ARG BASE_IMAGE -ARG VARIANT -ARG VERSION -ARG FRAMEWORK_VERSION=v2.11.7 -# Not to be confused with the concept of MODEL, this is either fips or generic -ARG SECURITY_PROFILE=generic -# TARGETARCH is used to determine the architecture of the image -# it is already set by Docker so it doesn't need to be defined here - -############################################################### -#### Upstream Images #### -############################################################### -FROM ${BASE_IMAGE} AS ubuntu-23.04-upstream - -FROM ${BASE_IMAGE} AS ubuntu-20.04-upstream - -FROM ${BASE_IMAGE} AS ubuntu-22.04-upstream - - -############################################################### -#### Pre-Process Common to All #### -############################################################### -FROM ${FLAVOR}-${FLAVOR_RELEASE}-upstream AS common -ENV DEBIAN_FRONTEND=noninteractive - -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - gnupg \ - software-properties-common \ - && add-apt-repository ppa:oibaf/test \ - && apt-get update \ - && apt-get install -y --no-install-recommends \ - conntrack \ - console-data \ - cloud-guest-utils \ - coreutils \ - cryptsetup \ - curl \ - debianutils \ - dosfstools \ - dracut \ - dracut-network \ - e2fsprogs \ - fdisk \ - file \ - gawk \ - gdisk \ - grub2-common \ - haveged \ - iproute2 \ - iptables \ - iputils-ping \ - jq \ - kbd \ - krb5-locales \ - less \ - lldpd \ - lvm2 \ - nano \ - nbd-client \ - neovim \ - nohang \ - open-iscsi \ - open-vm-tools \ - openssh-server \ - parted \ - rsync \ - snmpd \ - squashfs-tools \ - sudo \ - systemd \ - systemd-timesyncd \ - tar \ - ubuntu-advantage-tools \ - xz-utils \ - zstd \ - && apt-get remove -y unattended-upgrades && apt-get clean && rm -rf /var/lib/apt/lists/* - -############################################################### -#### Common to a Single Architecture #### -############################################################### - -FROM common AS amd64 -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - dmsetup \ - efibootmgr \ - grub2 \ - grub-efi-amd64-bin \ - grub-efi-amd64-signed \ - grub-pc-bin \ - isc-dhcp-common \ - mdadm \ - ncurses-term \ - networkd-dispatcher \ - nfs-common \ - os-prober \ - packagekit-tools \ - publicsuffix \ - shared-mime-info \ - thermald \ - xdg-user-dirs \ - xxd \ - zerofree \ - zfsutils-linux \ - && apt-get clean && rm -rf /var/lib/apt/lists/* - -FROM common AS arm64 -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - grub-efi-arm64 \ - grub-efi-arm64-bin \ - grub-efi-arm64-signed \ - keyutils \ - && apt-get clean && rm -rf /var/lib/apt/lists/* - -############################################################### -#### Common to an Arch and Flavor #### -############################################################### -FROM ${TARGETARCH} AS base-ubuntu-20.04 -RUN apt-get update && apt-get install -y --no-install-recommends \ - file \ - fuse \ - patch \ - policykit-1 \ - && apt-get clean && rm -rf /var/lib/apt/lists/* - -FROM ${TARGETARCH} AS base-ubuntu-22.04 -RUN apt-get update && apt-get install -y --no-install-recommends \ - dracut-live \ - firmware-sof-signed \ - fuse3 \ - pigz \ - polkitd \ - && apt-get clean && rm -rf /var/lib/apt/lists/* - -FROM base-ubuntu-20.04 AS amd64-base-ubuntu-20.04 -# If a kernel is already installed, don't try to install it again, this way the base image can -# be non-hwe for older releases -RUN apt-get update -RUN [ -z "$(ls -A /lib/modules/)" ] && apt-get install -y --no-install-recommends \ - linux-image-generic-hwe-20.04 || true -RUN apt-get clean && rm -rf /var/lib/apt/lists/* - -FROM base-ubuntu-22.04 AS amd64-base-ubuntu-22.04 -RUN apt-get update -# If a kernel is already installed, don't try to install it again, this way the base image can -# be non-hwe for older releases -RUN [ -z "$(ls -A /lib/modules)" ] && apt-get install -y --no-install-recommends \ - linux-image-generic-hwe-22.04 || true -RUN apt-get clean && rm -rf /var/lib/apt/lists/* - -FROM amd64-base-ubuntu-22.04 AS amd64-ubuntu-23.04 -FROM amd64-base-ubuntu-22.04 AS amd64-ubuntu-22.04 -FROM amd64-base-ubuntu-20.04 AS amd64-ubuntu-20.04 - -FROM base-ubuntu-22.04 AS arm64-ubuntu-23.04 -FROM base-ubuntu-22.04 AS arm64-ubuntu-22.04 -FROM base-ubuntu-20.04 AS arm64-ubuntu-20.04 - -############################################################### -#### Common to a Single Model #### -############################################################### -FROM ${TARGETARCH}-${FLAVOR}-${FLAVOR_RELEASE} AS generic -RUN apt-get update && apt-get install -y --no-install-recommends \ - linux-base \ - qemu-guest-agent \ - && apt-get clean && rm -rf /var/lib/apt/lists/* - -FROM arm64-${FLAVOR}-${FLAVOR_RELEASE} AS rpicommon -RUN apt-get update && apt-get install -y --no-install-recommends \ - linux-raspi \ - && apt-get clean && rm -rf /var/lib/apt/lists/* -COPY rpi/config.txt /boot/config.txt - -FROM rpicommon AS ubuntu-20.04-rpi -RUN apt-get update && apt-get install -y --no-install-recommends \ - linux-firmware-raspi2 \ - && apt-get clean && rm -rf /var/lib/apt/lists/* - -FROM rpicommon AS ubuntu-23.04-rpi -RUN apt-get update && apt-get install -y --no-install-recommends \ - linux-firmware-raspi \ - linux-modules-extra-raspi \ - && apt-get clean && rm -rf /var/lib/apt/lists/* - -FROM generic AS amd64-ubuntu-23.04-generic -FROM generic AS amd64-ubuntu-22.04-generic -FROM generic AS amd64-ubuntu-20.04-generic -FROM generic AS arm64-ubuntu-23.04-generic -FROM ubuntu-23.04-rpi AS arm64-ubuntu-23.04-rpi3 -FROM ubuntu-23.04-rpi AS arm64-ubuntu-23.04-rpi4 -FROM ubuntu-23.04-rpi AS arm64-ubuntu-22.04-rpi3 -FROM ubuntu-23.04-rpi AS arm64-ubuntu-22.04-rpi4 -FROM ubuntu-20.04-rpi AS arm64-ubuntu-20.04-rpi3 -FROM ubuntu-20.04-rpi AS arm64-ubuntu-20.04-rpi4 -FROM ubuntu-20.04-upstream AS arm64-ubuntu-20.04-nvidia-jetson-agx-orin - -############################################################### -#### Common to a Single Flavor #### -############################################################### -FROM ${TARGETARCH}-${FLAVOR}-${FLAVOR_RELEASE}-${MODEL} AS ubuntu-23.04 -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - dbus-user-session \ - pkg-config \ - systemd-hwe-hwdb \ - systemd-resolved \ - && apt-get clean && rm -rf /var/lib/apt/lists/* - -FROM ${TARGETARCH}-${FLAVOR}-${FLAVOR_RELEASE}-${MODEL} AS ubuntu-22.04 -RUN apt-get update -# If the generic kernel is installed we don't want to install HWE related packages -SHELL ["/bin/bash", "-o", "pipefail", "-c"] -RUN apt-cache search linux-image-generic | grep hwe &> /dev/null && apt-get install -y --no-install-recommends \ - systemd-hwe-hwdb -RUN apt-get clean && rm -rf /var/lib/apt/lists/* - -FROM ${TARGETARCH}-${FLAVOR}-${FLAVOR_RELEASE}-${MODEL} AS ubuntu-20.04 - -############################################################### -#### Post-Process Common to All #### -############################################################### -FROM ${FLAVOR}-${FLAVOR_RELEASE} AS all - -# compress firmware -RUN find /usr/lib/firmware -type f -execdir zstd --rm -9 {} \+ -# compress modules -RUN find /usr/lib/modules -type f -name "*.ko" -execdir zstd --rm -9 {} \+ - -RUN systemctl enable systemd-networkd -RUN systemctl enable ssh - -# Fixup sudo perms -RUN chown root:root /usr/bin/sudo && chmod 4755 /usr/bin/sudo - -RUN journalctl --vacuum-size=1K && rm /etc/machine-id && rm /var/lib/dbus/machine-id && rm /etc/hostname - -FROM --platform="linux/${TARGETARCH}" quay.io/kairos/framework:${FRAMEWORK_VERSION}_${SECURITY_PROFILE} AS framework - -FROM all AS base-kairos - -# Symlinks to make elemental installer work -RUN ORIG=/usr/sbin/grub-install; DEST=/usr/sbin/grub2-install; [ -e $ORIG ] && [ ! -e $DEST ] && ln -s $ORIG $DEST || true -RUN ORIG=/usr/bin/grub-editenv; DEST=/usr/sbin/grub2-editenv; [ -e $ORIG ] && [ ! -e $DEST ] && ln -s $ORIG $DEST || true - -# Originally done in Earthly -COPY --from=framework / / - -RUN rm -rf /etc/ssh/ssh_host_* - -COPY naming.sh /usr/local/bin/naming.sh -COPY which-init.sh /usr/local/bin/which-init.sh - -RUN sed -i -n '/KAIROS_/!p' /etc/os-release - -# need to be defined after FROM for them to be replaced in the RUN bellow -ARG FLAVOR -ARG FLAVOR_RELEASE -ARG VARIANT -ARG OS_ID=kairos -ARG HOME_URL="https://github.com/kairos-io/kairos" -ARG BUG_REPORT_URL="https://github.com/kairos-io/kairos/issues" -ARG GITHUB_REPO="kairos-io/kairos" -# TODO: merge these -ARG VERSION -ARG FAMILY -ARG MODEL -ARG REGISTRY_AND_ORG="quay.io/kairos" -ARG K3S_VERSION -ARG TARGETARCH -ARG OS_NAME=kairos-${VARIANT}-${FLAVOR}-${FLAVOR_RELEASE} -ENV KAIROS_VERSION="${VERSION}${K3S_VERSION:+-k3s$K3S_VERSION}" -ENV OS_VERSION=${KAIROS_VERSION} -ENV OS_LABEL=${KAIROS_VERSION} -RUN OS_LABEL=$(naming.sh container_artifact_label) \ - OS_REPO=$(naming.sh container_artifact_repo) \ - ARTIFACT=$(naming.sh bootable_artifact_name) \ - envsubst >>/etc/os-release /IMAGE - -RUN rm -rf /etc/machine-id - -FROM base-kairos AS kairos-core - -FROM base-kairos AS kairos-standard -ARG K3S_VERSION -LABEL io.kairos.k3s_version="${K3S_VERSION}" -RUN luet install -y system/provider-kairos -RUN luet install -y "k8s/k3s-$(which-init.sh)@${K3S_VERSION}" utils/edgevpn utils/k9s utils/nerdctl container/kubectl utils/kube-vip - -FROM kairos-${VARIANT} AS kairos-final -ARG BASE_IMAGE -ARG VARIANT -ARG FAMILY -ARG FLAVOR -ARG FLAVOR_RELEASE -ARG MODEL -ARG VERSION -ARG FRAMEWORK_VERSION -ARG SECURITY_PROFILE -LABEL org.opencontainers.image.authors="Kairos Maintainers " -LABEL org.opencontainers.image.licenses="Apache-2.0" -LABEL org.opencontainers.image.url="https://github.com/kairos-io/kairos" -LABEL org.opencontainers.image.source="https://github.com/kairos-io/kairos.git" -LABEL io.kairos.base_image="${BASE_IMAGE}" -LABEL io.kairos.variant="${VARIANT}" -LABEL io.kairos.family="${FAMILY}" -LABEL io.kairos.flavor="${FLAVOR}" -LABEL io.kairos.flavor_release="${FLAVOR_RELEASE}" -LABEL io.kairos.model="${MODEL}" -LABEL io.kairos.version="${VERSION}" -LABEL io.kairos.framework-version="${FRAMEWORK_VERSION}" -LABEL io.kairos.security-profile="${SECURITY_PROFILE}" - -SHELL ["/bin/bash", "-o", "pipefail", "-c"] -RUN luet database get-all-installed --output /etc/kairos/versions.yaml - -# TODO what about caches? -RUN kernel=$(ls /lib/modules | head -n1) && depmod -a "${kernel}" -# Regenerate initrd if necessary, proper config files with immucore and custom initrd should already be in there installed by framework -# for systemd distros -RUN if [ -f "/usr/bin/dracut" ]; then \ - kernel=$(ls /lib/modules | head -n1) && \ - dracut -f "/boot/initrd-${kernel}" "${kernel}" && \ - ln -sf "initrd-${kernel}" /boot/initrd; \ - fi -# for alpine (openrc based) -RUN if [ -f "/sbin/mkinitfs" ]; then \ - kernel=$(ls /lib/modules | head -n1) && \ - mkinitfs -o /boot/initrd "${kernel}"; \ - fi - -# symlink kernel to /boot/vmlinuz -RUN kernel=$(ls /boot/vmlinuz-* 2>/dev/null | head -n1) && if [ -e "$kernel" ]; then ln -sf "$kernel" /boot/vmlinuz; fi || true -RUN kernel=$(ls /boot/Image-* 2>/dev/null | head -n1) && if [ -e "$kernel" ]; then ln -sf "$kernel" /boot/vmlinuz; fi || true - -# this is generally present on rhel based systems, but it doesn't hurt to remove in any case -RUN rm -rf /boot/initramfs-* || true - -RUN rm -rf /tmp/* -RUN luet cleanup -RUN rm -rf /var/luet \ No newline at end of file From ba2da8e663eed4dd18000d696915b59cab74da3a Mon Sep 17 00:00:00 2001 From: abhinav Date: Mon, 4 Aug 2025 19:09:06 -0700 Subject: [PATCH 06/40] update kairos-init version --- .github/workflows/base-images.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/base-images.yaml b/.github/workflows/base-images.yaml index 5427caf4..83b2cc86 100644 --- a/.github/workflows/base-images.yaml +++ b/.github/workflows/base-images.yaml @@ -12,7 +12,7 @@ on: description: "Kairos Init Image" required: false type: string - default: "quay.io/kairos/kairos-init:v0.5.1" + default: "quay.io/kairos/kairos-init:v0.5.7" arch: description: "Architecture" required: false @@ -40,7 +40,7 @@ on: description: "Registry prefix for output images" required: false type: string - default: "us-east1-docker.pkg.dev/spectro-images/dev/piyush-1/edge" + default: "us-east1-docker.pkg.dev/spectro-images/dev/pe-6616/edge" jobs: generate-matrix: @@ -70,7 +70,7 @@ jobs: tag = f"{registry_prefix}/kairos-custom:{simple_name}-core-{arch}-{model}-{kairos_version}" if trusted_boot: tag += "-uki" - + matrix.append({ "base_os": base_os_image, "tag": tag @@ -92,7 +92,7 @@ jobs: ("ubuntu:24.04", "kairos-ubuntu:24.04-core"), ("opensuse/leap:15.6", "kairos-opensuse:leap-15.6-core") ] - + for base_os, tag_prefix in combinations: tag = f"{registry_prefix}/{tag_prefix}-{arch}-{model}-{kairos_version}" matrix.append({ From 36d3e58cdc7cfec05eef095028c707268550d221 Mon Sep 17 00:00:00 2001 From: Piyush Kumar Date: Fri, 15 Aug 2025 01:03:37 +0530 Subject: [PATCH 07/40] fixed secret flag --- docker-bake.hcl | 51 +++++++++++++++++-------------------------------- 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/docker-bake.hcl b/docker-bake.hcl index 139f1af8..993a3bba 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -240,6 +240,21 @@ function "get_ubuntu_image" { result = fips_enabled ? "${spectro_pub_repo}/third-party/ubuntu-fips:22.04" : "${spectro_pub_repo}/third-party/ubuntu:22.04" } +secret "enrollment" { + type = "file" + src = "secure-boot/enrollment/" +} + +secret "private-keys" { + type = "file" + src = "secure-boot/private-keys/" +} + +secret "public-keys" { + type = "file" + src = "secure-boot/public-keys/" +} + function "get_base_image" { params = [base_image, os_distribution, os_version, is_uki] result = base_image != "" ? base_image : ( @@ -412,23 +427,7 @@ target "trustedboot-image" { contexts = { provider-image = "target:provider-image" } - secret = [ - { - type = "file" - id = "enrollment" - src = "secure-boot/enrollment/" - }, - { - type = "file" - id = "private-keys" - src = "secure-boot/private-keys/" - }, - { - type = "file" - id = "public-keys" - src = "secure-boot/public-keys/" - } - ] + secret = ["enrollment", "private-keys", "public-keys"] args = { AURORABOOT_IMAGE = AURORABOOT_IMAGE } @@ -500,23 +499,7 @@ target "build-uki-iso" { CMDLINE = CMDLINE BRANDING = BRANDING } - secret = [ - { - type = "file" - id = "enrollment" - src = "secure-boot/enrollment/" - }, - { - type = "file" - id = "private-keys" - src = "secure-boot/private-keys/" - }, - { - type = "file" - id = "public-keys" - src = "secure-boot/public-keys/" - } - ] + secret = ["enrollment", "private-keys", "public-keys"] output = ["type=local,dest=./iso-output/"] } From 2b1c211724e86534f7a340f16306b9f7768be0f7 Mon Sep 17 00:00:00 2001 From: Vivek-Joshi-99 Date: Thu, 28 Aug 2025 01:42:58 +0000 Subject: [PATCH 08/40] Update default values in base images workflow --- .github/workflows/base-images.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/base-images.yaml b/.github/workflows/base-images.yaml index 83b2cc86..27b422cc 100644 --- a/.github/workflows/base-images.yaml +++ b/.github/workflows/base-images.yaml @@ -12,7 +12,7 @@ on: description: "Kairos Init Image" required: false type: string - default: "quay.io/kairos/kairos-init:v0.5.7" + default: "quay.io/kairos/kairos-init:v0.5.17" arch: description: "Architecture" required: false @@ -30,7 +30,7 @@ on: description: "Kairos Version" required: false type: string - default: "v3.4.2" + default: "v3.5.1" trusted_boot: description: "Trusted Boot" required: false From 3ffadcd25365a5da5d48dde19330010cd66cbd77 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Wed, 29 Oct 2025 00:49:51 +0530 Subject: [PATCH 09/40] Kairos init test arun (#456) * add iso-disk-image target * use earthly to build iso disk image for testing * workaround using earthly for testing * fix with workaroung * feat: support comma separated k8s version in provider images * fix: k8s version in produced image tag * iso fix in iso-disk-image target * fix: setting BASE_K8S_VERSION correctly * fix iso-disk-image target * remove debug statements --- Makefile | 59 +++++++++++++--------- docker-bake.hcl | 73 ++++++++++++++++++++++----- dockerfiles/Dockerfile.install-k8s | 34 +++++++------ dockerfiles/Dockerfile.iso-disk-image | 6 +++ 4 files changed, 118 insertions(+), 54 deletions(-) create mode 100644 dockerfiles/Dockerfile.iso-disk-image diff --git a/Makefile b/Makefile index be43990d..3efe3199 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,20 @@ -include .arg export -.PHONY: base-image build-iso build-provider-images +.PHONY: base-image build-iso build-provider-images iso-disk-image + +# Helper variables for Make-based processing +comma := , +empty := +space := $(empty) $(empty) + +# Get target type based on IS_UKI +PROVIDER_TARGET_TYPE = $(if $(filter true,$(IS_UKI)),uki-provider-image,provider-image) + +# Get versions: either from K8S_VERSION or k8s_version.json +ALL_K8S_VERSIONS = $(if $(strip $(K8S_VERSION)),\ + $(subst $(comma),$(space),$(K8S_VERSION)),\ + $(shell jq -r --arg key "$(K8S_DISTRIBUTION)" 'if .[$$key] then .[$$key][] else empty end' k8s_version.json)) PUSH ?= true IS_UKI ?= false @@ -16,7 +29,7 @@ build-all-images: $(MAKE) build-iso base-image: - docker buildx bake base-image + docker buildx bake base-image iso: @if [ "$(IS_UKI)" = "true" ]; then \ @@ -25,26 +38,22 @@ iso: docker buildx bake build-iso; \ fi -build-provider-images: - @if [ -z "$(K8S_DISTRIBUTION)" ]; then \ - echo "K8S_DISTRIBUTION is not set. Please set K8S_DISTRIBUTION to kubeadm, kubeadm-fips, k3s, nodeadm, rke2 or canonical." && exit 1; \ - fi - @if [ "$(IS_UKI)" = "true" ]; then \ - TARGET=uki-provider-image; \ - else \ - TARGET=provider-image; \ - fi; \ - if [ -z "$(K8S_VERSION)" ]; then \ - VERSIONS=$$(jq -r --arg key "$(K8S_DISTRIBUTION)" 'if .[$key] then .[$key][] else empty end' k8s_version.json); \ - if [ -z "$$VERSIONS" ]; then \ - echo "No versions found for K8S_DISTRIBUTION=$(K8S_DISTRIBUTION) in k8s_version.json"; \ - exit 1; \ - fi; \ - for version in $$VERSIONS; do \ - docker buildx bake $$TARGET \ - --set *.args.K8S_VERSION=$$version; \ - done; \ - else \ - docker buildx bake $$TARGET \ - --set *.args.K8S_VERSION=$(K8S_VERSION); \ - fi \ No newline at end of file +iso-disk-image: + docker buildx bake iso-disk-image + +build-provider-images: check-k8s-distribution check-versions $(addprefix build-provider-image-,$(strip $(ALL_K8S_VERSIONS))) + @echo "All provider images built successfully" + +build-provider-image-%: check-k8s-distribution + @echo "building for k8s version - $*" + @env K8S_VERSION=$* docker buildx bake $(PROVIDER_TARGET_TYPE) --set *.args.K8S_VERSION=$* + +check-versions: + @$(if $(strip $(ALL_K8S_VERSIONS)),,$(error No versions found for K8S_DISTRIBUTION=$(K8S_DISTRIBUTION))) + +check-k8s-distribution: + @$(if $(strip $(K8S_DISTRIBUTION)),,$(error K8S_DISTRIBUTION is not set. Please set K8S_DISTRIBUTION to kubeadm, kubeadm-fips, k3s, nodeadm, rke2 or canonical)) + + + + diff --git a/docker-bake.hcl b/docker-bake.hcl index 993a3bba..92b2f7e1 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -240,20 +240,20 @@ function "get_ubuntu_image" { result = fips_enabled ? "${spectro_pub_repo}/third-party/ubuntu-fips:22.04" : "${spectro_pub_repo}/third-party/ubuntu:22.04" } -secret "enrollment" { - type = "file" - src = "secure-boot/enrollment/" -} +# secret "enrollment" { +# type = "file" +# src = "secure-boot/enrollment/" +# } -secret "private-keys" { - type = "file" - src = "secure-boot/private-keys/" -} +# secret "private-keys" { +# type = "file" +# src = "secure-boot/private-keys/" +# } -secret "public-keys" { - type = "file" - src = "secure-boot/public-keys/" -} +# secret "public-keys" { +# type = "file" +# src = "secure-boot/public-keys/" +# } function "get_base_image" { params = [base_image, os_distribution, os_version, is_uki] @@ -427,7 +427,24 @@ target "trustedboot-image" { contexts = { provider-image = "target:provider-image" } - secret = ["enrollment", "private-keys", "public-keys"] + # secret = ["enrollment", "private-keys", "public-keys"] + secret = [ + { + type = "file" + src = "secure-boot/enrollment/" + id = "enrollment" + }, + { + type = "file" + src = "secure-boot/private-keys/" + id = "private-keys" + }, + { + type = "file" + src = "secure-boot/public-keys/" + id = "public-keys" + } + ] args = { AURORABOOT_IMAGE = AURORABOOT_IMAGE } @@ -499,7 +516,24 @@ target "build-uki-iso" { CMDLINE = CMDLINE BRANDING = BRANDING } - secret = ["enrollment", "private-keys", "public-keys"] + # secret = ["enrollment", "private-keys", "public-keys"] + secret = [ + { + type = "file" + src = "secure-boot/enrollment/" + id = "enrollment" + }, + { + type = "file" + src = "secure-boot/private-keys/" + id = "private-keys" + }, + { + type = "file" + src = "secure-boot/public-keys/" + id = "public-keys" + } + ] output = ["type=local,dest=./iso-output/"] } @@ -586,3 +620,14 @@ target "third-party-etcdctl" { TARGETPLATFORM = "linux/${ARCH}" } } + +target "iso-disk-image" { + dockerfile = "dockerfiles/Dockerfile.iso-disk-image" + platforms = ["linux/${ARCH}"] + contexts = { + build-iso = IS_UKI ? "target:build-uki-iso" : "target:build-iso" + # build-iso = "target:build-iso" + } + tags = ["${IMAGE_REGISTRY}/${IMAGE_REPO}/${ISO_NAME}:${IMAGE_TAG}"] + output = ["type=image,push=true"] +} diff --git a/dockerfiles/Dockerfile.install-k8s b/dockerfiles/Dockerfile.install-k8s index 0938403a..2e8e3904 100644 --- a/dockerfiles/Dockerfile.install-k8s +++ b/dockerfiles/Dockerfile.install-k8s @@ -19,16 +19,6 @@ RUN apk add curl COPY --from=third-party-luet /WORKDIR/luet /usr/bin/luet -RUN if [ "$K8S_DISTRIBUTION" = "kubeadm" ] || [ "$K8S_DISTRIBUTION" = "kubeadm-fips" ] || [ "$K8S_DISTRIBUTION" = "nodeadm" ] || [ "$K8S_DISTRIBUTION" = "canonical" ]; then \ - BASE_K8S_VERSION="$K8S_VERSION"; \ - elif [ "$K8S_DISTRIBUTION" = "k3s" ]; then \ - K8S_DISTRIBUTION_TAG="$K3S_FLAVOR_TAG"; \ - BASE_K8S_VERSION="$K8S_VERSION-$K8S_DISTRIBUTION_TAG"; \ - elif [ "$K8S_DISTRIBUTION" = "rke2" ]; then \ - K8S_DISTRIBUTION_TAG="$RKE2_FLAVOR_TAG"; \ - BASE_K8S_VERSION="$K8S_VERSION-$K8S_DISTRIBUTION_TAG"; \ - fi - WORKDIR /output RUN mkdir -p /etc/luet/repos.conf.d && \ @@ -36,20 +26,34 @@ RUN mkdir -p /etc/luet/repos.conf.d && \ COPY . /tmp/build-context/ RUN if [ -f /tmp/build-context/spectro-luet-auth.yaml ]; then \ - cp /tmp/build-context/spectro-luet-auth.yaml spectro-luet-auth.yaml && \ - cat spectro-luet-auth.yaml >> /etc/luet/repos.conf.d/spectro.yaml; \ + cp /tmp/build-context/spectro-luet-auth.yaml spectro-luet-auth.yaml && \ + cat spectro-luet-auth.yaml >> /etc/luet/repos.conf.d/spectro.yaml; \ fi RUN luet repo update RUN if [ "$K8S_DISTRIBUTION" = "kubeadm" ]; then \ - luet install -y container-runtime/containerd --system-target /output; \ + luet install -y container-runtime/containerd --system-target /output; \ fi RUN if [ "$K8S_DISTRIBUTION" = "kubeadm-fips" ]; then \ - luet install -y container-runtime/containerd-fips --system-target /output; \ + luet install -y container-runtime/containerd-fips --system-target /output; \ fi -RUN luet install -y k8s/$K8S_DISTRIBUTION@$BASE_K8S_VERSION --system-target /output && luet cleanup +# Calculate BASE_K8S_VERSION based on K8S_DISTRIBUTION +RUN if [ "$K8S_DISTRIBUTION" = "kubeadm" ] || \ + [ "$K8S_DISTRIBUTION" = "kubeadm-fips" ] || \ + [ "$K8S_DISTRIBUTION" = "nodeadm" ] || \ + [ "$K8S_DISTRIBUTION" = "canonical" ]; then \ + BASE_K8S_VERSION="$K8S_VERSION"; \ + elif [ "$K8S_DISTRIBUTION" = "k3s" ]; then \ + K8S_DISTRIBUTION_TAG="$K3S_FLAVOR_TAG"; \ + BASE_K8S_VERSION="$K8S_VERSION-$K8S_DISTRIBUTION_TAG"; \ + elif [ "$K8S_DISTRIBUTION" = "rke2" ]; then \ + K8S_DISTRIBUTION_TAG="$RKE2_FLAVOR_TAG"; \ + BASE_K8S_VERSION="$K8S_VERSION-$K8S_DISTRIBUTION_TAG"; \ + fi && \ + echo "Installing k8s/$K8S_DISTRIBUTION@$BASE_K8S_VERSION for K8S_VERSION=$K8S_VERSION" && \ + luet install -y k8s/$K8S_DISTRIBUTION@$BASE_K8S_VERSION --system-target /output && luet cleanup RUN rm -rf /output/var/cache/* \ No newline at end of file diff --git a/dockerfiles/Dockerfile.iso-disk-image b/dockerfiles/Dockerfile.iso-disk-image new file mode 100644 index 00000000..9a103dc6 --- /dev/null +++ b/dockerfiles/Dockerfile.iso-disk-image @@ -0,0 +1,6 @@ +FROM scratch + +COPY --from=build-iso /*.iso /disk/ + +# Set metadata labels +LABEL org.opencontainers.image.title="CanvOS ISO Disk Image" From 90864a86d207ab2b88f0933419b53eb09eed3f46 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Wed, 29 Oct 2025 01:27:31 +0530 Subject: [PATCH 10/40] updating kairos-init version to v0.5.20 --- .github/workflows/base-images.yaml | 2 +- docker-bake-kairosify.hcl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/base-images.yaml b/.github/workflows/base-images.yaml index 27b422cc..950c64c8 100644 --- a/.github/workflows/base-images.yaml +++ b/.github/workflows/base-images.yaml @@ -12,7 +12,7 @@ on: description: "Kairos Init Image" required: false type: string - default: "quay.io/kairos/kairos-init:v0.5.17" + default: "quay.io/kairos/kairos-init:v0.5.20" arch: description: "Architecture" required: false diff --git a/docker-bake-kairosify.hcl b/docker-bake-kairosify.hcl index 8742074b..be4eb3b4 100644 --- a/docker-bake-kairosify.hcl +++ b/docker-bake-kairosify.hcl @@ -1,5 +1,5 @@ variable "KAIROS_INIT_IMAGE" { - default = "quay.io/kairos/kairos-init:v0.5.4" + default = "quay.io/kairos/kairos-init:v0.5.20" } variable "ARCH" { From c6bf39d11bd7e12cee64d6189105d37fb1651058 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Wed, 29 Oct 2025 01:53:41 +0530 Subject: [PATCH 11/40] minor fixes --- .github/workflows/base-images.yaml | 2 +- docker-bake-kairosify.hcl | 2 +- docker-bake.hcl | 8 ++++---- dockerfiles/Dockerfile.iso-disk-image | 3 +-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/workflows/base-images.yaml b/.github/workflows/base-images.yaml index 950c64c8..45790240 100644 --- a/.github/workflows/base-images.yaml +++ b/.github/workflows/base-images.yaml @@ -30,7 +30,7 @@ on: description: "Kairos Version" required: false type: string - default: "v3.5.1" + default: "v3.5.3" trusted_boot: description: "Trusted Boot" required: false diff --git a/docker-bake-kairosify.hcl b/docker-bake-kairosify.hcl index be4eb3b4..8b2f4ead 100644 --- a/docker-bake-kairosify.hcl +++ b/docker-bake-kairosify.hcl @@ -15,7 +15,7 @@ variable "MODEL" { } variable "KAIROS_VERSION" { - default = "v3.5.0" + default = "v3.5.3" } variable "TRUSTED_BOOT" { diff --git a/docker-bake.hcl b/docker-bake.hcl index 92b2f7e1..1929b71f 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -259,16 +259,16 @@ function "get_base_image" { params = [base_image, os_distribution, os_version, is_uki] result = base_image != "" ? base_image : ( - os_distribution == "ubuntu" && os_version == "20" ? + os_distribution == "ubuntu" && ( os_version == "20" || os_version == "20.04" ) ? "${SPECTRO_PUB_REPO}/edge/kairos-${OS_DISTRIBUTION}:${OS_VERSION}.04-core-${ARCH}-generic-${KAIROS_VERSION}" : - os_distribution == "ubuntu" && os_version == "22" ? + os_distribution == "ubuntu" && ( os_version == "22" || os_version == "22.04" ) ? "${SPECTRO_PUB_REPO}/edge/kairos-${OS_DISTRIBUTION}:${OS_VERSION}.04-core-${ARCH}-generic-${KAIROS_VERSION}" : - os_distribution == "ubuntu" && os_version == "24" ? + os_distribution == "ubuntu" && ( os_version == "24" || os_version == "24.04" ) ? "${SPECTRO_PUB_REPO}/edge/kairos-${OS_DISTRIBUTION}:${OS_VERSION}.04-core-${ARCH}-generic-${KAIROS_VERSION}" : - os_distribution == "ubuntu" && os_version == "24" && is_uki ? + os_distribution == "ubuntu" && ( os_version == "24" || os_version == "24.04" ) && is_uki ? "${SPECTRO_PUB_REPO}/edge/kairos-${OS_DISTRIBUTION}:${OS_VERSION}.04-core-${ARCH}-generic-${KAIROS_VERSION}-uki" : os_distribution == "opensuse" && os_version == "15.6" ? diff --git a/dockerfiles/Dockerfile.iso-disk-image b/dockerfiles/Dockerfile.iso-disk-image index 9a103dc6..5d0227ce 100644 --- a/dockerfiles/Dockerfile.iso-disk-image +++ b/dockerfiles/Dockerfile.iso-disk-image @@ -2,5 +2,4 @@ FROM scratch COPY --from=build-iso /*.iso /disk/ -# Set metadata labels -LABEL org.opencontainers.image.title="CanvOS ISO Disk Image" +LABEL org.opencontainers.image.title="CanvOS Installer Disk Image" From ff14e8dacee482d0ec7a42f525715ce92559b1d6 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Wed, 29 Oct 2025 19:38:39 +0530 Subject: [PATCH 12/40] updating defaults --- docker-bake.hcl | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/docker-bake.hcl b/docker-bake.hcl index 1929b71f..b20f4daa 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -32,7 +32,7 @@ variable "LUET_PROJECT" { } variable "PE_VERSION" { - default = "v4.6.21" + default = "v4.7.16" } variable "SPECTRO_LUET_VERSION" { @@ -40,7 +40,7 @@ variable "SPECTRO_LUET_VERSION" { } variable "KAIROS_VERSION" { - default = "v3.4.2" + default = "v3.5.3" } variable AURORABOOT_IMAGE { @@ -48,15 +48,15 @@ variable AURORABOOT_IMAGE { } variable "K3S_PROVIDER_VERSION" { - default = "v4.6.0" + default = "v4.7.1" } variable "KUBEADM_PROVIDER_VERSION" { - default = "v4.6.3" + default = "v4.7.3" } variable "RKE2_PROVIDER_VERSION" { - default = "v4.6.0" + default = "v4.7.1" } variable "NODEADM_PROVIDER_VERSION" { @@ -64,7 +64,7 @@ variable "NODEADM_PROVIDER_VERSION" { } variable "CANONICAL_PROVIDER_VERSION" { - default = "v1.1.0-rc.1" + default = "v1.2.2" } variable "K3S_FLAVOR_TAG" { @@ -180,14 +180,6 @@ variable "EXPIRATION_IN_DAYS" { default = 5475 } -variable "CMDLINE" { - default = "stylus.registration" -} - -variable "BRANDING" { - default = "Palette eXtended Kubernetes Edge" -} - variable "EFI_MAX_SIZE" { default = "2048" } From db8df3b67209dee49866ce8dd746087919d0e221 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Thu, 6 Nov 2025 16:53:49 +0000 Subject: [PATCH 13/40] fix ubuntu OS version without suffix --- docker-bake.hcl | 50 ++++++++++++++++++++++--------------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/docker-bake.hcl b/docker-bake.hcl index b20f4daa..e84d0730 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -8,7 +8,12 @@ variable "ARCH" { } variable "SPECTRO_PUB_REPO" { - default = FIPS_ENABLED ? "us-east1-docker.pkg.dev/spectro-images-fips/dev/piyush" : "us-east1-docker.pkg.dev/spectro-images/dev/piyush" + # default = FIPS_ENABLED ? "us-east1-docker.pkg.dev/spectro-images-fips/dev/piyush" : "us-east1-docker.pkg.dev/spectro-images/dev/piyush" + default = FIPS_ENABLED ? "us-east1-docker.pkg.dev/spectro-images/dev-fips/arun" : "us-east1-docker.pkg.dev/spectro-images/dev/arun" +} + +variable "KAIROS_BASE_IMAGE_URL" { + default = "${SPECTRO_PUB_REPO}/edge" } variable "SPECTRO_THIRD_PARTY_IMAGE" { @@ -232,39 +237,30 @@ function "get_ubuntu_image" { result = fips_enabled ? "${spectro_pub_repo}/third-party/ubuntu-fips:22.04" : "${spectro_pub_repo}/third-party/ubuntu:22.04" } -# secret "enrollment" { -# type = "file" -# src = "secure-boot/enrollment/" -# } +secret "enrollment" { + type = "file" + src = "secure-boot/enrollment/" +} -# secret "private-keys" { -# type = "file" -# src = "secure-boot/private-keys/" -# } +secret "private-keys" { + type = "file" + src = "secure-boot/private-keys/" +} -# secret "public-keys" { -# type = "file" -# src = "secure-boot/public-keys/" -# } +secret "public-keys" { + type = "file" + src = "secure-boot/public-keys/" +} function "get_base_image" { params = [base_image, os_distribution, os_version, is_uki] result = base_image != "" ? base_image : ( - - os_distribution == "ubuntu" && ( os_version == "20" || os_version == "20.04" ) ? - "${SPECTRO_PUB_REPO}/edge/kairos-${OS_DISTRIBUTION}:${OS_VERSION}.04-core-${ARCH}-generic-${KAIROS_VERSION}" : - - os_distribution == "ubuntu" && ( os_version == "22" || os_version == "22.04" ) ? - "${SPECTRO_PUB_REPO}/edge/kairos-${OS_DISTRIBUTION}:${OS_VERSION}.04-core-${ARCH}-generic-${KAIROS_VERSION}" : - - os_distribution == "ubuntu" && ( os_version == "24" || os_version == "24.04" ) ? - "${SPECTRO_PUB_REPO}/edge/kairos-${OS_DISTRIBUTION}:${OS_VERSION}.04-core-${ARCH}-generic-${KAIROS_VERSION}" : - - os_distribution == "ubuntu" && ( os_version == "24" || os_version == "24.04" ) && is_uki ? - "${SPECTRO_PUB_REPO}/edge/kairos-${OS_DISTRIBUTION}:${OS_VERSION}.04-core-${ARCH}-generic-${KAIROS_VERSION}-uki" : + # Format version: add .04 if not present, then build image URL + os_distribution == "ubuntu" && length(regexall("^(20|22|24)(\\.04)?$", os_version)) > 0 ? + "${KAIROS_BASE_IMAGE_URL}/kairos-${OS_DISTRIBUTION}:${length(regexall("\\.04", os_version)) > 0 ? os_version : os_version + ".04"}-core-${ARCH}-generic-${KAIROS_VERSION}${is_uki && length(regexall("^24", os_version)) > 0 ? "-uki" : ""}" : os_distribution == "opensuse" && os_version == "15.6" ? - "${SPECTRO_PUB_REPO}/edge/kairos-opensuse:leap-${OS_VERSION}-core-${ARCH}-generic-${KAIROS_VERSION}" : + "${KAIROS_BASE_IMAGE_URL}/kairos-opensuse:leap-${OS_VERSION}-core-${ARCH}-generic-${KAIROS_VERSION}" : "" ) @@ -419,7 +415,6 @@ target "trustedboot-image" { contexts = { provider-image = "target:provider-image" } - # secret = ["enrollment", "private-keys", "public-keys"] secret = [ { type = "file" @@ -508,7 +503,6 @@ target "build-uki-iso" { CMDLINE = CMDLINE BRANDING = BRANDING } - # secret = ["enrollment", "private-keys", "public-keys"] secret = [ { type = "file" From fe963bc3c2b03f357484e4e686e53824f298e834 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Thu, 6 Nov 2025 20:04:54 +0000 Subject: [PATCH 14/40] update luet release version --- docker-bake.hcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-bake.hcl b/docker-bake.hcl index e84d0730..205c7d0b 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -41,7 +41,7 @@ variable "PE_VERSION" { } variable "SPECTRO_LUET_VERSION" { - default = "v4.7.0-rc.1" + default = "v4.7.1" } variable "KAIROS_VERSION" { From 0de2677c2d04115a307341d6ed812d9ecdb1e8ff Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Fri, 7 Nov 2025 11:40:48 +0000 Subject: [PATCH 15/40] syncing docker bake with earthfile --- docker-bake.hcl | 7 +------ dockerfiles/Dockerfile.install-k8s | 22 ++++++---------------- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/docker-bake.hcl b/docker-bake.hcl index 205c7d0b..a9c61baf 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -40,10 +40,6 @@ variable "PE_VERSION" { default = "v4.7.16" } -variable "SPECTRO_LUET_VERSION" { - default = "v4.7.1" -} - variable "KAIROS_VERSION" { default = "v3.5.3" } @@ -352,9 +348,8 @@ target "install-k8s" { K3S_FLAVOR_TAG = K3S_FLAVOR_TAG RKE2_FLAVOR_TAG = RKE2_FLAVOR_TAG LUET_PROJECT = LUET_PROJECT - LUET_REPO = ARCH == "arm64" ? "${LUET_PROJECT}-arm" : LUET_PROJECT + LUET_REPO = ARCH == "arm64" ? "${LUET_PROJECT}-arm" : "${LUET_PROJECT}-amd" SPECTRO_LUET_REPO = SPECTRO_LUET_REPO - SPECTRO_LUET_VERSION = SPECTRO_LUET_VERSION } } diff --git a/dockerfiles/Dockerfile.install-k8s b/dockerfiles/Dockerfile.install-k8s index 2e8e3904..7cf14307 100644 --- a/dockerfiles/Dockerfile.install-k8s +++ b/dockerfiles/Dockerfile.install-k8s @@ -9,7 +9,6 @@ ARG K3S_FLAVOR_TAG ARG RKE2_FLAVOR_TAG ARG LUET_PROJECT ARG SPECTRO_LUET_REPO -ARG SPECTRO_LUET_VERSION ARG ARCH ARG LUET_REPO @@ -22,8 +21,7 @@ COPY --from=third-party-luet /WORKDIR/luet /usr/bin/luet WORKDIR /output RUN mkdir -p /etc/luet/repos.conf.d && \ - luet repo add spectro --type docker --url $SPECTRO_LUET_REPO/$LUET_REPO/$SPECTRO_LUET_VERSION --priority 1 -y - + luet repo add spectro --type docker --url $SPECTRO_LUET_REPO/$LUET_REPO --priority 1 -y COPY . /tmp/build-context/ RUN if [ -f /tmp/build-context/spectro-luet-auth.yaml ]; then \ cp /tmp/build-context/spectro-luet-auth.yaml spectro-luet-auth.yaml && \ @@ -32,26 +30,18 @@ RUN if [ -f /tmp/build-context/spectro-luet-auth.yaml ]; then \ RUN luet repo update -RUN if [ "$K8S_DISTRIBUTION" = "kubeadm" ]; then \ - luet install -y container-runtime/containerd --system-target /output; \ - fi - -RUN if [ "$K8S_DISTRIBUTION" = "kubeadm-fips" ]; then \ - luet install -y container-runtime/containerd-fips --system-target /output; \ - fi - # Calculate BASE_K8S_VERSION based on K8S_DISTRIBUTION RUN if [ "$K8S_DISTRIBUTION" = "kubeadm" ] || \ [ "$K8S_DISTRIBUTION" = "kubeadm-fips" ] || \ [ "$K8S_DISTRIBUTION" = "nodeadm" ] || \ [ "$K8S_DISTRIBUTION" = "canonical" ]; then \ - BASE_K8S_VERSION="$K8S_VERSION"; \ + BASE_K8S_VERSION="$K8S_VERSION"; \ elif [ "$K8S_DISTRIBUTION" = "k3s" ]; then \ - K8S_DISTRIBUTION_TAG="$K3S_FLAVOR_TAG"; \ - BASE_K8S_VERSION="$K8S_VERSION-$K8S_DISTRIBUTION_TAG"; \ + K8S_DISTRIBUTION_TAG="$K3S_FLAVOR_TAG"; \ + BASE_K8S_VERSION="$K8S_VERSION-$K8S_DISTRIBUTION_TAG"; \ elif [ "$K8S_DISTRIBUTION" = "rke2" ]; then \ - K8S_DISTRIBUTION_TAG="$RKE2_FLAVOR_TAG"; \ - BASE_K8S_VERSION="$K8S_VERSION-$K8S_DISTRIBUTION_TAG"; \ + K8S_DISTRIBUTION_TAG="$RKE2_FLAVOR_TAG"; \ + BASE_K8S_VERSION="$K8S_VERSION-$K8S_DISTRIBUTION_TAG"; \ fi && \ echo "Installing k8s/$K8S_DISTRIBUTION@$BASE_K8S_VERSION for K8S_VERSION=$K8S_VERSION" && \ luet install -y k8s/$K8S_DISTRIBUTION@$BASE_K8S_VERSION --system-target /output && luet cleanup From 129b14cc05339cb0bba225c3fa7c957494de8b49 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Thu, 30 Oct 2025 13:34:53 +0530 Subject: [PATCH 16/40] PE-7685: install rsyslog and logrotate in slem (#484) --- slem/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slem/Dockerfile b/slem/Dockerfile index fda42039..c35cb2ed 100644 --- a/slem/Dockerfile +++ b/slem/Dockerfile @@ -21,7 +21,7 @@ RUN zypper -n in \ growpart gptfdisk haveged htop iproute2 iputils issue-generator lsscsi mdadm multipath-tools \ nfs-client open-iscsi openssh open-vm-tools pigz policycoreutils polkit procps \ qemu-guest-agent strace systemd systemd-network timezone tmux vim which tpm* nethogs patch shim iw \ - grub2-i386-pc grub2-x86_64-efi kernel-firmware-all dracut squashfs dhcp-client + grub2-i386-pc grub2-x86_64-efi kernel-firmware-all dracut squashfs dhcp-client rsyslog logrotate RUN systemctl disable NetworkManager.service NetworkManager-wait-online.service From 526649269f68978955a324c464db39c93baf3890 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Thu, 13 Nov 2025 20:41:39 +0000 Subject: [PATCH 17/40] fix getting opensuse base image --- docker-bake.hcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-bake.hcl b/docker-bake.hcl index a9c61baf..21b3dfa1 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -255,7 +255,7 @@ function "get_base_image" { os_distribution == "ubuntu" && length(regexall("^(20|22|24)(\\.04)?$", os_version)) > 0 ? "${KAIROS_BASE_IMAGE_URL}/kairos-${OS_DISTRIBUTION}:${length(regexall("\\.04", os_version)) > 0 ? os_version : os_version + ".04"}-core-${ARCH}-generic-${KAIROS_VERSION}${is_uki && length(regexall("^24", os_version)) > 0 ? "-uki" : ""}" : - os_distribution == "opensuse" && os_version == "15.6" ? + os_distribution == "opensuse-leap" && os_version == "15.6" ? "${KAIROS_BASE_IMAGE_URL}/kairos-opensuse:leap-${OS_VERSION}-core-${ARCH}-generic-${KAIROS_VERSION}" : "" From 8d340bbf9436dd757456af0b5ba6d3c113c5428c Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Mon, 17 Nov 2025 12:04:31 +0530 Subject: [PATCH 18/40] Cloud image (#492) * add support for cloud images * fix cloud image build * add * update readme * add user-data example * readme --------- Co-authored-by: Akhilesh Verma Co-authored-by: Nianyu Shen Co-authored-by: Akhilesh Verma --- .gitignore | 6 +- Earthfile | 74 +++- README.md | 23 ++ cloud-images/config/user-data.yaml | 21 ++ cloud-images/scripts/create-raw-to-ami.sh | 350 ++++++++++++++++++ .../workaround/custom-post-reset.yaml | 54 +++ cloud-images/workaround/grubmenu.cfg | 26 ++ custom-postreset.yaml | 54 +++ grubmenu.cfg | 26 ++ scripts/build-raw-image-auroraboot.sh | 15 + 10 files changed, 647 insertions(+), 2 deletions(-) create mode 100644 cloud-images/config/user-data.yaml create mode 100755 cloud-images/scripts/create-raw-to-ami.sh create mode 100644 cloud-images/workaround/custom-post-reset.yaml create mode 100644 cloud-images/workaround/grubmenu.cfg create mode 100644 custom-postreset.yaml create mode 100644 grubmenu.cfg create mode 100644 scripts/build-raw-image-auroraboot.sh diff --git a/.gitignore b/.gitignore index c67f2b50..0760e7a8 100644 --- a/.gitignore +++ b/.gitignore @@ -7,9 +7,12 @@ variables.env.old config.yaml content-*/* *.arg +*.arg.* .idea +.secret .DS_Store - +*/user-data.yaml +upload.sh hack/*.img test/.env two-node-create.json @@ -25,3 +28,4 @@ sb-private-ca/*.req spectro-luet-auth.yaml spc.tgz efi-size-check/target/ +cloud-images/config/user-data.yaml diff --git a/Earthfile b/Earthfile index 1ac8eaad..723c2eee 100644 --- a/Earthfile +++ b/Earthfile @@ -181,6 +181,8 @@ BASE_ALPINE: COPY --if-exists certs/ /etc/ssl/certs/ RUN update-ca-certificates + SAVE IMAGE --push gcr.io/spectro-dev-public/canvos/alpine:$ALPINE_TAG + iso-image-rootfs: FROM --platform=linux/${ARCH} +iso-image SAVE ARTIFACT --keep-own /. rootfs @@ -814,6 +816,10 @@ KAIROS_RELEASE: # Used to build the installer image. The installer ISO will be created from this. iso-image: FROM --platform=linux/${ARCH} +base-image + ARG IS_CLOUD_IMAGE=false + ARG IMAGE_REGISTRY + ARG IMAGE_TAG + IF [ "$IS_UKI" = "false" ] COPY --platform=linux/${ARCH} +stylus-image/ / ELSE @@ -822,6 +828,10 @@ iso-image: RUN rm -f /usr/bin/luet END COPY overlay/files/ / + IF [ "$IS_CLOUD_IMAGE" = "true" ] + COPY cloud-images/workaround/grubmenu.cfg /etc/kairos/branding/grubmenu.cfg + COPY cloud-images/workaround/custom-post-reset.yaml /system/oem/custom-post-reset.yaml + END IF [ -f /etc/logrotate.d/stylus.conf ] RUN chmod 644 /etc/logrotate.d/stylus.conf @@ -831,7 +841,69 @@ iso-image: RUN touch /etc/machine-id \ && chmod 444 /etc/machine-id - SAVE IMAGE palette-installer-image:$IMAGE_TAG + SAVE IMAGE --push $IMAGE_REGISTRY/palette-installer-image:$IMAGE_TAG + +cloud-image: + ARG IS_CLOUD_IMAGE=true + + FROM --allow-privileged earthly/dind:alpine-3.19-docker-25.0.5-r0 + # Copy the config file first + COPY cloud-images/config/user-data.yaml /config.yaml + WORKDIR /output + + WITH DOCKER \ + --pull quay.io/kairos/auroraboot:v0.6.4 \ + --load index.docker.io/library/palette-installer-image:latest=(+iso-image --IS_CLOUD_IMAGE=true) + RUN mkdir -p /output && \ + docker run --rm \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v /config.yaml:/config.yaml:ro \ + -v /output:/aurora \ + --net host \ + --privileged \ + quay.io/kairos/auroraboot:v0.6.4 \ + --debug \ + --set "disable_http_server=true" \ + --set "container_image=docker://index.docker.io/library/palette-installer-image:latest" \ + --set "disable_netboot=true" \ + --set "disk.raw=true" \ + --set "state_dir=/aurora" \ + --cloud-config /config.yaml + END + SAVE ARTIFACT /output/* AS LOCAL ./build/ + +aws-cloud-image: + FROM +ubuntu + + RUN apt-get update && apt-get install -y unzip ca-certificates curl + RUN curl --fail -s "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \ + unzip -q awscliv2.zip -d aws_install_temp && \ + ./aws_install_temp/aws/install && \ + rm -rf awscliv2.zip aws_install_temp + + ARG REGION + ARG S3_BUCKET + ARG S3_KEY + # Get the base image name from the BASE_IMAGE variable + + WORKDIR /workdir + COPY cloud-images/scripts/create-raw-to-ami.sh create-raw-to-ami.sh + COPY +cloud-image/ /workdir/ + + RUN --secret AWS_PROFILE \ + --secret AWS_ACCESS_KEY_ID \ + --secret AWS_SECRET_ACCESS_KEY \ + RAW_FILE_PATH=$(ls /workdir/*.raw) && \ + echo "RAW_FILE_PATH: $RAW_FILE_PATH" && \ + if [ ! -f "$RAW_FILE_PATH" ]; then \ + echo "Error: RAW file '/workdir/$RAW_FILE_PATH' not found." && \ + ls -la /workdir/ && \ + exit 1; \ + else \ + echo "RAW file '$RAW_FILE_PATH' found." && \ + echo "Proceeding with creation of AMI..."; \ + fi && \ + /workdir/create-raw-to-ami.sh $RAW_FILE_PATH iso-disk-image: FROM scratch diff --git a/README.md b/README.md index d9c07728..6928e815 100644 --- a/README.md +++ b/README.md @@ -172,6 +172,29 @@ To build just the installer image ./earthly.sh +iso --ARCH=amd64 ``` +To build public cloud images(currently only aws is supported) +aws cloud credentials should be passed in the `.secret` file on the repo dir +example: +```shell +/workspace/spectrocloud/CanvOS$ cat .secret +AWS_PROFILE="" +AWS_ACCESS_KEY_ID="xxxxxx" +AWS_SECRET_ACCESS_KEY="xxxxxxx" +``` +Also region and bucket details need to be passed in .arg file +```shell +#aws cloud +REGION="us-east-1" +S3_BUCKET="test-bkp" +S3_KEY="" +``` +user-data should be kept under `cloud-images/config/user-data.yaml` + +To build AWS cloud image: +```shell +./earthly.sh -P +aws-cloud-image --ARCH=amd64 +``` + To build the provider images ```shell diff --git a/cloud-images/config/user-data.yaml b/cloud-images/config/user-data.yaml new file mode 100644 index 00000000..136b6fcb --- /dev/null +++ b/cloud-images/config/user-data.yaml @@ -0,0 +1,21 @@ +#cloud-config +install: + device: /dev/sda + reboot: true + poweroff: false +stylus: + debug: true + site: + paletteEndpoint: xxxx.spectrocloud.com + autoRegister: true + edgeHostToken: xxxxxxxxxxx + insecureSkipVerify: false + +stages: + initramfs: + - name: "Set user and password" + users: + kairos: + passwd: "kairos" + groups: + - "admin" \ No newline at end of file diff --git a/cloud-images/scripts/create-raw-to-ami.sh b/cloud-images/scripts/create-raw-to-ami.sh new file mode 100755 index 00000000..d847c717 --- /dev/null +++ b/cloud-images/scripts/create-raw-to-ami.sh @@ -0,0 +1,350 @@ +#!/bin/bash + +# Exit immediately if a command exits with a non-zero status. +set -ex +# Treat unset variables as an error when substituting. +set -u +# Pipefail: the return value of a pipeline is the status of the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -o pipefail + +# --- Configuration and Setup --- + +ARG_FILE=".arg" + +# source if .arg exists +if [[ -f "$ARG_FILE" ]]; then + source ".arg" +fi + +# Function for logging messages +log() { + echo "$(date '+%Y-%m-%d %H:%M:%S') - $*" +} + +log "Starting RAW to AMI creation process." + +# --- Dependency Checks --- + +log "Checking dependencies..." +# Check for essential commands +for cmd in curl jq aws; do + if ! command -v "$cmd" &>/dev/null; then + log "Error: Required command '$cmd' not found." >&2 + log "Please install '$cmd' and try again." >&2 + exit 1 + # fi + fi +done +log "All dependencies found." + +# --- Variable Validation --- +RAW_FILE=$1 +log "Validating configuration..." +required_vars=(REGION S3_BUCKET S3_KEY RAW_FILE) +missing_vars=() +for var in "${required_vars[@]}"; do + # if S3_KEY is not set, set it to the RAW_FILE name + if [[ "$var" == "S3_KEY" && -z "${!var-}" ]]; then + S3_KEY=$(basename "$RAW_FILE") + fi + if [[ -z "${!var-}" ]]; then # Check if var is unset or empty + missing_vars+=("$var") + fi +done + +# Validate AWS Credentials - Prefer AWS_PROFILE +if [[ -z "${AWS_PROFILE-}" ]]; then + log "AWS_PROFILE not set. Checking for AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY..." + unset AWS_PROFILE + if [[ -z "${AWS_ACCESS_KEY_ID-}" || -z "${AWS_SECRET_ACCESS_KEY-}" ]]; then + missing_vars+=("AWS_PROFILE or (AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY)") + else + log "Warning: Using AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY from '$ARG_FILE'. Using AWS_PROFILE is recommended for production." + export AWS_ACCESS_KEY_ID="$AWS_ACCESS_KEY_ID" + export AWS_SECRET_ACCESS_KEY="$AWS_SECRET_ACCESS_KEY" + # Consider unsetting AWS_SESSION_TOKEN if sourced, unless explicitly needed and managed. + # The script had a hardcoded token commented out, ensure no active tokens are sourced insecurely. + if [[ -n "${AWS_SESSION_TOKEN-}" ]]; then + export AWS_SESSION_TOKEN="$AWS_SESSION_TOKEN" + log "Using AWS_SESSION_TOKEN." + fi + fi +elif [[ -n "${AWS_ACCESS_KEY_ID-}" || -n "${AWS_SECRET_ACCESS_KEY-}" ]]; then + log "Warning: AWS_PROFILE is set, but AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY are also present in '$ARG_FILE'. AWS_PROFILE will be used." + # Unset keys if profile is preferred to avoid confusion + unset AWS_ACCESS_KEY_ID + unset AWS_SECRET_ACCESS_KEY + unset AWS_SESSION_TOKEN +fi + +if [[ ${#missing_vars[@]} -ne 0 ]]; then + log "Error: Missing required configuration variables in '$ARG_FILE': ${missing_vars[*]}" >&2 + exit 1 +fi + +# Validate RAW_FILE existence +if [[ ! -f "$RAW_FILE" ]]; then + log "Error: RAW file '$RAW_FILE' not found." >&2 + exit 1 +fi + +log "Configuration validated successfully." + +# --- AWS Helper Functions --- + +# Execute AWS CLI command with region and profile if set +# Usage: AWS [options...] +AWS() { + local args=("$@") + local cmd=("aws" "--region" "$REGION") + if [[ -n "${AWS_PROFILE-}" ]]; then + cmd+=("--profile" "$AWS_PROFILE") + fi + "${cmd[@]}" "${args[@]}" +} + +# Execute AWS CLI command without region, but with profile if set +# Usage: AWSNR [options...] +AWSNR() { + local args=("$@") + local cmd=("aws") + if [[ -n "${AWS_PROFILE-}" ]]; then + cmd+=("--profile" "$AWS_PROFILE") + fi + "${cmd[@]}" "${args[@]}" +} + +# Wait for an EC2 snapshot import task to complete. +# Usage: waitForSnapshotCompletion +# Returns: Snapshot ID on success, exits on failure. +waitForSnapshotCompletion() { + local taskID="$1" + local status + local snapshot_id + + log "Waiting for snapshot import task '$taskID' to complete..." + while true; do + # Query status and handle potential errors if task doesn't exist immediately + status=$(AWS ec2 describe-import-snapshot-tasks --import-task-ids "$taskID" --query 'ImportSnapshotTasks[0].SnapshotTaskDetail.Status' --output text 2>/dev/null || echo "error") + + if [[ "$status" == "completed" ]]; then + snapshot_id=$(AWS ec2 describe-import-snapshot-tasks --import-task-ids "$taskID" --query 'ImportSnapshotTasks[0].SnapshotTaskDetail.SnapshotId' --output text) + log "Snapshot import task '$taskID' completed. Snapshot ID: $snapshot_id" + echo "$snapshot_id" # Return snapshot ID + break + elif [[ "$status" == "deleted" || "$status" == "cancelling" || "$status" == "cancelled" ]]; then + log "Error: Snapshot import task '$taskID' failed with status: $status" >&2 + # Optionally, get more detailed error message if available + local status_message + status_message=$(AWS ec2 describe-import-snapshot-tasks --import-task-ids "$taskID" --query 'ImportSnapshotTasks[0].SnapshotTaskDetail.StatusMessage' --output text 2>/dev/null) + if [[ -n "$status_message" ]]; then + log "Status Message: $status_message" >&2 + fi + exit 1 + elif [[ "$status" == "error" ]]; then + log "Error querying status for task '$taskID'. Retrying..." >&2 + sleep 15 # Wait longer if query failed + else + log "Snapshot import task '$taskID' status: $status. Waiting..." + sleep 30 + fi + done +} + +# Wait for an EC2 AMI to become available. +# Usage: waitAMI +waitAMI() { + local amiID="$1" + local ami_region="$2" # Use a different name to avoid conflict with global REGION + local status + + log "[$ami_region] Waiting for AMI '$amiID' to become available..." + while true; do + status=$(AWSNR ec2 describe-images --region "$ami_region" --image-ids "$amiID" --query "Images[0].State" --output text 2>/dev/null || echo "error") + + if [[ "$status" == "available" ]]; then + log "[$ami_region] AMI '$amiID' is now available." + break + elif [[ "$status" == "pending" ]]; then + log "[$ami_region] AMI '$amiID' is pending. Waiting..." + sleep 15 # Increased wait time + elif [[ "$status" == "error" ]]; then + log "[$ami_region] Error querying status for AMI '$amiID'. Retrying..." >&2 + sleep 15 + elif [[ "$status" == "failed" ]]; then + log "[$ami_region] Error: AMI '$amiID' entered failed state." >&2 + # Optionally retrieve reason for failure + local state_reason + state_reason=$(AWSNR ec2 describe-images --region "$ami_region" --image-ids "$amiID" --query "Images[0].StateReason.Message" --output text 2>/dev/null) + if [[ -n "$state_reason" ]]; then + log "[$ami_region] Failure Reason: $state_reason" >&2 + fi + exit 1 + else + # Handle other potential states explicitly if needed (e.g., deregistered) + log "[$ami_region] Warning: AMI '$amiID' is in an unexpected state: $status." >&2 + sleep 30 + fi + done +} + +# Check if an AMI with the given name exists, otherwise create it from the snapshot. +# Usage: checkImageExistsOrCreate +checkImageExistsOrCreate() { + local imageName="$1" + local snapshotID="$2" + local imageID + local description="AMI for ${imageName} created from snapshot ${snapshotID}" # More descriptive + + log "Checking if image '$imageName' exists..." + # Use filters robustly, checking owner might be necessary depending on account setup + imageID=$(AWS ec2 describe-images --filters "Name=name,Values=$imageName" "Name=state,Values=available,pending" --query 'Images[?State!=`deregistered`]|[0].ImageId' --output text) + + if [[ "$imageID" != "None" && -n "$imageID" ]]; then + log "Image '$imageName' already exists with ID: $imageID. Checking state..." + waitAMI "$imageID" "$REGION" # Ensure existing AMI is actually available + else + log "Image '$imageName' does not exist or is not available. Creating from snapshot '$snapshotID'..." + + # Construct BlockDeviceMappings using jq for better readability and safety + local block_device_mappings + block_device_mappings=$(jq -n --arg snapshot_id "$snapshotID" '[{DeviceName: "/dev/xvda", Ebs: {SnapshotId: $snapshot_id}}]') + + # Register the image + imageID=$(AWS ec2 register-image \ + --name "$imageName" \ + --description "$description" \ + --architecture x86_64 \ + --root-device-name /dev/xvda \ + --block-device-mappings "[{\"DeviceName\":\"/dev/xvda\",\"Ebs\":{\"SnapshotId\":\"$snapshotID\"}}]" \ + --virtualization-type hvm \ + --boot-mode uefi \ + --ena-support \ + --query 'ImageId' \ + --output text) + + if [[ -z "$imageID" ]]; then + log "Error: Failed to register image '$imageName'." >&2 + exit 1 + fi + log "Image '$imageName' registration initiated with Image ID: $imageID." + + # Add tags immediately after registration starts (optional, can be done after available) + # log "Tagging image $imageID..." + # AWS ec2 create-tags --resources "$imageID" --tags Key=Name,Value="$imageName" Key=Project,Value=Kairos # Add relevant tags + # Check tag creation success? + + # Wait for the newly created AMI to be available + waitAMI "$imageID" "$REGION" + fi + # Return the final, available image ID + echo "$imageID" +} + +# Import a RAW file from S3 as an EC2 snapshot. +# Checks if a snapshot with a specific tag already exists. +# Usage: importAsSnapshot +# Returns: Snapshot ID on success, exits on failure. +importAsSnapshot() { + local s3Key="$1" + local snapshotID + local taskID + local snapshot_tag_key="SourceS3Key" # Using a specific tag for idempotency check + + # log "Checking for existing snapshot tagged with '$snapshot_tag_key=$s3Key'..." + # snapshotID=$(AWS ec2 describe-snapshots --filters "Name=tag:$snapshot_tag_key,Values=$s3Key" --query "Snapshots[0].SnapshotId" --output text) + # if [[ "$snapshotID" != "None" && -n "$snapshotID" ]]; then + # log "Snapshot '$snapshotID' already exists for S3 key '$s3Key'." + # echo "$snapshotID" + # return 0 # Indicate success, snapshot already exists + # fi + + # log "No existing snapshot found. Importing '$s3Key' from bucket '$S3_BUCKET'..." + + # Use jq to create the disk container JSON safely + local disk_container_json + disk_container_json=$(jq -n --arg desc "Snapshot for $s3Key" --arg bucket "$S3_BUCKET" --arg key "$s3Key" '{ + Description: $desc, + Format: "RAW", + UserBucket: { S3Bucket: $bucket, S3Key: $key } + }') + + # Initiate the snapshot import task + taskID=$(AWS ec2 import-snapshot --description "Import $s3Key" \ + --disk-container "$disk_container_json" \ + --tag-specifications 'ResourceType=import-snapshot-task,Tags=[{Key=Name,Value='"Import-$s3Key"'}]' \ + --query 'ImportTaskId' --output text) + + if [[ -z "$taskID" ]]; then + log "Error: Failed to initiate snapshot import for '$s3Key'." >&2 + exit 1 + fi + log "Snapshot import task started with ID: $taskID" + + # Wait for completion and get the Snapshot ID + snapshotID=$(waitForSnapshotCompletion "$taskID" | tail -1 | tee /dev/fd/2) + if [[ -z "$snapshotID" ]]; then + log "Error: waitForSnapshotCompletion did not return a Snapshot ID for task '$taskID'." >&2 + exit 1 + fi + + # log "Adding tag '$snapshot_tag_key=$s3Key' to snapshot '$snapshotID'..." + # if AWS ec2 create-tags --resources "$snapshotID" --tags Key="$snapshot_tag_key",Value="$s3Key" Key=Name,Value="$s3Key"; then + # log "Successfully tagged snapshot '$snapshotID'." + # else + # log "Warning: Failed to tag snapshot '$snapshotID'. Manual tagging might be required." >&2 + # # Decide if this is a critical failure or just a warning + # # exit 1 + # fi + + echo "$snapshotID" # Return the newly created snapshot ID +} + +# --- Main Execution --- +# check if object exists in s3 +OBJECT_EXISTS=false +if AWS s3 ls "s3://$S3_BUCKET/$S3_KEY" > /dev/null 2>&1; then + log "Object '$S3_KEY' already exists in s3://$S3_BUCKET/$S3_KEY." + OBJECT_EXISTS=true +fi + +# if object does not exist, upload it +if ! $OBJECT_EXISTS; then + log "Uploading '$RAW_FILE' to s3://$S3_BUCKET/$S3_KEY..." + if AWS s3 cp "$RAW_FILE" "s3://$S3_BUCKET/$S3_KEY"; then + log "Successfully uploaded '$RAW_FILE' to S3." + else + log "Error: Failed to upload '$RAW_FILE' to s3://$S3_BUCKET/$S3_KEY." >&2 + exit 1 + fi +fi + +# Step 2: Import S3 object as Snapshot +log "Importing S3 object 's3://$S3_BUCKET/$S3_KEY' as EC2 snapshot..." +snapshotID=$(importAsSnapshot "$S3_KEY" | tail -1) +if [[ -z "$snapshotID" ]]; then + log "Error: Failed to import snapshot from S3 object '$S3_KEY'." >&2 + exit 1 +fi +log "Snapshot import process completed. Snapshot ID: $snapshotID" + +# Step 3: Create (or find) AMI from Snapshot +# Use S3_KEY or a dedicated AMI name variable for the image name +ami_name="${AMI_NAME:-$S3_KEY}" # Use AMI_NAME from .arg if set, otherwise default to S3_KEY +log "Creating/Verifying AMI '$ami_name' from snapshot '$snapshotID'..." +final_ami_id=$(checkImageExistsOrCreate "$ami_name" "$snapshotID") +if [[ -z "$final_ami_id" ]]; then + log "Error: Failed to create or verify AMI '$ami_name'." >&2 + exit 1 +fi + +log "Process completed successfully!" +log "Final AMI ID: $final_ami_id" +log "AMI Name: $ami_name" +log "Region: $REGION" + +# Optional: Output AMI ID for automation +# echo "$final_ami_id" > /path/to/output/ami_id.txt + +exit 0 diff --git a/cloud-images/workaround/custom-post-reset.yaml b/cloud-images/workaround/custom-post-reset.yaml new file mode 100644 index 00000000..10d6e3fc --- /dev/null +++ b/cloud-images/workaround/custom-post-reset.yaml @@ -0,0 +1,54 @@ +stages: + after-reset: + - if: '[ ! -e "/run/cos/uki_boot_mode" ] && [ ! -e "/run/cos/uki_install_mode" ] && [ ! -f $STYLUS_ROOT/opt/spectrocloud/state/agent-mode ]' + - commands: + - rm /oem/80_stylus.yaml || true + - grub2-editenv /oem/grubenv set saved_entry=registration + name: "Set registration grub env entry after reset" + - if: '[ -e "/run/cos/uki_boot_mode" ] && [ ! -f $STYLUS_ROOT/opt/spectrocloud/state/agent-mode ]' + - commands: + - rm /oem/80_stylus.yaml || true + - kairos-agent bootentry --select registration + name: "Set EFI registration entry after reset" + - if: '[ ! -e "/run/cos/uki_boot_mode" ] && [ ! -e "/run/cos/uki_install_mode" ] && [ ! -f $STYLUS_ROOT/opt/spectrocloud/state/agent-mode ]' + commands: + - if mount | grep /usr/local >/dev/null; then umount /usr/local; fi + - mount $(findfs PARTLABEL=persistent) /usr/local + - bash /opt/spectrocloud/scripts/content.sh + - mkdir -p /usr/local/bin + - ln -sf /opt/spectrocloud/bin/agent-provider-stylus /usr/local/bin/agent-provider-stylus + - ln -sf /opt/spectrocloud/bin/palette-tui /usr/local/bin/palette-tui + - journalctl > /usr/local/installer.log + - umount /usr/local + name: "Run after install commands" + - if: '[ ! -e "/run/cos/uki_boot_mode" ] && [ ! -e "/run/cos/uki_install_mode" ] && [ ! -f $STYLUS_ROOT/opt/spectrocloud/state/agent-mode ]' + commands: + - if mount | grep /oem >/dev/null; then umount /oem || /bin/true; fi + - mount $(findfs PARTLABEL=oem) /oem + - if [ -e /run/initramfs/live/.edge_custom_config.yaml ]; then cp /run/initramfs/live/.edge_custom_config.yaml /oem/.edge_custom_config.yaml; fi + - umount /oem || /bin/true + name: "Copy public key after install" + - if: '[ -e "/run/cos/uki_install_mode" ] && [ ! -f $STYLUS_ROOT/opt/spectrocloud/state/agent-mode ]' + commands: + - if mount | grep /usr/local >/dev/null; then umount /usr/local; fi + - for d in /dev/mapper/*; do if [ ! "$d" = "/dev/mapper/control" ]; then cryptsetup close $d; fi; done + - /usr/lib/systemd/systemd-cryptsetup attach persistent $(findfs PARTLABEL=persistent) - tpm2-device=auto + - mount /dev/mapper/persistent /usr/local + - bash /opt/spectrocloud/scripts/content.sh + - mkdir -p /usr/local/bin + - ln -sf /opt/spectrocloud/bin/agent-provider-stylus /usr/local/bin/agent-provider-stylus + - ln -sf /opt/spectrocloud/bin/palette-tui /usr/local/bin/palette-tui + - journalctl > /usr/local/installer.log + - if mount | grep /usr/local >/dev/null; then umount /usr/local; fi + - if [ -e /dev/mapper/persistent ]; then cryptsetup close /dev/mapper/persistent; fi + name: "Run after uki install commands" + - if: '[ -e "/run/cos/uki_install_mode" ] && [ ! -f $STYLUS_ROOT/opt/spectrocloud/state/agent-mode ]' + commands: + - if mount | grep /oem >/dev/null; then umount /oem || /bin/true; fi + - for d in /dev/mapper/*; do if [ ! "$d" = "/dev/mapper/control" ]; then cryptsetup close $d; fi; done + - /usr/lib/systemd/systemd-cryptsetup attach oem $(findfs PARTLABEL=oem) - tpm2-device=auto + - mount /dev/mapper/oem /oem + - if [ -e /run/initramfs/live/.edge_custom_config.yaml ]; then cp /run/initramfs/live/.edge_custom_config.yaml /oem/.edge_custom_config.yaml; fi + - if mount | grep /oem >/dev/null; then umount /oem || /bin/true; fi + - if [ -e /dev/mapper/oem ]; then cryptsetup close /dev/mapper/oem; fi + name: "Run uki copy public key after install commands" \ No newline at end of file diff --git a/cloud-images/workaround/grubmenu.cfg b/cloud-images/workaround/grubmenu.cfg new file mode 100644 index 00000000..1e2a4b5a --- /dev/null +++ b/cloud-images/workaround/grubmenu.cfg @@ -0,0 +1,26 @@ +menuentry "Palette eXtended Kubernetes Edge Reset" --id statereset { + if [ test -s /cOS/recovery.squashfs ]; then + set img=/cOS/recovery.squashfs + set recoverylabel=COS_RECOVERY + else + set img=/cOS/recovery.img + fi + search.fs_label COS_RECOVERY root + set label=COS_SYSTEM + loopback loop0 /$img + set root=($root) + source (loop0)/etc/cos/bootargs.cfg + linux (loop0)$kernel $kernelcmd ${extra_cmdline} ${extra_recovery_cmdline} kairos.reset + initrd (loop0)$initramfs +} + +menuentry "Palette eXtended Kubernetes Edge Registration" --id registration { + search --no-floppy --label --set=root COS_STATE + set img=/cOS/active.img + set label=COS_ACTIVE + loopback loop0 /$img + set root=($root) + source (loop0)/etc/cos/bootargs.cfg + linux (loop0)$kernel $kernelcmd ${extra_cmdline} ${extra_active_cmdline} stylus.registration + initrd (loop0)$initramfs +} \ No newline at end of file diff --git a/custom-postreset.yaml b/custom-postreset.yaml new file mode 100644 index 00000000..e5451a13 --- /dev/null +++ b/custom-postreset.yaml @@ -0,0 +1,54 @@ +stages: + after-reset: + - if: '[ ! -e "/run/cos/uki_boot_mode" ] && [ ! -e "/run/cos/uki_install_mode" ] && [ ! -f $STYLUS_ROOT/opt/spectrocloud/state/agent-mode ]' + - commands: + - rm /oem/80_stylus.yaml || true + - grub2-editenv /oem/grubenv set saved_entry=registration + name: "Set registration grub env entry after reset" + - if: '[ -e "/run/cos/uki_boot_mode" ] && [ ! -f $STYLUS_ROOT/opt/spectrocloud/state/agent-mode ]' + - commands: + - rm /oem/80_stylus.yaml || true + - kairos-agent bootentry --select registration + name: "Set EFI registration entry after reset" + - if: '[ ! -e "/run/cos/uki_boot_mode" ] && [ ! -e "/run/cos/uki_install_mode" ] && [ ! -f $STYLUS_ROOT/opt/spectrocloud/state/agent-mode ]' + commands: + - if mount | grep /usr/local >/dev/null; then umount /usr/local; fi + - mount $(findfs PARTLABEL=persistent) /usr/local + - bash /opt/spectrocloud/scripts/content.sh + - mkdir -p /usr/local/bin + - ln -sf /opt/spectrocloud/bin/agent-provider-stylus /usr/local/bin/agent-provider-stylus + - ln -sf /opt/spectrocloud/bin/palette-tui /usr/local/bin/palette-tui + - journalctl > /usr/local/installer.log + - umount /usr/local + name: "Run after install commands" + - if: '[ ! -e "/run/cos/uki_boot_mode" ] && [ ! -e "/run/cos/uki_install_mode" ] && [ ! -f $STYLUS_ROOT/opt/spectrocloud/state/agent-mode ]' + commands: + - if mount | grep /oem >/dev/null; then umount /oem || /bin/true; fi + - mount $(findfs PARTLABEL=oem) /oem + - if [ -e /run/initramfs/live/.edge_custom_config.yaml ]; then cp /run/initramfs/live/.edge_custom_config.yaml /oem/.edge_custom_config.yaml; fi + - umount /oem || /bin/true + name: "Copy public key after install" + - if: '[ -e "/run/cos/uki_install_mode" ] && [ ! -f $STYLUS_ROOT/opt/spectrocloud/state/agent-mode ]' + commands: + - if mount | grep /usr/local >/dev/null; then umount /usr/local; fi + - for d in /dev/mapper/*; do if [ ! "$d" = "/dev/mapper/control" ]; then cryptsetup close $d; fi; done + - /usr/lib/systemd/systemd-cryptsetup attach persistent $(findfs PARTLABEL=persistent) - tpm2-device=auto + - mount /dev/mapper/persistent /usr/local + - bash /opt/spectrocloud/scripts/content.sh + - mkdir -p /usr/local/bin + - ln -sf /opt/spectrocloud/bin/agent-provider-stylus /usr/local/bin/agent-provider-stylus + - ln -sf /opt/spectrocloud/bin/palette-tui /usr/local/bin/palette-tui + - journalctl > /usr/local/installer.log + - if mount | grep /usr/local >/dev/null; then umount /usr/local; fi + - if [ -e /dev/mapper/persistent ]; then cryptsetup close /dev/mapper/persistent; fi + name: "Run after uki install commands" + - if: '[ -e "/run/cos/uki_install_mode" ] && [ ! -f $STYLUS_ROOT/opt/spectrocloud/state/agent-mode ]' + commands: + - if mount | grep /oem >/dev/null; then umount /oem || /bin/true; fi + - for d in /dev/mapper/*; do if [ ! "$d" = "/dev/mapper/control" ]; then cryptsetup close $d; fi; done + - /usr/lib/systemd/systemd-cryptsetup attach oem $(findfs PARTLABEL=oem) - tpm2-device=auto + - mount /dev/mapper/oem /oem + - if [ -e /run/initramfs/live/.edge_custom_config.yaml ]; then cp /run/initramfs/live/.edge_custom_config.yaml /oem/.edge_custom_config.yaml; fi + - if mount | grep /oem >/dev/null; then umount /oem || /bin/true; fi + - if [ -e /dev/mapper/oem ]; then cryptsetup close /dev/mapper/oem; fi + name: "Run uki copy public key after install commands" diff --git a/grubmenu.cfg b/grubmenu.cfg new file mode 100644 index 00000000..0ecac2dd --- /dev/null +++ b/grubmenu.cfg @@ -0,0 +1,26 @@ +menuentry "Palette eXtended Kubernetes Edge Reset" --id statereset { + if [ test -s /cOS/recovery.squashfs ]; then + set img=/cOS/recovery.squashfs + set recoverylabel=COS_RECOVERY + else + set img=/cOS/recovery.img + fi + search.fs_label COS_RECOVERY root + set label=COS_SYSTEM + loopback loop0 /$img + set root=($root) + source (loop0)/etc/cos/bootargs.cfg + linux (loop0)$kernel $kernelcmd ${extra_cmdline} ${extra_recovery_cmdline} kairos.reset + initrd (loop0)$initramfs +} + +menuentry "Palette eXtended Kubernetes Edge Registration" --id registration { + search --no-floppy --label --set=root COS_STATE + set img=/cOS/active.img + set label=COS_ACTIVE + loopback loop0 /$img + set root=($root) + source (loop0)/etc/cos/bootargs.cfg + linux (loop0)$kernel $kernelcmd ${extra_cmdline} ${extra_active_cmdline} stylus.registration + initrd (loop0)$initramfs +} diff --git a/scripts/build-raw-image-auroraboot.sh b/scripts/build-raw-image-auroraboot.sh new file mode 100644 index 00000000..0e55fe92 --- /dev/null +++ b/scripts/build-raw-image-auroraboot.sh @@ -0,0 +1,15 @@ +#/bin/bash +set -x +containerImage=$2 +docker run -v /var/run/docker.sock:/var/run/docker.sock \ + -v $PWD/$1:/config.yaml \ + --net host \ + --privileged \ + -v $PWD:/aurora --rm quay.io/kairos/auroraboot:v0.6.4 \ + --debug \ + --set "disable_http_server=true" \ + --set "container_image=docker:${containerImage}" \ + --set "disable_netboot=true" \ + --set "disk.raw=true" \ + --set "state_dir=/aurora" \ + --cloud-config /config.yaml \ No newline at end of file From 633b075aa680ba3f09ee1d331611395f4066a8a0 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Mon, 17 Nov 2025 13:03:13 +0000 Subject: [PATCH 19/40] updating alpine tag --- docker-bake.hcl | 17 +++++++++++++++-- dockerfiles/Dockerfile.alpine | 9 +++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 dockerfiles/Dockerfile.alpine diff --git a/docker-bake.hcl b/docker-bake.hcl index 21b3dfa1..c05a4f73 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -21,7 +21,7 @@ variable "SPECTRO_THIRD_PARTY_IMAGE" { } variable "ALPINE_TAG" { - default = "3.20" + default = "3.22" } variable "ALPINE_IMG" { @@ -197,6 +197,10 @@ variable "BASE_IMAGE" { default = "" } +variable "ALPINE_BASE_IMAGE" { + default = FIPS_ENABLED ? "us-docker.pkg.dev/palette-images-fips/third-party/alpine:${ALPINE_TAG}-fips" : "us-docker.pkg.dev/palette-images/third-party/alpine:${ALPINE_TAG}" +} + variable "OSBUILDER_IMAGE" {} variable "IS_JETSON" { @@ -607,8 +611,17 @@ target "iso-disk-image" { platforms = ["linux/${ARCH}"] contexts = { build-iso = IS_UKI ? "target:build-uki-iso" : "target:build-iso" - # build-iso = "target:build-iso" } tags = ["${IMAGE_REGISTRY}/${IMAGE_REPO}/${ISO_NAME}:${IMAGE_TAG}"] output = ["type=image,push=true"] } + +target "alpine-all" { + dockerfile = "dockerfiles/Dockerfile.alpine" + platforms = ["linux/amd64", "linux/arm64"] + args = { + ALPINE_BASE_IMAGE = ALPINE_BASE_IMAGE + } + tags = [ALPINE_IMG] + output = ["type=image,push=true"] +} diff --git a/dockerfiles/Dockerfile.alpine b/dockerfiles/Dockerfile.alpine new file mode 100644 index 00000000..1ab1ab39 --- /dev/null +++ b/dockerfiles/Dockerfile.alpine @@ -0,0 +1,9 @@ +ARG ALPINE_BASE_IMAGE + +FROM ${ALPINE_BASE_IMAGE} + +RUN apk add --no-cache bash curl jq ca-certificates upx + +# In FIPS mode, this may fail due to OpenSSL FIPS constraints. +RUN update-ca-certificates || true + From 38fb67fa963ef6734bee1ba4aad9123b36e2a9e0 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Mon, 17 Nov 2025 15:02:28 +0000 Subject: [PATCH 20/40] skipping kernel update for fips --- docker-bake.hcl | 1 + dockerfiles/Dockerfile.base-image | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docker-bake.hcl b/docker-bake.hcl index c05a4f73..7deec364 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -304,6 +304,7 @@ target "base-image" { KAIROS_VERSION = KAIROS_VERSION DISABLE_SELINUX = DISABLE_SELINUX ARCH = ARCH + FIPS_ENABLED = FIPS_ENABLED } } diff --git a/dockerfiles/Dockerfile.base-image b/dockerfiles/Dockerfile.base-image index f3ced693..1cbe1b45 100644 --- a/dockerfiles/Dockerfile.base-image +++ b/dockerfiles/Dockerfile.base-image @@ -11,6 +11,7 @@ ARG CIS_HARDENING ARG KAIROS_VERSION ARG DISABLE_SELINUX ARG ARCH +ARG FIPS_ENABLED COPY . /tmp/build-context RUN if [ "$IS_JETSON" = "true" ]; then \ @@ -49,12 +50,14 @@ RUN if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ]; then \ apt-get purge -y $(dpkg -l | awk '/^ii\s+linux-(image|headers|modules)/ {print $2}' | grep -v "${latest_kernel}") && \ apt-get autoremove -y && \ rm -rf /var/lib/apt/lists/* && \ - \ kernel=$(ls /boot/vmlinuz-* | tail -n1) && \ ln -sf "${kernel#/boot/}" /boot/vmlinuz && \ - kernel=$(ls /lib/modules | tail -n1) && \ - dracut -f "/boot/initrd-${kernel}" "${kernel}" && \ - ln -sf "initrd-${kernel}" /boot/initrd && \ + if [ "$FIPS_ENABLED" = "false" ]; then \ + kernel=$(printf '%s\n' /lib/modules/* | xargs -n1 basename | sort -V | tail -1) && \ + dracut -f "/boot/initrd-${kernel}" "${kernel}" && \ + ln -sf "initrd-${kernel}" /boot/initrd; \ + fi && \ + kernel=$(printf '%s\n' /lib/modules/* | xargs -n1 basename | sort -V | tail -1) && \ depmod -a "${kernel}" && \ \ if [ ! -f /usr/bin/grub2-editenv ]; then \ From e932f5e8d1ecbe8fa6d571adb448ebbcf302f7b2 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Tue, 18 Nov 2025 13:44:16 +0000 Subject: [PATCH 21/40] refactoring and new make targets --- Makefile | 34 ++++++++--------- docker-bake.hcl | 21 +--------- dockerfiles/Dockerfile.base-image | 38 ++++++++++++++----- dockerfiles/Dockerfile.install-k8s | 8 ++-- dockerfiles/Dockerfile.iso-image | 11 +++++- dockerfiles/Dockerfile.third-party | 15 ++------ ubuntu-fips/22.04/Dockerfile.ubuntu22.04-fips | 2 +- 7 files changed, 65 insertions(+), 64 deletions(-) diff --git a/Makefile b/Makefile index 3efe3199..12e35583 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ space := $(empty) $(empty) # Get target type based on IS_UKI PROVIDER_TARGET_TYPE = $(if $(filter true,$(IS_UKI)),uki-provider-image,provider-image) +ISO_TARGET_TYPE = $(if $(filter true,$(IS_UKI)),build-uki-iso,build-iso) # Get versions: either from K8S_VERSION or k8s_version.json ALL_K8S_VERSIONS = $(if $(strip $(K8S_VERSION)),\ @@ -19,27 +20,23 @@ ALL_K8S_VERSIONS = $(if $(strip $(K8S_VERSION)),\ PUSH ?= true IS_UKI ?= false -build-all-images: - $(MAKE) build-provider-images - @if [ "$(ARCH)" = "arm64" ]; then \ - docker buildx bake iso-image --set iso-image.platforms=linux/arm64; \ - elif [ "$(ARCH)" = "amd64" ]; then \ - docker buildx bake iso-image --set iso-image.platforms=linux/amd64; \ - fi - $(MAKE) build-iso +build-all-images: build-provider-images iso + + +build: + docker buildx bake ${TARGET} base-image: - docker buildx bake base-image + # docker buildx bake base-image + $(MAKE) TARGET=base-image build iso: - @if [ "$(IS_UKI)" = "true" ]; then \ - docker buildx bake build-uki-iso; \ - else \ - docker buildx bake build-iso; \ - fi + # docker buildx bake $(ISO_TARGET_TYPE) + $(MAKE) TARGET=$(ISO_TARGET_TYPE) build iso-disk-image: - docker buildx bake iso-disk-image + # docker buildx bake iso-disk-image + $(MAKE) TARGET=iso-disk-image build build-provider-images: check-k8s-distribution check-versions $(addprefix build-provider-image-,$(strip $(ALL_K8S_VERSIONS))) @echo "All provider images built successfully" @@ -47,6 +44,7 @@ build-provider-images: check-k8s-distribution check-versions $(addprefix build-p build-provider-image-%: check-k8s-distribution @echo "building for k8s version - $*" @env K8S_VERSION=$* docker buildx bake $(PROVIDER_TARGET_TYPE) --set *.args.K8S_VERSION=$* + # $(MAKE) TARGET=$(PROVIDER_TARGET_TYPE) build K8S_VERSION=$* check-versions: @$(if $(strip $(ALL_K8S_VERSIONS)),,$(error No versions found for K8S_DISTRIBUTION=$(K8S_DISTRIBUTION))) @@ -54,6 +52,6 @@ check-versions: check-k8s-distribution: @$(if $(strip $(K8S_DISTRIBUTION)),,$(error K8S_DISTRIBUTION is not set. Please set K8S_DISTRIBUTION to kubeadm, kubeadm-fips, k3s, nodeadm, rke2 or canonical)) - - - +uki-genkey: + # docker buildx bake uki-genkey + $(MAKE) TARGET=uki-genkey build diff --git a/docker-bake.hcl b/docker-bake.hcl index 7deec364..903d4470 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -32,9 +32,6 @@ variable "SPECTRO_LUET_REPO" { default = "us-docker.pkg.dev/palette-images/edge" } -variable "LUET_PROJECT" { - default = "luet-repo" -} variable "PE_VERSION" { default = "v4.7.16" @@ -237,21 +234,6 @@ function "get_ubuntu_image" { result = fips_enabled ? "${spectro_pub_repo}/third-party/ubuntu-fips:22.04" : "${spectro_pub_repo}/third-party/ubuntu:22.04" } -secret "enrollment" { - type = "file" - src = "secure-boot/enrollment/" -} - -secret "private-keys" { - type = "file" - src = "secure-boot/private-keys/" -} - -secret "public-keys" { - type = "file" - src = "secure-boot/public-keys/" -} - function "get_base_image" { params = [base_image, os_distribution, os_version, is_uki] result = base_image != "" ? base_image : ( @@ -352,8 +334,7 @@ target "install-k8s" { K8S_VERSION = K8S_VERSION K3S_FLAVOR_TAG = K3S_FLAVOR_TAG RKE2_FLAVOR_TAG = RKE2_FLAVOR_TAG - LUET_PROJECT = LUET_PROJECT - LUET_REPO = ARCH == "arm64" ? "${LUET_PROJECT}-arm" : "${LUET_PROJECT}-amd" + LUET_REPO = ARCH == "arm64" ? "luet-repo-arm" : "luet-repo-amd" SPECTRO_LUET_REPO = SPECTRO_LUET_REPO } } diff --git a/dockerfiles/Dockerfile.base-image b/dockerfiles/Dockerfile.base-image index 1cbe1b45..ad732123 100644 --- a/dockerfiles/Dockerfile.base-image +++ b/dockerfiles/Dockerfile.base-image @@ -24,12 +24,13 @@ RUN if [ "$IS_UKI" = "true" ]; then \ RUN if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ]; then \ if [ ! -z "$UBUNTU_PRO_KEY" ]; then \ sed -i '/^[[:space:]]*$/d' /etc/os-release && \ - apt update && apt-get install -y snapd && \ + apt update && \ + apt-get install -y snapd && \ pro attach $UBUNTU_PRO_KEY; \ fi && \ \ - apt-get update && \ - apt-get install --no-install-recommends kbd zstd vim iputils-ping bridge-utils curl tcpdump ethtool rsyslog logrotate -y && \ + DEBIAN_FRONTEND=noninteractive apt-get update && \ + DEBIAN_FRONTEND=noninteractive UCF_FORCE_CONFFOLD=1 apt-get install --no-install-recommends kbd zstd vim iputils-ping bridge-utils curl tcpdump ethtool rsyslog logrotate -y && \ \ APT_UPGRADE_FLAGS="-y" && \ if [ "$UPDATE_KERNEL" = "false" ]; then \ @@ -40,18 +41,37 @@ RUN if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ]; then \ apt-mark hold linux-image-generic linux-headers-generic linux-generic; \ fi; \ else \ - APT_UPGRADE_FLAGS="-y --with-new-pkgs"; \ + APT_UPGRADE_FLAGS="-y --with-new-pkgs" && \ + DEBIAN_FRONTEND=noninteractive apt-get update && \ + apt-get install -y linux-image-generic-hwe-$OS_VERSION; \ fi && \ \ if [ "$IS_UKI" = "false" ]; then \ DEBIAN_FRONTEND=noninteractive apt-get update && \ apt-get upgrade $APT_UPGRADE_FLAGS && \ - latest_kernel=$(ls /lib/modules | tail -n1 | awk -F '-' '{print $1"-"$2}') && \ - apt-get purge -y $(dpkg -l | awk '/^ii\s+linux-(image|headers|modules)/ {print $2}' | grep -v "${latest_kernel}") && \ + DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y cloud-guest-utils && \ + \ + latest_kernel=$(printf '%s\n' /lib/modules/* | xargs -n1 basename | sort -V | tail -1 | awk -F '-' '{print $1"-"$2}') && \ + if [ "$FIPS_ENABLED" = "true" ]; then \ + # When FIPS is enabled, we need to remove any non-FIPS kernel packages (e.g., 5.15 HWE) to avoid conflicts. + # However, some kernel packages may be held (apt-mark hold), which causes `apt-get purge` to fail with: + # "E: Held packages were changed and -y was used without --allow-change-held-packages." + # To fix this, we first unhold all matching non-FIPS and non-latest kernel packages before purging them. + # This ensures a clean, FIPS-only environment without apt resolver errors. + for pkg in $(dpkg -l | awk '/^.i\s+linux-(image|headers|modules)/ {print $2}' \ + | grep -v "$latest_kernel" | grep -v fips); do \ + apt-mark unhold "$pkg" || true; \ + done && \ + apt-get purge -y $(dpkg -l | awk '/^.i\s+linux-(image|headers|modules)/ {print $2}' | grep -v "${latest_kernel}" | grep -v fips); \ + else \ + apt-get purge -y $(dpkg -l | awk '/^ii\s+linux-(image|headers|modules)/ {print $2}' | grep -v "${latest_kernel}"); \ + fi && \ apt-get autoremove -y && \ rm -rf /var/lib/apt/lists/* && \ - kernel=$(ls /boot/vmlinuz-* | tail -n1) && \ - ln -sf "${kernel#/boot/}" /boot/vmlinuz && \ + kernel=$(ls /boot/vmlinuz-* 2>/dev/null | tail -n1) && \ + # if [ -n "$kernel" ]; then \ + ln -sf "${kernel#/boot/}" /boot/vmlinuz; \ + # fi && \ if [ "$FIPS_ENABLED" = "false" ]; then \ kernel=$(printf '%s\n' /lib/modules/* | xargs -n1 basename | sort -V | tail -1) && \ dracut -f "/boot/initrd-${kernel}" "${kernel}" && \ @@ -124,7 +144,7 @@ RUN export OS_ID=${OS_DISTRIBUTION} && \ export OS_REPO=spectrocloud/CanvOS && \ export OS_NAME=${kairos-core-${OS_DISTRIBUTION}} && \ export ARTIFACT=${kairos-core-${OS_DISTRIBUTION}-${OS_VERSION}} && \ - export KAIROS_RELEASE=${OS_VERSION} && \ + export KAIROS_RELEASE=${KAIROS_VERSION} && \ envsubst >>/etc/os-release < /tmp/build-context/overlay/files/usr/lib/os-release.tmpl RUN rm -rf /var/cache/* && \ diff --git a/dockerfiles/Dockerfile.install-k8s b/dockerfiles/Dockerfile.install-k8s index 7cf14307..00412b7b 100644 --- a/dockerfiles/Dockerfile.install-k8s +++ b/dockerfiles/Dockerfile.install-k8s @@ -7,7 +7,6 @@ ARG K8S_DISTRIBUTION ARG K8S_VERSION ARG K3S_FLAVOR_TAG ARG RKE2_FLAVOR_TAG -ARG LUET_PROJECT ARG SPECTRO_LUET_REPO ARG ARCH ARG LUET_REPO @@ -20,12 +19,13 @@ COPY --from=third-party-luet /WORKDIR/luet /usr/bin/luet WORKDIR /output +COPY . /tmp/build-context/ + RUN mkdir -p /etc/luet/repos.conf.d && \ luet repo add spectro --type docker --url $SPECTRO_LUET_REPO/$LUET_REPO --priority 1 -y -COPY . /tmp/build-context/ + RUN if [ -f /tmp/build-context/spectro-luet-auth.yaml ]; then \ - cp /tmp/build-context/spectro-luet-auth.yaml spectro-luet-auth.yaml && \ - cat spectro-luet-auth.yaml >> /etc/luet/repos.conf.d/spectro.yaml; \ + cat /tmp/build-context/spectro-luet-auth.yaml >> /etc/luet/repos.conf.d/spectro.yaml; \ fi RUN luet repo update diff --git a/dockerfiles/Dockerfile.iso-image b/dockerfiles/Dockerfile.iso-image index bb28f3d9..0bdcff5d 100644 --- a/dockerfiles/Dockerfile.iso-image +++ b/dockerfiles/Dockerfile.iso-image @@ -1,5 +1,6 @@ ARG ARCH ARG IS_UKI +ARG IS_CLOUD_IMAGE=false FROM base-image AS iso-image @@ -16,6 +17,14 @@ RUN if [ -f /etc/logrotate.d/stylus.conf ]; then \ chmod 644 /etc/logrotate.d/stylus.conf; \ fi +COPY cloud-images/workaround/ /tmp/cloud-images/workaround/ + +RUN if [ "$IS_CLOUD_IMAGE" = "true" ]; then \ + cp /tmp/cloud-images/workaround/grubmenu.cfg /etc/kairos/branding/grubmenu.cfg && \ + cp /tmp/cloud-images/workaround/custom-post-reset.yaml /system/oem/custom-post-reset.yaml; \ + fi + RUN rm -f /etc/ssh/ssh_host_* /etc/ssh/moduli && \ touch /etc/machine-id && \ - chmod 444 /etc/machine-id \ No newline at end of file + chmod 444 /etc/machine-id && \ + rm -rf /tmp/cloud-images \ No newline at end of file diff --git a/dockerfiles/Dockerfile.third-party b/dockerfiles/Dockerfile.third-party index dd6e0b43..2e71339b 100644 --- a/dockerfiles/Dockerfile.third-party +++ b/dockerfiles/Dockerfile.third-party @@ -3,21 +3,14 @@ ARG TARGETPLATFORM ARG ALPINE_IMG FROM --platform=${TARGETPLATFORM} ${SPECTRO_THIRD_PARTY_IMAGE} AS source -FROM --platform=${TARGETPLATFORM} ${ALPINE_IMG} AS download-third-party -ARG ARCH -ARG BIN_TYPE -ARG binary - -COPY --from=source /binaries/${binary}/latest/${BIN_TYPE}/${ARCH}/${binary} /artifacts/${binary} -COPY --from=source /binaries/${binary}/latest/${BIN_TYPE}/${ARCH}/${binary}.version /artifacts/${binary}.version - -FROM ${ALPINE_IMG} AS third-party +FROM --platform=${TARGETPLATFORM} ${ALPINE_IMG} AS third-party ARG ARCH +ARG BIN_TYPE ARG binary WORKDIR /WORKDIR -COPY --from=download-third-party /artifacts/${binary} /WORKDIR/${binary} -COPY --from=download-third-party /artifacts/${binary}.version /WORKDIR/${binary}.version +COPY --from=source /binaries/${binary}/latest/${BIN_TYPE}/${ARCH}/${binary} /WORKDIR/${binary} +COPY --from=source /binaries/${binary}/latest/${BIN_TYPE}/${ARCH}/${binary}.version /WORKDIR/${binary}.version RUN upx -1 /WORKDIR/${binary} \ No newline at end of file diff --git a/ubuntu-fips/22.04/Dockerfile.ubuntu22.04-fips b/ubuntu-fips/22.04/Dockerfile.ubuntu22.04-fips index d6605b84..6178dd87 100644 --- a/ubuntu-fips/22.04/Dockerfile.ubuntu22.04-fips +++ b/ubuntu-fips/22.04/Dockerfile.ubuntu22.04-fips @@ -1,4 +1,4 @@ -FROM quay.io/kairos/kairos-init:v0.5.17 AS kairos-init +FROM quay.io/kairos/kairos-init:v0.5.20 AS kairos-init FROM ubuntu:22.04 ARG VERSION=v3.5.3 From 1e7e1d2fd0122a495275f081a9f12bdb8666da70 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Tue, 18 Nov 2025 21:08:41 +0000 Subject: [PATCH 22/40] fix uki image generation --- Makefile | 110 +++++++++++++++++------ docker-bake.hcl | 38 +------- dockerfiles/Dockerfile.build-uki-iso | 22 ++--- dockerfiles/Dockerfile.trustedboot-image | 13 +-- dockerfiles/Dockerfile.uki-genkey | 2 +- 5 files changed, 98 insertions(+), 87 deletions(-) diff --git a/Makefile b/Makefile index 12e35583..1ec9a667 100644 --- a/Makefile +++ b/Makefile @@ -1,57 +1,113 @@ -include .arg export -.PHONY: base-image build-iso build-provider-images iso-disk-image +# ============================================================================== +# PHONY TARGETS +# ============================================================================== +.PHONY: build build-all-images base-image iso build-provider-images iso-disk-image \ + uki-genkey alpine-all validate-user-data help -# Helper variables for Make-based processing +.SILENT: uki-genkey validate-user-data + +# ============================================================================== +# HELPER VARIABLES +# ============================================================================== comma := , empty := space := $(empty) $(empty) -# Get target type based on IS_UKI +# ============================================================================== +# CONFIGURATION DEFAULTS +# ============================================================================== +PUSH ?= true +DEBUG ?= false +NO_CACHE ?= false + +# ============================================================================== +# COMPUTED VARIABLES +# ============================================================================== +# Target type selection based on IS_UKI flag PROVIDER_TARGET_TYPE = $(if $(filter true,$(IS_UKI)),uki-provider-image,provider-image) ISO_TARGET_TYPE = $(if $(filter true,$(IS_UKI)),build-uki-iso,build-iso) -# Get versions: either from K8S_VERSION or k8s_version.json +# Docker buildx progress output +DOCKER_BUILD_OUT = $(if $(filter true,$(DEBUG)),--progress=plain,) + +# Docker buildx no-cache flag +DOCKER_NO_CACHE = $(if $(filter true,$(NO_CACHE)),--no-cache,) + +# K8S versions: either from K8S_VERSION (comma-separated) or k8s_version.json ALL_K8S_VERSIONS = $(if $(strip $(K8S_VERSION)),\ $(subst $(comma),$(space),$(K8S_VERSION)),\ $(shell jq -r --arg key "$(K8S_DISTRIBUTION)" 'if .[$$key] then .[$$key][] else empty end' k8s_version.json)) -PUSH ?= true -IS_UKI ?= false - -build-all-images: build-provider-images iso - +# Common BAKE_ARGS for pushing images +PUSH_ARGS = $(if $(filter true,$(PUSH)),--set *.output=type=image,push=$(PUSH),) +# ============================================================================== +# CORE BUILD TARGET +# ============================================================================== build: - docker buildx bake ${TARGET} + @$(if $(BAKE_ENV),env $(BAKE_ENV)) \ + docker buildx bake ${DOCKER_BUILD_OUT} ${DOCKER_NO_CACHE} ${TARGET} $(BAKE_ARGS) + +# ============================================================================== +# MAIN BUILD TARGETS +# ============================================================================== +build-all-images: build-provider-images iso base-image: - # docker buildx bake base-image $(MAKE) TARGET=base-image build iso: - # docker buildx bake $(ISO_TARGET_TYPE) $(MAKE) TARGET=$(ISO_TARGET_TYPE) build iso-disk-image: - # docker buildx bake iso-disk-image - $(MAKE) TARGET=iso-disk-image build + $(MAKE) TARGET=iso-disk-image build BAKE_ARGS="$(PUSH_ARGS)" -build-provider-images: check-k8s-distribution check-versions $(addprefix build-provider-image-,$(strip $(ALL_K8S_VERSIONS))) +# ============================================================================== +# PROVIDER IMAGE BUILD TARGETS +# ============================================================================== +build-provider-images: .check-provider-prereqs $(addprefix .build-provider-image-,$(strip $(ALL_K8S_VERSIONS))) @echo "All provider images built successfully" -build-provider-image-%: check-k8s-distribution - @echo "building for k8s version - $*" - @env K8S_VERSION=$* docker buildx bake $(PROVIDER_TARGET_TYPE) --set *.args.K8S_VERSION=$* - # $(MAKE) TARGET=$(PROVIDER_TARGET_TYPE) build K8S_VERSION=$* - -check-versions: - @$(if $(strip $(ALL_K8S_VERSIONS)),,$(error No versions found for K8S_DISTRIBUTION=$(K8S_DISTRIBUTION))) - -check-k8s-distribution: - @$(if $(strip $(K8S_DISTRIBUTION)),,$(error K8S_DISTRIBUTION is not set. Please set K8S_DISTRIBUTION to kubeadm, kubeadm-fips, k3s, nodeadm, rke2 or canonical)) - +.build-provider-image-%: .check-provider-prereqs + @echo "Building provider image for k8s version: $*" + $(MAKE) TARGET=$(PROVIDER_TARGET_TYPE) \ + BAKE_ENV="K8S_VERSION=$*" \ + BAKE_ARGS="--set *.args.K8S_VERSION=$* $(PUSH_ARGS)" \ + build + +.check-provider-prereqs: + @$(if $(strip $(K8S_DISTRIBUTION)),,\ + $(error K8S_DISTRIBUTION is not set. Please set K8S_DISTRIBUTION to kubeadm, kubeadm-fips, k3s, nodeadm, rke2 or canonical)) + @$(if $(strip $(ALL_K8S_VERSIONS)),,\ + $(error No versions found for K8S_DISTRIBUTION=$(K8S_DISTRIBUTION))) + +# ============================================================================== +# UTILITY TARGETS +# ============================================================================== uki-genkey: - # docker buildx bake uki-genkey $(MAKE) TARGET=uki-genkey build + ./keys.sh secure-boot/ + +validate-user-data: + $(MAKE) TARGET=validate-user-data build + +alpine-all: + $(MAKE) TARGET=alpine-all BAKE_ARGS="$(PUSH_ARGS)" build + +help: + @echo "Available targets:" + @echo " build-all-images - Build all provider images and ISO" + @echo " base-image - Build base image" + @echo " iso - Build ISO installer" + @echo " iso-disk-image - Build ISO disk image" + @echo " build-provider-images - Build all provider images for configured K8S versions" + @echo " uki-genkey - Generate UKI secure boot keys" + @echo " validate-user-data - Validate user-data configuration" + @echo "" + @echo "Configuration (set in .arg file or as make variables):" + @echo " PUSH - Push images to registry (default: true)" + @echo " DEBUG - Enable debug output (default: false)" + @echo " NO_CACHE - Disable build cache (default: false)" diff --git a/docker-bake.hcl b/docker-bake.hcl index 903d4470..1a9f81e6 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -42,7 +42,7 @@ variable "KAIROS_VERSION" { } variable AURORABOOT_IMAGE { - default = "quay.io/kairos/auroraboot:v0.10.0" + default = "quay.io/kairos/auroraboot:v0.8.7" } variable "K3S_PROVIDER_VERSION" { @@ -396,23 +396,6 @@ target "trustedboot-image" { contexts = { provider-image = "target:provider-image" } - secret = [ - { - type = "file" - src = "secure-boot/enrollment/" - id = "enrollment" - }, - { - type = "file" - src = "secure-boot/private-keys/" - id = "private-keys" - }, - { - type = "file" - src = "secure-boot/public-keys/" - id = "public-keys" - } - ] args = { AURORABOOT_IMAGE = AURORABOOT_IMAGE } @@ -484,24 +467,7 @@ target "build-uki-iso" { CMDLINE = CMDLINE BRANDING = BRANDING } - secret = [ - { - type = "file" - src = "secure-boot/enrollment/" - id = "enrollment" - }, - { - type = "file" - src = "secure-boot/private-keys/" - id = "private-keys" - }, - { - type = "file" - src = "secure-boot/public-keys/" - id = "public-keys" - } - ] - output = ["type=local,dest=./iso-output/"] + output = ["type=local,dest=./build/"] } target "stylus-image-pack" { diff --git a/dockerfiles/Dockerfile.build-uki-iso b/dockerfiles/Dockerfile.build-uki-iso index d664784e..0b938e3c 100644 --- a/dockerfiles/Dockerfile.build-uki-iso +++ b/dockerfiles/Dockerfile.build-uki-iso @@ -6,7 +6,7 @@ ARG ISO_NAME ARG CLUSTERCONFIG ARG EDGE_CUSTOM_CONFIG ARG AUTO_ENROLL_SECUREBOOT_KEYS -ARG DEBUG +ARG DEBUG=false ARG CMDLINE ARG BRANDING="Palette eXtended Kubernetes Edge" @@ -50,19 +50,13 @@ WORKDIR /build COPY --from=iso-image / /iso-source/ -RUN --mount=type=secret,id=enrollment,target=/tmp/enrollment \ - mkdir -p /keys && \ - cp -r /tmp/enrollment/* /keys/ - -RUN --mount=type=secret,id=private-keys,target=/tmp/private-keys \ - cp -r /tmp/private-keys/* /keys/ - -RUN --mount=type=secret,id=public-keys,target=/tmp/public-keys \ - cp -r /tmp/public-keys/* /keys/ +COPY secure-boot/enrollment/ secure-boot/private-keys/ secure-boot/public-keys/ /keys/ RUN if [ "$ARCH" = "amd64" ]; then \ mkdir -p /iso && \ - /usr/bin/auroraboot build-uki \ + /usr/bin/auroraboot \ + $([ "$DEBUG" = "true" ] && echo "--debug") \ + build-uki \ --output-type iso \ --name "${ISO_NAME}" \ --output-dir /iso \ @@ -70,10 +64,12 @@ RUN if [ "$ARCH" = "amd64" ]; then \ --keys /keys \ --boot-branding "${BRANDING}" \ $([ -n "$CMDLINE" ] && echo "--extend-cmdline \"$CMDLINE\"") \ - $([ "$AUTO_ENROLL_SECUREBOOT_KEYS" = "true" ] && echo "--secure-boot-enroll") \ - $([ "$DEBUG" = "true" ] && echo "--debug") \ + $([ "$AUTO_ENROLL_SECUREBOOT_KEYS" = "true" ] && echo "--secure-boot-enroll force") \ dir:/iso-source; \ fi +RUN cd /iso && \ + sha256sum "${ISO_NAME}.iso" > "${ISO_NAME}.iso.sha256" + FROM scratch as output COPY --from=builder /iso/ / \ No newline at end of file diff --git a/dockerfiles/Dockerfile.trustedboot-image b/dockerfiles/Dockerfile.trustedboot-image index fc4f480f..6b7e4e25 100644 --- a/dockerfiles/Dockerfile.trustedboot-image +++ b/dockerfiles/Dockerfile.trustedboot-image @@ -1,4 +1,5 @@ ARG AURORABOOT_IMAGE +ARG DEBUG=false FROM provider-image AS provider-image-rootfs @@ -6,19 +7,11 @@ FROM ${AURORABOOT_IMAGE} AS builder COPY --from=provider-image-rootfs / /build/image/ -RUN --mount=type=secret,id=enrollment,target=/tmp/enrollment \ - mkdir -p /keys && \ - cp -r /tmp/enrollment/* /keys/ - -RUN --mount=type=secret,id=private-keys,target=/tmp/private-keys \ - cp -r /tmp/private-keys/* /keys/ - -RUN --mount=type=secret,id=public-keys,target=/tmp/public-keys \ - cp -r /tmp/public-keys/* /keys/ +COPY secure-boot/enrollment/ secure-boot/private-keys/ secure-boot/public-keys/ /keys/ RUN mkdir -p /output -RUN /usr/bin/auroraboot build-uki \ +RUN /usr/bin/auroraboot --debug build-uki \ --output-dir /output \ --keys /keys \ --output-type container \ diff --git a/dockerfiles/Dockerfile.uki-genkey b/dockerfiles/Dockerfile.uki-genkey index ffcabb1a..22f5c42b 100644 --- a/dockerfiles/Dockerfile.uki-genkey +++ b/dockerfiles/Dockerfile.uki-genkey @@ -58,7 +58,7 @@ RUN if [ "$UKI_BRING_YOUR_OWN_KEYS" != "true" ]; then \ fi; \ fi -FROM scratch as output +FROM scratch AS output COPY --from=builder /keys/ /enrollment/ COPY --from=builder /private-keys/ /private-keys/ From 7010044758492f16fae79dec68f42f396098b896 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Wed, 19 Nov 2025 11:58:47 +0000 Subject: [PATCH 23/40] fix for PUSH flag --- Makefile | 4 ++-- docker-bake.hcl | 1 + dockerfiles/Dockerfile.trustedboot-image | 4 +++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 1ec9a667..23d27dfa 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ export # ============================================================================== -# PHONY TARGETS +# TARGETS # ============================================================================== .PHONY: build build-all-images base-image iso build-provider-images iso-disk-image \ uki-genkey alpine-all validate-user-data help @@ -42,7 +42,7 @@ ALL_K8S_VERSIONS = $(if $(strip $(K8S_VERSION)),\ $(shell jq -r --arg key "$(K8S_DISTRIBUTION)" 'if .[$$key] then .[$$key][] else empty end' k8s_version.json)) # Common BAKE_ARGS for pushing images -PUSH_ARGS = $(if $(filter true,$(PUSH)),--set *.output=type=image,push=$(PUSH),) +PUSH_ARGS = $(if $(filter true,$(PUSH)),--set *.output=type=image$(comma)push=$(PUSH),) # ============================================================================== # CORE BUILD TARGET diff --git a/docker-bake.hcl b/docker-bake.hcl index 1a9f81e6..540c97ac 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -398,6 +398,7 @@ target "trustedboot-image" { } args = { AURORABOOT_IMAGE = AURORABOOT_IMAGE + DEBUG = DEBUG } output = ["type=local,dest=./trusted-boot/"] } diff --git a/dockerfiles/Dockerfile.trustedboot-image b/dockerfiles/Dockerfile.trustedboot-image index 6b7e4e25..ccd0b0ab 100644 --- a/dockerfiles/Dockerfile.trustedboot-image +++ b/dockerfiles/Dockerfile.trustedboot-image @@ -11,7 +11,9 @@ COPY secure-boot/enrollment/ secure-boot/private-keys/ secure-boot/public-keys/ RUN mkdir -p /output -RUN /usr/bin/auroraboot --debug build-uki \ +RUN /usr/bin/auroraboot \ + $([ "$DEBUG" = "true" ] && echo "--debug") \ + build-uki \ --output-dir /output \ --keys /keys \ --output-type container \ From a9ff3a8b16ccb56a8e226a7da917d277dc521fc5 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Mon, 24 Nov 2025 09:58:50 +0000 Subject: [PATCH 24/40] bump kairos version to v3.5.8 --- .github/workflows/base-images.yaml | 2 +- Makefile | 22 +++++++++++++------ docker-bake-kairosify.hcl | 2 +- docker-bake.hcl | 5 ++--- rhel-core-images/Dockerfile.rhel8 | 2 +- rhel-core-images/Dockerfile.rhel8.sat | 2 +- rhel-core-images/Dockerfile.rhel9 | 2 +- rhel-core-images/Dockerfile.rhel9.sat | 2 +- rhel-fips/Dockerfile.rhel8 | 2 +- rhel-fips/Dockerfile.rhel9 | 2 +- slem/Dockerfile | 2 +- ubuntu-fips/20.04/Dockerfile | 2 +- ubuntu-fips/20.04/build.sh | 2 +- ubuntu-fips/22.04/Dockerfile.ubuntu22.04-fips | 2 +- 14 files changed, 29 insertions(+), 22 deletions(-) diff --git a/.github/workflows/base-images.yaml b/.github/workflows/base-images.yaml index 45790240..dad0f38c 100644 --- a/.github/workflows/base-images.yaml +++ b/.github/workflows/base-images.yaml @@ -30,7 +30,7 @@ on: description: "Kairos Version" required: false type: string - default: "v3.5.3" + default: "v3.5.8" trusted_boot: description: "Trusted Boot" required: false diff --git a/Makefile b/Makefile index 23d27dfa..19eb3797 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,16 @@ space := $(empty) $(empty) PUSH ?= true DEBUG ?= false NO_CACHE ?= false +DRY_RUN ?= false + +# Common Configuration expressions for building targets +PUSH_ARGS = $(if $(filter true,$(PUSH)),--set *.output=type=image$(comma)push=$(PUSH),) +# Dry run flag +DRY_RUN_ARGS = $(if $(filter true,$(DRY_RUN)),--print,) +# Progress output flag +DOCKER_BUILD_OUT = $(if $(filter true,$(DEBUG)),--progress=plain,) +# No cache flag +DOCKER_NO_CACHE = $(if $(filter true,$(NO_CACHE)),--no-cache,) # ============================================================================== # COMPUTED VARIABLES @@ -30,26 +40,20 @@ NO_CACHE ?= false PROVIDER_TARGET_TYPE = $(if $(filter true,$(IS_UKI)),uki-provider-image,provider-image) ISO_TARGET_TYPE = $(if $(filter true,$(IS_UKI)),build-uki-iso,build-iso) -# Docker buildx progress output -DOCKER_BUILD_OUT = $(if $(filter true,$(DEBUG)),--progress=plain,) -# Docker buildx no-cache flag -DOCKER_NO_CACHE = $(if $(filter true,$(NO_CACHE)),--no-cache,) # K8S versions: either from K8S_VERSION (comma-separated) or k8s_version.json ALL_K8S_VERSIONS = $(if $(strip $(K8S_VERSION)),\ $(subst $(comma),$(space),$(K8S_VERSION)),\ $(shell jq -r --arg key "$(K8S_DISTRIBUTION)" 'if .[$$key] then .[$$key][] else empty end' k8s_version.json)) -# Common BAKE_ARGS for pushing images -PUSH_ARGS = $(if $(filter true,$(PUSH)),--set *.output=type=image$(comma)push=$(PUSH),) # ============================================================================== # CORE BUILD TARGET # ============================================================================== build: @$(if $(BAKE_ENV),env $(BAKE_ENV)) \ - docker buildx bake ${DOCKER_BUILD_OUT} ${DOCKER_NO_CACHE} ${TARGET} $(BAKE_ARGS) + docker buildx bake ${DRY_RUN_ARGS} ${DOCKER_BUILD_OUT} ${DOCKER_NO_CACHE} ${TARGET} $(BAKE_ARGS) # ============================================================================== # MAIN BUILD TARGETS @@ -71,6 +75,10 @@ iso-disk-image: build-provider-images: .check-provider-prereqs $(addprefix .build-provider-image-,$(strip $(ALL_K8S_VERSIONS))) @echo "All provider images built successfully" +# ============================================================================== +# PROVIDER IMAGE BUILD TARGETS (INTERNAL) +# ============================================================================== + .build-provider-image-%: .check-provider-prereqs @echo "Building provider image for k8s version: $*" $(MAKE) TARGET=$(PROVIDER_TARGET_TYPE) \ diff --git a/docker-bake-kairosify.hcl b/docker-bake-kairosify.hcl index 8b2f4ead..544494cc 100644 --- a/docker-bake-kairosify.hcl +++ b/docker-bake-kairosify.hcl @@ -15,7 +15,7 @@ variable "MODEL" { } variable "KAIROS_VERSION" { - default = "v3.5.3" + default = "v3.5.8" } variable "TRUSTED_BOOT" { diff --git a/docker-bake.hcl b/docker-bake.hcl index 540c97ac..eb4e8c25 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -8,7 +8,6 @@ variable "ARCH" { } variable "SPECTRO_PUB_REPO" { - # default = FIPS_ENABLED ? "us-east1-docker.pkg.dev/spectro-images-fips/dev/piyush" : "us-east1-docker.pkg.dev/spectro-images/dev/piyush" default = FIPS_ENABLED ? "us-east1-docker.pkg.dev/spectro-images/dev-fips/arun" : "us-east1-docker.pkg.dev/spectro-images/dev/arun" } @@ -38,11 +37,11 @@ variable "PE_VERSION" { } variable "KAIROS_VERSION" { - default = "v3.5.3" + default = "v3.5.8" } variable AURORABOOT_IMAGE { - default = "quay.io/kairos/auroraboot:v0.8.7" + default = "quay.io/kairos/auroraboot:v0.14.0" } variable "K3S_PROVIDER_VERSION" { diff --git a/rhel-core-images/Dockerfile.rhel8 b/rhel-core-images/Dockerfile.rhel8 index 3a0a06d9..7bd01ad9 100644 --- a/rhel-core-images/Dockerfile.rhel8 +++ b/rhel-core-images/Dockerfile.rhel8 @@ -3,7 +3,7 @@ FROM registry.access.redhat.com/ubi8/ubi-init:8.7-10 ARG USERNAME ARG PASSWORD -ARG KAIROS_VERSION=v3.5.3 +ARG KAIROS_VERSION=v3.5.8 RUN dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm -y # Subscription manager in redhat does not run directly in containers unless you run on a redhat host, hence we remove the rhsm-host, login to the redhat subscription and add the repos diff --git a/rhel-core-images/Dockerfile.rhel8.sat b/rhel-core-images/Dockerfile.rhel8.sat index d2963dda..2cf341f2 100644 --- a/rhel-core-images/Dockerfile.rhel8.sat +++ b/rhel-core-images/Dockerfile.rhel8.sat @@ -8,7 +8,7 @@ FROM $BASE_IMAGE ARG ORGNAME ARG KEYNAME ARG SATHOSTNAME -ARG KAIROS_VERSION=v3.5.3 +ARG KAIROS_VERSION=v3.5.8 RUN dnf config-manager --disable ubi-8-appstream-rpms ubi-8-baseos-rpms ubi-8-codeready-builder-rpms RUN rm /etc/rhsm-host diff --git a/rhel-core-images/Dockerfile.rhel9 b/rhel-core-images/Dockerfile.rhel9 index a01b2eb3..599bb880 100644 --- a/rhel-core-images/Dockerfile.rhel9 +++ b/rhel-core-images/Dockerfile.rhel9 @@ -3,7 +3,7 @@ FROM registry.access.redhat.com/ubi9-init:9.4-6 ARG USERNAME ARG PASSWORD -ARG KAIROS_VERSION=v3.5.3 +ARG KAIROS_VERSION=v3.5.8 RUN dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm -y # Subscription manager in redhat does not run directly in containers unless you run on a redhat host, hence we remove the rhsm-host, login to the redhat subscription and add the repos diff --git a/rhel-core-images/Dockerfile.rhel9.sat b/rhel-core-images/Dockerfile.rhel9.sat index a43145da..f52e8b29 100644 --- a/rhel-core-images/Dockerfile.rhel9.sat +++ b/rhel-core-images/Dockerfile.rhel9.sat @@ -8,7 +8,7 @@ FROM $BASE_IMAGE ARG ORGNAME ARG KEYNAME ARG SATHOSTNAME -ARG KAIROS_VERSION=v3.5.3 +ARG KAIROS_VERSION=v3.5.8 RUN dnf config-manager --disable ubi-9-appstream-rpms ubi-9-baseos-rpms ubi-9-codeready-builder-rpms RUN rm /etc/rhsm-host diff --git a/rhel-fips/Dockerfile.rhel8 b/rhel-fips/Dockerfile.rhel8 index f4142847..39d6f479 100644 --- a/rhel-fips/Dockerfile.rhel8 +++ b/rhel-fips/Dockerfile.rhel8 @@ -7,7 +7,7 @@ ARG USERNAME ARG PASSWORD # Generate os-release file -ARG KAIROS_VERSION=v3.5.3 +ARG KAIROS_VERSION=v3.5.8 # Don't get asked while running apt commands ENV DEBIAN_FRONTEND=noninteractive diff --git a/rhel-fips/Dockerfile.rhel9 b/rhel-fips/Dockerfile.rhel9 index 244fd2d4..9a154997 100644 --- a/rhel-fips/Dockerfile.rhel9 +++ b/rhel-fips/Dockerfile.rhel9 @@ -7,7 +7,7 @@ ARG USERNAME ARG PASSWORD # Generate os-release file -ARG KAIROS_VERSION=v3.5.3 +ARG KAIROS_VERSION=v3.5.8 # Don't get asked while running apt commands ENV DEBIAN_FRONTEND=noninteractive diff --git a/slem/Dockerfile b/slem/Dockerfile index c35cb2ed..14b36465 100644 --- a/slem/Dockerfile +++ b/slem/Dockerfile @@ -9,7 +9,7 @@ RUN zypper --gpg-auto-import-keys ref ADD repos/opensuse* /etc/zypp/repos.d/ RUN zypper --gpg-auto-import-keys ref -ARG KAIROS_VERSION=v3.5.3 +ARG KAIROS_VERSION=v3.5.8 COPY --from=kairos-init /kairos-init /kairos-init RUN zypper -n in \ diff --git a/ubuntu-fips/20.04/Dockerfile b/ubuntu-fips/20.04/Dockerfile index 73061fad..64061941 100644 --- a/ubuntu-fips/20.04/Dockerfile +++ b/ubuntu-fips/20.04/Dockerfile @@ -5,7 +5,7 @@ FROM quay.io/kairos/kairos-init:v0.5.20 AS kairos-init # Base ubuntu image (focal) FROM ubuntu:focal AS base -ARG KAIROS_VERSION=v3.5.3 +ARG KAIROS_VERSION=v3.5.8 # Don't get asked while running apt commands ENV DEBIAN_FRONTEND=noninteractive diff --git a/ubuntu-fips/20.04/build.sh b/ubuntu-fips/20.04/build.sh index ed577966..38e31411 100755 --- a/ubuntu-fips/20.04/build.sh +++ b/ubuntu-fips/20.04/build.sh @@ -1,3 +1,3 @@ BASE_IMAGE="${1:-ubuntu-focal-fips}" -DOCKER_BUILDKIT=1 docker build . --no-cache --secret id=pro-attach-config,src=pro-attach-config.yaml -t "$BASE_IMAGE" \ No newline at end of file +DOCKER_BUILDKIT=1 docker build . --secret id=pro-attach-config,src=pro-attach-config.yaml -t "$BASE_IMAGE" \ No newline at end of file diff --git a/ubuntu-fips/22.04/Dockerfile.ubuntu22.04-fips b/ubuntu-fips/22.04/Dockerfile.ubuntu22.04-fips index 6178dd87..6f8d97a1 100644 --- a/ubuntu-fips/22.04/Dockerfile.ubuntu22.04-fips +++ b/ubuntu-fips/22.04/Dockerfile.ubuntu22.04-fips @@ -1,7 +1,7 @@ FROM quay.io/kairos/kairos-init:v0.5.20 AS kairos-init FROM ubuntu:22.04 -ARG VERSION=v3.5.3 +ARG VERSION=v3.5.8 RUN --mount=type=bind,from=kairos-init,src=/kairos-init,dst=/kairos-init \ /kairos-init -l debug -s install --version "${VERSION}" From 12837ccc5fc4951391af5e227605e918fd2069f5 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Mon, 24 Nov 2025 11:11:16 +0000 Subject: [PATCH 25/40] bump PE version --- docker-bake.hcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-bake.hcl b/docker-bake.hcl index eb4e8c25..eda2cdaa 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -33,7 +33,7 @@ variable "SPECTRO_LUET_REPO" { variable "PE_VERSION" { - default = "v4.7.16" + default = "v4.8.1" } variable "KAIROS_VERSION" { From d220c2aef5e4a6c3ae3cffc476e7e8edf18bdd50 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Mon, 24 Nov 2025 13:35:16 +0000 Subject: [PATCH 26/40] bump kairos-init version --- .github/workflows/base-images.yaml | 2 +- docker-bake-kairosify.hcl | 2 +- rhel-core-images/Dockerfile.rhel8 | 2 +- rhel-core-images/Dockerfile.rhel8.sat | 2 +- rhel-core-images/Dockerfile.rhel9 | 2 +- rhel-core-images/Dockerfile.rhel9.sat | 2 +- rhel-fips/Dockerfile.rhel8 | 2 +- rhel-fips/Dockerfile.rhel9 | 2 +- slem/Dockerfile | 2 +- ubuntu-fips/20.04/Dockerfile | 2 +- ubuntu-fips/22.04/Dockerfile.ubuntu22.04-fips | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/base-images.yaml b/.github/workflows/base-images.yaml index dad0f38c..e1451cf3 100644 --- a/.github/workflows/base-images.yaml +++ b/.github/workflows/base-images.yaml @@ -12,7 +12,7 @@ on: description: "Kairos Init Image" required: false type: string - default: "quay.io/kairos/kairos-init:v0.5.20" + default: "quay.io/kairos/kairos-init:v0.5.27" arch: description: "Architecture" required: false diff --git a/docker-bake-kairosify.hcl b/docker-bake-kairosify.hcl index 544494cc..b97527d8 100644 --- a/docker-bake-kairosify.hcl +++ b/docker-bake-kairosify.hcl @@ -1,5 +1,5 @@ variable "KAIROS_INIT_IMAGE" { - default = "quay.io/kairos/kairos-init:v0.5.20" + default = "quay.io/kairos/kairos-init:v0.5.27" } variable "ARCH" { diff --git a/rhel-core-images/Dockerfile.rhel8 b/rhel-core-images/Dockerfile.rhel8 index 7bd01ad9..7f3bf96a 100644 --- a/rhel-core-images/Dockerfile.rhel8 +++ b/rhel-core-images/Dockerfile.rhel8 @@ -1,4 +1,4 @@ -FROM quay.io/kairos/kairos-init:v0.5.20 AS kairos-init +FROM quay.io/kairos/kairos-init:v0.5.27 AS kairos-init FROM registry.access.redhat.com/ubi8/ubi-init:8.7-10 ARG USERNAME diff --git a/rhel-core-images/Dockerfile.rhel8.sat b/rhel-core-images/Dockerfile.rhel8.sat index 2cf341f2..21855647 100644 --- a/rhel-core-images/Dockerfile.rhel8.sat +++ b/rhel-core-images/Dockerfile.rhel8.sat @@ -1,5 +1,5 @@ ARG BASE_IMAGE=registry.access.redhat.com/ubi8/ubi-init:8.7-10 -ARG KAIROS_INIT_IMAGE=quay.io/kairos/kairos-init:v0.5.20 +ARG KAIROS_INIT_IMAGE=quay.io/kairos/kairos-init:v0.5.27 FROM $KAIROS_INIT_IMAGE as kairos-init diff --git a/rhel-core-images/Dockerfile.rhel9 b/rhel-core-images/Dockerfile.rhel9 index 599bb880..d691a8a0 100644 --- a/rhel-core-images/Dockerfile.rhel9 +++ b/rhel-core-images/Dockerfile.rhel9 @@ -1,4 +1,4 @@ -FROM quay.io/kairos/kairos-init:v0.5.20 AS kairos-init +FROM quay.io/kairos/kairos-init:v0.5.27 AS kairos-init FROM registry.access.redhat.com/ubi9-init:9.4-6 ARG USERNAME diff --git a/rhel-core-images/Dockerfile.rhel9.sat b/rhel-core-images/Dockerfile.rhel9.sat index f52e8b29..3bd6ee04 100644 --- a/rhel-core-images/Dockerfile.rhel9.sat +++ b/rhel-core-images/Dockerfile.rhel9.sat @@ -1,5 +1,5 @@ ARG BASE_IMAGE=registry.access.redhat.com/ubi9-init:9.4-6 -ARG KAIROS_INIT_IMAGE=quay.io/kairos/kairos-init:v0.5.20 +ARG KAIROS_INIT_IMAGE=quay.io/kairos/kairos-init:v0.5.27 FROM $KAIROS_INIT_IMAGE as kairos-init diff --git a/rhel-fips/Dockerfile.rhel8 b/rhel-fips/Dockerfile.rhel8 index 39d6f479..26b5f975 100644 --- a/rhel-fips/Dockerfile.rhel8 +++ b/rhel-fips/Dockerfile.rhel8 @@ -1,5 +1,5 @@ # Kairos init image -FROM quay.io/kairos/kairos-init:v0.5.20 AS kairos-init +FROM quay.io/kairos/kairos-init:v0.5.27 AS kairos-init FROM registry.access.redhat.com/ubi8/ubi-init:8.7-10 as base diff --git a/rhel-fips/Dockerfile.rhel9 b/rhel-fips/Dockerfile.rhel9 index 9a154997..aeb923dc 100644 --- a/rhel-fips/Dockerfile.rhel9 +++ b/rhel-fips/Dockerfile.rhel9 @@ -1,5 +1,5 @@ # Kairos init image -FROM quay.io/kairos/kairos-init:v0.5.20 AS kairos-init +FROM quay.io/kairos/kairos-init:v0.5.27 AS kairos-init FROM registry.access.redhat.com/ubi9-init:9.4-6 as base diff --git a/slem/Dockerfile b/slem/Dockerfile index 14b36465..bb555036 100644 --- a/slem/Dockerfile +++ b/slem/Dockerfile @@ -1,4 +1,4 @@ -FROM quay.io/kairos/kairos-init:v0.5.20 AS kairos-init +FROM quay.io/kairos/kairos-init:v0.5.27 AS kairos-init FROM registry.suse.com/suse/sle-micro-rancher/5.4:latest diff --git a/ubuntu-fips/20.04/Dockerfile b/ubuntu-fips/20.04/Dockerfile index 64061941..48ed68a1 100644 --- a/ubuntu-fips/20.04/Dockerfile +++ b/ubuntu-fips/20.04/Dockerfile @@ -1,6 +1,6 @@ # Kairos init image -FROM quay.io/kairos/kairos-init:v0.5.20 AS kairos-init +FROM quay.io/kairos/kairos-init:v0.5.27 AS kairos-init # Base ubuntu image (focal) FROM ubuntu:focal AS base diff --git a/ubuntu-fips/22.04/Dockerfile.ubuntu22.04-fips b/ubuntu-fips/22.04/Dockerfile.ubuntu22.04-fips index 6f8d97a1..3613df58 100644 --- a/ubuntu-fips/22.04/Dockerfile.ubuntu22.04-fips +++ b/ubuntu-fips/22.04/Dockerfile.ubuntu22.04-fips @@ -1,4 +1,4 @@ -FROM quay.io/kairos/kairos-init:v0.5.20 AS kairos-init +FROM quay.io/kairos/kairos-init:v0.5.27 AS kairos-init FROM ubuntu:22.04 ARG VERSION=v3.5.8 From 1b2671817bacdc211b223486ea204469cb76f5a0 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Tue, 25 Nov 2025 10:42:00 +0000 Subject: [PATCH 27/40] bumo kairos version to 3.5.9 and kairos init to 0.5.28 --- .github/workflows/base-images.yaml | 4 ++-- Earthfile | 2 +- docker-bake-kairosify.hcl | 4 ++-- docker-bake.hcl | 2 +- rhel-core-images/Dockerfile.rhel8 | 4 ++-- rhel-core-images/Dockerfile.rhel8.sat | 4 ++-- rhel-core-images/Dockerfile.rhel9 | 4 ++-- rhel-core-images/Dockerfile.rhel9.sat | 4 ++-- rhel-fips/Dockerfile.rhel8 | 4 ++-- rhel-fips/Dockerfile.rhel9 | 4 ++-- slem/Dockerfile | 4 ++-- ubuntu-fips/20.04/Dockerfile | 4 ++-- ubuntu-fips/22.04/Dockerfile.ubuntu22.04-fips | 4 ++-- 13 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/base-images.yaml b/.github/workflows/base-images.yaml index e1451cf3..53f8a652 100644 --- a/.github/workflows/base-images.yaml +++ b/.github/workflows/base-images.yaml @@ -12,7 +12,7 @@ on: description: "Kairos Init Image" required: false type: string - default: "quay.io/kairos/kairos-init:v0.5.27" + default: "quay.io/kairos/kairos-init:v0.5.28" arch: description: "Architecture" required: false @@ -30,7 +30,7 @@ on: description: "Kairos Version" required: false type: string - default: "v3.5.8" + default: "v3.5.9" trusted_boot: description: "Trusted Boot" required: false diff --git a/Earthfile b/Earthfile index 723c2eee..85b2e202 100644 --- a/Earthfile +++ b/Earthfile @@ -20,7 +20,7 @@ ARG KAIROS_BASE_IMAGE_URL=$SPECTRO_PUB_REPO/edge # Spectro Cloud and Kairos tags. ARG PE_VERSION=v4.7.16 -ARG KAIROS_VERSION=v3.5.3 +ARG KAIROS_VERSION=v3.5.9 ARG K3S_FLAVOR_TAG=k3s1 ARG RKE2_FLAVOR_TAG=rke2r1 ARG BASE_IMAGE_URL=quay.io/kairos diff --git a/docker-bake-kairosify.hcl b/docker-bake-kairosify.hcl index b97527d8..7fe0b9d6 100644 --- a/docker-bake-kairosify.hcl +++ b/docker-bake-kairosify.hcl @@ -1,5 +1,5 @@ variable "KAIROS_INIT_IMAGE" { - default = "quay.io/kairos/kairos-init:v0.5.27" + default = "quay.io/kairos/kairos-init:v0.5.28" } variable "ARCH" { @@ -15,7 +15,7 @@ variable "MODEL" { } variable "KAIROS_VERSION" { - default = "v3.5.8" + default = "v3.5.9" } variable "TRUSTED_BOOT" { diff --git a/docker-bake.hcl b/docker-bake.hcl index eda2cdaa..1352e781 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -37,7 +37,7 @@ variable "PE_VERSION" { } variable "KAIROS_VERSION" { - default = "v3.5.8" + default = "v3.5.9" } variable AURORABOOT_IMAGE { diff --git a/rhel-core-images/Dockerfile.rhel8 b/rhel-core-images/Dockerfile.rhel8 index 7f3bf96a..541f1e7e 100644 --- a/rhel-core-images/Dockerfile.rhel8 +++ b/rhel-core-images/Dockerfile.rhel8 @@ -1,9 +1,9 @@ -FROM quay.io/kairos/kairos-init:v0.5.27 AS kairos-init +FROM quay.io/kairos/kairos-init:v0.5.28 AS kairos-init FROM registry.access.redhat.com/ubi8/ubi-init:8.7-10 ARG USERNAME ARG PASSWORD -ARG KAIROS_VERSION=v3.5.8 +ARG KAIROS_VERSION=v3.5.9 RUN dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm -y # Subscription manager in redhat does not run directly in containers unless you run on a redhat host, hence we remove the rhsm-host, login to the redhat subscription and add the repos diff --git a/rhel-core-images/Dockerfile.rhel8.sat b/rhel-core-images/Dockerfile.rhel8.sat index 21855647..1d8f567f 100644 --- a/rhel-core-images/Dockerfile.rhel8.sat +++ b/rhel-core-images/Dockerfile.rhel8.sat @@ -1,5 +1,5 @@ ARG BASE_IMAGE=registry.access.redhat.com/ubi8/ubi-init:8.7-10 -ARG KAIROS_INIT_IMAGE=quay.io/kairos/kairos-init:v0.5.27 +ARG KAIROS_INIT_IMAGE=quay.io/kairos/kairos-init:v0.5.28 FROM $KAIROS_INIT_IMAGE as kairos-init @@ -8,7 +8,7 @@ FROM $BASE_IMAGE ARG ORGNAME ARG KEYNAME ARG SATHOSTNAME -ARG KAIROS_VERSION=v3.5.8 +ARG KAIROS_VERSION=v3.5.9 RUN dnf config-manager --disable ubi-8-appstream-rpms ubi-8-baseos-rpms ubi-8-codeready-builder-rpms RUN rm /etc/rhsm-host diff --git a/rhel-core-images/Dockerfile.rhel9 b/rhel-core-images/Dockerfile.rhel9 index d691a8a0..22155362 100644 --- a/rhel-core-images/Dockerfile.rhel9 +++ b/rhel-core-images/Dockerfile.rhel9 @@ -1,9 +1,9 @@ -FROM quay.io/kairos/kairos-init:v0.5.27 AS kairos-init +FROM quay.io/kairos/kairos-init:v0.5.28 AS kairos-init FROM registry.access.redhat.com/ubi9-init:9.4-6 ARG USERNAME ARG PASSWORD -ARG KAIROS_VERSION=v3.5.8 +ARG KAIROS_VERSION=v3.5.9 RUN dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm -y # Subscription manager in redhat does not run directly in containers unless you run on a redhat host, hence we remove the rhsm-host, login to the redhat subscription and add the repos diff --git a/rhel-core-images/Dockerfile.rhel9.sat b/rhel-core-images/Dockerfile.rhel9.sat index 3bd6ee04..7ccf6889 100644 --- a/rhel-core-images/Dockerfile.rhel9.sat +++ b/rhel-core-images/Dockerfile.rhel9.sat @@ -1,5 +1,5 @@ ARG BASE_IMAGE=registry.access.redhat.com/ubi9-init:9.4-6 -ARG KAIROS_INIT_IMAGE=quay.io/kairos/kairos-init:v0.5.27 +ARG KAIROS_INIT_IMAGE=quay.io/kairos/kairos-init:v0.5.28 FROM $KAIROS_INIT_IMAGE as kairos-init @@ -8,7 +8,7 @@ FROM $BASE_IMAGE ARG ORGNAME ARG KEYNAME ARG SATHOSTNAME -ARG KAIROS_VERSION=v3.5.8 +ARG KAIROS_VERSION=v3.5.9 RUN dnf config-manager --disable ubi-9-appstream-rpms ubi-9-baseos-rpms ubi-9-codeready-builder-rpms RUN rm /etc/rhsm-host diff --git a/rhel-fips/Dockerfile.rhel8 b/rhel-fips/Dockerfile.rhel8 index 26b5f975..3a96bc55 100644 --- a/rhel-fips/Dockerfile.rhel8 +++ b/rhel-fips/Dockerfile.rhel8 @@ -1,5 +1,5 @@ # Kairos init image -FROM quay.io/kairos/kairos-init:v0.5.27 AS kairos-init +FROM quay.io/kairos/kairos-init:v0.5.28 AS kairos-init FROM registry.access.redhat.com/ubi8/ubi-init:8.7-10 as base @@ -7,7 +7,7 @@ ARG USERNAME ARG PASSWORD # Generate os-release file -ARG KAIROS_VERSION=v3.5.8 +ARG KAIROS_VERSION=v3.5.9 # Don't get asked while running apt commands ENV DEBIAN_FRONTEND=noninteractive diff --git a/rhel-fips/Dockerfile.rhel9 b/rhel-fips/Dockerfile.rhel9 index aeb923dc..29641f11 100644 --- a/rhel-fips/Dockerfile.rhel9 +++ b/rhel-fips/Dockerfile.rhel9 @@ -1,5 +1,5 @@ # Kairos init image -FROM quay.io/kairos/kairos-init:v0.5.27 AS kairos-init +FROM quay.io/kairos/kairos-init:v0.5.28 AS kairos-init FROM registry.access.redhat.com/ubi9-init:9.4-6 as base @@ -7,7 +7,7 @@ ARG USERNAME ARG PASSWORD # Generate os-release file -ARG KAIROS_VERSION=v3.5.8 +ARG KAIROS_VERSION=v3.5.9 # Don't get asked while running apt commands ENV DEBIAN_FRONTEND=noninteractive diff --git a/slem/Dockerfile b/slem/Dockerfile index bb555036..214f0ae1 100644 --- a/slem/Dockerfile +++ b/slem/Dockerfile @@ -1,4 +1,4 @@ -FROM quay.io/kairos/kairos-init:v0.5.27 AS kairos-init +FROM quay.io/kairos/kairos-init:v0.5.28 AS kairos-init FROM registry.suse.com/suse/sle-micro-rancher/5.4:latest @@ -9,7 +9,7 @@ RUN zypper --gpg-auto-import-keys ref ADD repos/opensuse* /etc/zypp/repos.d/ RUN zypper --gpg-auto-import-keys ref -ARG KAIROS_VERSION=v3.5.8 +ARG KAIROS_VERSION=v3.5.9 COPY --from=kairos-init /kairos-init /kairos-init RUN zypper -n in \ diff --git a/ubuntu-fips/20.04/Dockerfile b/ubuntu-fips/20.04/Dockerfile index 48ed68a1..7d85ec93 100644 --- a/ubuntu-fips/20.04/Dockerfile +++ b/ubuntu-fips/20.04/Dockerfile @@ -1,11 +1,11 @@ # Kairos init image -FROM quay.io/kairos/kairos-init:v0.5.27 AS kairos-init +FROM quay.io/kairos/kairos-init:v0.5.28 AS kairos-init # Base ubuntu image (focal) FROM ubuntu:focal AS base -ARG KAIROS_VERSION=v3.5.8 +ARG KAIROS_VERSION=v3.5.9 # Don't get asked while running apt commands ENV DEBIAN_FRONTEND=noninteractive diff --git a/ubuntu-fips/22.04/Dockerfile.ubuntu22.04-fips b/ubuntu-fips/22.04/Dockerfile.ubuntu22.04-fips index 3613df58..19742c1f 100644 --- a/ubuntu-fips/22.04/Dockerfile.ubuntu22.04-fips +++ b/ubuntu-fips/22.04/Dockerfile.ubuntu22.04-fips @@ -1,7 +1,7 @@ -FROM quay.io/kairos/kairos-init:v0.5.27 AS kairos-init +FROM quay.io/kairos/kairos-init:v0.5.28 AS kairos-init FROM ubuntu:22.04 -ARG VERSION=v3.5.8 +ARG VERSION=v3.5.9 RUN --mount=type=bind,from=kairos-init,src=/kairos-init,dst=/kairos-init \ /kairos-init -l debug -s install --version "${VERSION}" From 254aa2f9d1ddcc55220615b6644caadfbd5738a6 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Thu, 27 Nov 2025 17:37:42 +0530 Subject: [PATCH 28/40] Pe 7789 (#500) * PE-7685: install rsyslog and logrotate in slem (#484) * Change logging to syslog for ubuntu (#493) * Update PE_VERSION to v4.8.1 (#495) * Add FIPS-compliant SSH configuration Create a new configuration file for SSHD that prioritizes higher-performance FIPS algorithms, specifying preferred ciphers, key exchange algorithms, and MACs. * reordering host key Algos for fips --------- Co-authored-by: Zulfihar Ali Ahamed Co-authored-by: Santhosh --- Earthfile | 2 +- .../rhel9/etc/ssh/sshd_config.d/100_fips_crypto.conf | 6 ++++++ ubuntu-fips/22.04/fix.sh | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 rhel-fips/overlay/rhel9/etc/ssh/sshd_config.d/100_fips_crypto.conf diff --git a/Earthfile b/Earthfile index 85b2e202..66ba0c9d 100644 --- a/Earthfile +++ b/Earthfile @@ -19,7 +19,7 @@ ARG SPECTRO_LUET_REPO=us-docker.pkg.dev/palette-images/edge ARG KAIROS_BASE_IMAGE_URL=$SPECTRO_PUB_REPO/edge # Spectro Cloud and Kairos tags. -ARG PE_VERSION=v4.7.16 +ARG PE_VERSION=v4.8.1 ARG KAIROS_VERSION=v3.5.9 ARG K3S_FLAVOR_TAG=k3s1 ARG RKE2_FLAVOR_TAG=rke2r1 diff --git a/rhel-fips/overlay/rhel9/etc/ssh/sshd_config.d/100_fips_crypto.conf b/rhel-fips/overlay/rhel9/etc/ssh/sshd_config.d/100_fips_crypto.conf new file mode 100644 index 00000000..717dc6dd --- /dev/null +++ b/rhel-fips/overlay/rhel9/etc/ssh/sshd_config.d/100_fips_crypto.conf @@ -0,0 +1,6 @@ +# Default algorithms favoring higher-performance FIPS algorithms +# in most cases. +Ciphers ^aes256-gcm@openssh.com,aes256-ctr,aes128-gcm@openssh.com,aes128-ctr +KexAlgorithms ^ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521 +MACs ^hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha2-512 +HostKeyAlgorithms ^ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,rsa-sha2-256,rsa-sha2-512 \ No newline at end of file diff --git a/ubuntu-fips/22.04/fix.sh b/ubuntu-fips/22.04/fix.sh index cfa01a64..93deea46 100755 --- a/ubuntu-fips/22.04/fix.sh +++ b/ubuntu-fips/22.04/fix.sh @@ -2588,7 +2588,7 @@ if ! grep -Erq "^auth\.\*,authpriv\.\*" /etc/rsyslog.*; then fi if ! grep -Erq "^daemon\.\*" /etc/rsyslog.*; then - echo "daemon.* /var/log/messages" >> /etc/rsyslog.d/50-default.conf + echo "daemon.* /var/log/syslog" >> /etc/rsyslog.d/50-default.conf fi systemctl restart rsyslog.service From 4d8d04c3a30f11a1ae047d3ed5400d4c59589464 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Tue, 2 Dec 2025 05:25:35 +0000 Subject: [PATCH 29/40] fix auroraboot flags --- dockerfiles/Dockerfile.build-uki-iso | 5 ++++- dockerfiles/Dockerfile.trustedboot-image | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/dockerfiles/Dockerfile.build-uki-iso b/dockerfiles/Dockerfile.build-uki-iso index 0b938e3c..457f8e13 100644 --- a/dockerfiles/Dockerfile.build-uki-iso +++ b/dockerfiles/Dockerfile.build-uki-iso @@ -61,7 +61,10 @@ RUN if [ "$ARCH" = "amd64" ]; then \ --name "${ISO_NAME}" \ --output-dir /iso \ --overlay-iso /overlay \ - --keys /keys \ + --public-keys /keys \ + --tpm-pcr-private-key /keys/tpm2-pcr-private.pem \ + --sb-key /keys/db.key \ + --sb-cert /keys/db.pem \ --boot-branding "${BRANDING}" \ $([ -n "$CMDLINE" ] && echo "--extend-cmdline \"$CMDLINE\"") \ $([ "$AUTO_ENROLL_SECUREBOOT_KEYS" = "true" ] && echo "--secure-boot-enroll force") \ diff --git a/dockerfiles/Dockerfile.trustedboot-image b/dockerfiles/Dockerfile.trustedboot-image index ccd0b0ab..da311c46 100644 --- a/dockerfiles/Dockerfile.trustedboot-image +++ b/dockerfiles/Dockerfile.trustedboot-image @@ -15,7 +15,10 @@ RUN /usr/bin/auroraboot \ $([ "$DEBUG" = "true" ] && echo "--debug") \ build-uki \ --output-dir /output \ - --keys /keys \ + --public-keys /keys \ + --tpm-pcr-private-key /keys/tpm2-pcr-private.pem \ + --sb-key /keys/db.key \ + --sb-cert /keys/db.pem \ --output-type container \ --boot-branding "Palette eXtended Kubernetes Edge" \ dir:/build/image From 50b827856b50023ba15a84ee2b12abf45d296fed Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Thu, 4 Dec 2025 07:42:11 +0000 Subject: [PATCH 30/40] mount keys and token as secret --- docker-bake.hcl | 22 ++++- dockerfiles/Dockerfile.base-image | 13 +-- dockerfiles/Dockerfile.build-uki-iso | 11 ++- dockerfiles/Dockerfile.trustedboot-image | 31 ++++--- dockerfiles/Dockerfile.uki-byok | 37 ++++++--- dockerfiles/Dockerfile.uki-genkey | 101 ++++++++++++----------- 6 files changed, 132 insertions(+), 83 deletions(-) diff --git a/docker-bake.hcl b/docker-bake.hcl index 1352e781..a9e5d15c 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -177,6 +177,19 @@ variable "EXPIRATION_IN_DAYS" { default = 5475 } +# Secrets for secure boot private keys - used by trustedboot-image and build-uki-iso +variable "SECURE_BOOT_SECRETS" { + default = [ + "id=db_key,src=secure-boot/private-keys/db.key", + "id=db_pem,src=secure-boot/public-keys/db.pem", + "id=kek_key,src=secure-boot/private-keys/KEK.key", + "id=kek_pem,src=secure-boot/public-keys/KEK.pem", + "id=pk_key,src=secure-boot/private-keys/PK.key", + "id=pk_pem,src=secure-boot/public-keys/PK.pem", + "id=tpm2_pcr_private,src=secure-boot/private-keys/tpm2-pcr-private.pem" + ] +} + variable "EFI_MAX_SIZE" { default = "2048" } @@ -279,7 +292,6 @@ target "base-image" { OS_VERSION = OS_VERSION IS_JETSON = IS_JETSON IS_UKI = IS_UKI - UBUNTU_PRO_KEY = UBUNTU_PRO_KEY UPDATE_KERNEL = UPDATE_KERNEL CIS_HARDENING = CIS_HARDENING KAIROS_VERSION = KAIROS_VERSION @@ -287,6 +299,7 @@ target "base-image" { ARCH = ARCH FIPS_ENABLED = FIPS_ENABLED } + secret = ["id=ubuntu_pro_key,env=UBUNTU_PRO_KEY"] } function "get_provider_base" { @@ -399,6 +412,7 @@ target "trustedboot-image" { AURORABOOT_IMAGE = AURORABOOT_IMAGE DEBUG = DEBUG } + secret = SECURE_BOOT_SECRETS output = ["type=local,dest=./trusted-boot/"] } @@ -449,6 +463,7 @@ target "build-iso" { target "build-uki-iso" { dockerfile = "dockerfiles/Dockerfile.build-uki-iso" target = "output" + context = "." platforms = ["linux/${ARCH}"] contexts = { validate-user-data = "target:validate-user-data" @@ -467,6 +482,7 @@ target "build-uki-iso" { CMDLINE = CMDLINE BRANDING = BRANDING } + secret = SECURE_BOOT_SECRETS output = ["type=local,dest=./build/"] } @@ -488,7 +504,7 @@ target "stylus-image-pack" { target "uki-genkey" { dockerfile = "dockerfiles/Dockerfile.uki-genkey" context = "." - target = "output" + target = UKI_BRING_YOUR_OWN_KEYS ? "output-byok" : "output-no-byok" platforms = ["linux/${ARCH}"] contexts = UKI_BRING_YOUR_OWN_KEYS ? { uki-byok = "target:uki-byok" @@ -496,7 +512,6 @@ target "uki-genkey" { args = { MY_ORG = MY_ORG EXPIRATION_IN_DAYS = EXPIRATION_IN_DAYS - UKI_BRING_YOUR_OWN_KEYS = UKI_BRING_YOUR_OWN_KEYS INCLUDE_MS_SECUREBOOT_KEYS = INCLUDE_MS_SECUREBOOT_KEYS AURORABOOT_IMAGE = AURORABOOT_IMAGE ARCH = ARCH @@ -506,6 +521,7 @@ target "uki-genkey" { target "uki-byok" { dockerfile = "dockerfiles/Dockerfile.uki-byok" + context = "." platforms = ["linux/${ARCH}"] args = { UBUNTU_IMAGE = get_ubuntu_image(FIPS_ENABLED, SPECTRO_PUB_REPO) diff --git a/dockerfiles/Dockerfile.base-image b/dockerfiles/Dockerfile.base-image index ad732123..8c215d2a 100644 --- a/dockerfiles/Dockerfile.base-image +++ b/dockerfiles/Dockerfile.base-image @@ -5,7 +5,6 @@ ARG OS_VERSION ARG IS_JETSON ARG IS_UKI -ARG UBUNTU_PRO_KEY ARG UPDATE_KERNEL ARG CIS_HARDENING ARG KAIROS_VERSION @@ -21,12 +20,14 @@ RUN if [ "$IS_UKI" = "true" ]; then \ cp /tmp/build-context/cloudconfigs/80_stylus_uki.yaml /system/oem/80_stylus_uki.yaml; \ fi -RUN if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ]; then \ - if [ ! -z "$UBUNTU_PRO_KEY" ]; then \ +# Use secret for UBUNTU_PRO_KEY - not cached, not stored in image layers +RUN --mount=type=secret,id=ubuntu_pro_key \ + if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ]; then \ + if [ -f /run/secrets/ubuntu_pro_key ] && [ -s /run/secrets/ubuntu_pro_key ]; then \ sed -i '/^[[:space:]]*$/d' /etc/os-release && \ - apt update && \ + apt-get update && \ apt-get install -y snapd && \ - pro attach $UBUNTU_PRO_KEY; \ + pro attach "$(cat /run/secrets/ubuntu_pro_key)"; \ fi && \ \ DEBIAN_FRONTEND=noninteractive apt-get update && \ @@ -90,7 +91,7 @@ RUN if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ]; then \ /tmp/harden.sh && rm /tmp/harden.sh; \ fi && \ \ - if [ ! -z "$UBUNTU_PRO_KEY" ]; then \ + if [ -f /run/secrets/ubuntu_pro_key ] && [ -s /run/secrets/ubuntu_pro_key ]; then \ pro detach --assume-yes; \ fi; \ fi diff --git a/dockerfiles/Dockerfile.build-uki-iso b/dockerfiles/Dockerfile.build-uki-iso index 457f8e13..272e5703 100644 --- a/dockerfiles/Dockerfile.build-uki-iso +++ b/dockerfiles/Dockerfile.build-uki-iso @@ -50,9 +50,16 @@ WORKDIR /build COPY --from=iso-image / /iso-source/ -COPY secure-boot/enrollment/ secure-boot/private-keys/ secure-boot/public-keys/ /keys/ +COPY secure-boot/enrollment/ /keys/ -RUN if [ "$ARCH" = "amd64" ]; then \ +RUN --mount=type=secret,id=db_key,target=/keys/db.key \ + --mount=type=secret,id=db_pem,target=/keys/db.pem \ + --mount=type=secret,id=kek_key,target=/keys/KEK.key \ + --mount=type=secret,id=kek_pem,target=/keys/KEK.pem \ + --mount=type=secret,id=pk_key,target=/keys/PK.key \ + --mount=type=secret,id=pk_pem,target=/keys/PK.pem \ + --mount=type=secret,id=tpm2_pcr_private,target=/keys/tpm2-pcr-private.pem \ + if [ "$ARCH" = "amd64" ]; then \ mkdir -p /iso && \ /usr/bin/auroraboot \ $([ "$DEBUG" = "true" ] && echo "--debug") \ diff --git a/dockerfiles/Dockerfile.trustedboot-image b/dockerfiles/Dockerfile.trustedboot-image index da311c46..70c3f3ec 100644 --- a/dockerfiles/Dockerfile.trustedboot-image +++ b/dockerfiles/Dockerfile.trustedboot-image @@ -7,21 +7,28 @@ FROM ${AURORABOOT_IMAGE} AS builder COPY --from=provider-image-rootfs / /build/image/ -COPY secure-boot/enrollment/ secure-boot/private-keys/ secure-boot/public-keys/ /keys/ +COPY secure-boot/enrollment/ /keys/ RUN mkdir -p /output -RUN /usr/bin/auroraboot \ - $([ "$DEBUG" = "true" ] && echo "--debug") \ - build-uki \ - --output-dir /output \ - --public-keys /keys \ - --tpm-pcr-private-key /keys/tpm2-pcr-private.pem \ - --sb-key /keys/db.key \ - --sb-cert /keys/db.pem \ - --output-type container \ - --boot-branding "Palette eXtended Kubernetes Edge" \ - dir:/build/image +RUN --mount=type=secret,id=db_key,target=/keys/db.key \ + --mount=type=secret,id=db_pem,target=/keys/db.pem \ + --mount=type=secret,id=kek_key,target=/keys/KEK.key \ + --mount=type=secret,id=kek_pem,target=/keys/KEK.pem \ + --mount=type=secret,id=pk_key,target=/keys/PK.key \ + --mount=type=secret,id=pk_pem,target=/keys/PK.pem \ + --mount=type=secret,id=tpm2_pcr_private,target=/keys/tpm2-pcr-private.pem \ + /usr/bin/auroraboot \ + $([ "$DEBUG" = "true" ] && echo "--debug") \ + build-uki \ + --output-dir /output \ + --public-keys /keys \ + --tpm-pcr-private-key /keys/tpm2-pcr-private.pem \ + --sb-key /keys/db.key \ + --sb-cert /keys/db.pem \ + --output-type container \ + --boot-branding "Palette eXtended Kubernetes Edge" \ + dir:/build/image FROM scratch AS output COPY --from=builder /output/ / \ No newline at end of file diff --git a/dockerfiles/Dockerfile.uki-byok b/dockerfiles/Dockerfile.uki-byok index 47628307..ad22cf73 100644 --- a/dockerfiles/Dockerfile.uki-byok +++ b/dockerfiles/Dockerfile.uki-byok @@ -4,25 +4,40 @@ FROM ${UBUNTU_IMAGE} ARG INCLUDE_MS_SECUREBOOT_KEYS=false -RUN apt-get update && apt-get install -y efitools curl -RUN apk add --no-cache curl tar && \ - curl -Ls https://github.com/Foxboron/sbctl/releases/download/0.13/sbctl-0.13-linux-amd64.tar.gz | tar -xvzf - && \ - mv sbctl/sbctl /usr/bin/sbctl +RUN apt-get update && apt-get install -y efitools curl tar ca-certificates && \ + update-ca-certificates -RUN mkdir -p /exported-keys /keys -RUN if [ -d "secure-boot/private-keys" ]; then \ - cp -r secure-boot/private-keys/ /keys/ ; \ +RUN curl -fsSL -o /tmp/sbctl.tar.gz https://github.com/Foxboron/sbctl/releases/download/0.13/sbctl-0.13-linux-amd64.tar.gz && \ + tar -xzf /tmp/sbctl.tar.gz -C /tmp && \ + mv /tmp/sbctl/sbctl /usr/bin/sbctl && \ + chmod +x /usr/bin/sbctl && \ + rm -rf /tmp/sbctl.tar.gz /tmp/sbctl + +RUN mkdir -p /exported-keys /keys /tmp/secure-boot /private-keys /public-keys + +COPY secure-boot/ /tmp/secure-boot + +RUN ls -ltrh /tmp/secure-boot + +# Copy keys from /tmp/secure-boot to their destinations +# Preserve original structure in /private-keys and /public-keys for output +RUN if [ -d "/tmp/secure-boot/private-keys" ]; then \ + cp -r /tmp/secure-boot/private-keys/* /keys/ && \ + cp -r /tmp/secure-boot/private-keys/* /private-keys/; \ fi -RUN if [ -d "secure-boot/public-keys" ]; then \ - cp -r secure-boot/public-keys/* /keys/ ; \ +RUN if [ -d "/tmp/secure-boot/public-keys" ]; then \ + cp -r /tmp/secure-boot/public-keys/* /keys/ && \ + cp -r /tmp/secure-boot/public-keys/* /public-keys/; \ fi -RUN if [ -d "secure-boot/exported-keys" ]; then \ - cp -r secure-boot/exported-keys/* /exported-keys/ ; \ +RUN if [ -d "/tmp/secure-boot/exported-keys" ]; then \ + cp -r /tmp/secure-boot/exported-keys/* /exported-keys/; \ fi +RUN rm -rf /tmp/secure-boot + WORKDIR /keys RUN sbctl import-keys \ diff --git a/dockerfiles/Dockerfile.uki-genkey b/dockerfiles/Dockerfile.uki-genkey index 22f5c42b..7f39f791 100644 --- a/dockerfiles/Dockerfile.uki-genkey +++ b/dockerfiles/Dockerfile.uki-genkey @@ -1,65 +1,68 @@ ARG MY_ORG ARG EXPIRATION_IN_DAYS -ARG UKI_BRING_YOUR_OWN_KEYS ARG INCLUDE_MS_SECUREBOOT_KEYS ARG AURORABOOT_IMAGE ARG ARCH +# Stage 1: Generate keys (used when UKI_BRING_YOUR_OWN_KEYS=false) FROM ${AURORABOOT_IMAGE} AS builder -RUN if [ "$UKI_BRING_YOUR_OWN_KEYS" != "true" ]; then \ - mkdir -p /custom-keys && \ - if [ -d "secure-boot/exported-keys" ]; then \ - cp -r secure-boot/exported-keys/* /custom-keys/ 2>/dev/null || true; \ - fi && \ - \ - if [ "$INCLUDE_MS_SECUREBOOT_KEYS" != "true" ]; then \ - if [[ -f /custom-keys/KEK && -f /custom-keys/db ]]; then \ - echo "Generating Secure Boot keys, including exported UEFI keys..." && \ - /usr/bin/auroraboot genkey \ - "$MY_ORG" \ - --custom-cert-dir /custom-keys \ - --skip-microsoft-certs-I-KNOW-WHAT-IM-DOING \ - --expiration-days $EXPIRATION_IN_DAYS \ - --output /keys; \ - else \ - echo "Generating Secure Boot keys..." && \ - /usr/bin/auroraboot genkey \ - "$MY_ORG" \ - --skip-microsoft-certs-I-KNOW-WHAT-IM-DOING \ - --expiration-days $EXPIRATION_IN_DAYS \ - --output /keys; \ - fi; \ +ARG MY_ORG +ARG EXPIRATION_IN_DAYS +ARG INCLUDE_MS_SECUREBOOT_KEYS + +RUN mkdir -p /custom-keys && \ + if [ -d "secure-boot/exported-keys" ]; then \ + cp -r secure-boot/exported-keys/* /custom-keys/ 2>/dev/null || true; \ + fi && \ + \ + if [ "$INCLUDE_MS_SECUREBOOT_KEYS" != "true" ]; then \ + if [[ -f /custom-keys/KEK && -f /custom-keys/db ]]; then \ + echo "Generating Secure Boot keys, including exported UEFI keys..." && \ + /usr/bin/auroraboot genkey \ + "$MY_ORG" \ + --custom-cert-dir /custom-keys \ + --skip-microsoft-certs-I-KNOW-WHAT-IM-DOING \ + --expiration-days $EXPIRATION_IN_DAYS \ + --output /keys; \ else \ - if [[ -f /custom-keys/KEK && -f /custom-keys/db ]]; then \ - echo "Generating Secure Boot keys, including exported UEFI keys and Microsoft keys..." && \ - /usr/bin/auroraboot genkey \ - "$MY_ORG" \ - --custom-cert-dir /custom-keys \ - --expiration-days $EXPIRATION_IN_DAYS \ - --output /keys; \ - else \ - echo "Generating Secure Boot keys, including Microsoft keys..." && \ - /usr/bin/auroraboot genkey \ - "$MY_ORG" \ - --expiration-days $EXPIRATION_IN_DAYS \ - --output /keys; \ - fi; \ - fi && \ - \ - ls -ltrh /keys && \ - mkdir -p /private-keys /public-keys && \ - cd /keys && mv *.key tpm2-pcr-private.pem /private-keys/ 2>/dev/null || true && \ - cd /keys && mv *.pem /public-keys/ 2>/dev/null || true; \ + echo "Generating Secure Boot keys..." && \ + /usr/bin/auroraboot genkey \ + "$MY_ORG" \ + --skip-microsoft-certs-I-KNOW-WHAT-IM-DOING \ + --expiration-days $EXPIRATION_IN_DAYS \ + --output /keys; \ + fi; \ else \ - mkdir -p /keys && \ - if [ -d "uki-byok" ]; then \ - cp -r uki-byok/* /keys/ 2>/dev/null || true; \ + if [[ -f /custom-keys/KEK && -f /custom-keys/db ]]; then \ + echo "Generating Secure Boot keys, including exported UEFI keys and Microsoft keys..." && \ + /usr/bin/auroraboot genkey \ + "$MY_ORG" \ + --custom-cert-dir /custom-keys \ + --expiration-days $EXPIRATION_IN_DAYS \ + --output /keys; \ + else \ + echo "Generating Secure Boot keys, including Microsoft keys..." && \ + /usr/bin/auroraboot genkey \ + "$MY_ORG" \ + --expiration-days $EXPIRATION_IN_DAYS \ + --output /keys; \ fi; \ - fi + fi && \ + \ + ls -ltrh /keys && \ + mkdir -p /private-keys /public-keys && \ + cd /keys && mv *.key tpm2-pcr-private.pem /private-keys/ 2>/dev/null || true && \ + cd /keys && mv *.pem /public-keys/ 2>/dev/null || true -FROM scratch AS output +# UKI_BRING_YOUR_OWN_KEYS=true - copy all files from uki-byok context +FROM scratch AS output-byok +COPY --from=uki-byok /output/ /enrollment/ +COPY --from=uki-byok /private-keys/ /private-keys/ +COPY --from=uki-byok /public-keys/ /public-keys/ +# UKI_BRING_YOUR_OWN_KEYS=false - use generated keys from builder +FROM scratch AS output-no-byok COPY --from=builder /keys/ /enrollment/ COPY --from=builder /private-keys/ /private-keys/ COPY --from=builder /public-keys/ /public-keys/ \ No newline at end of file From 1d721fcc6c323232fe843e678b78a64445794a8d Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Thu, 4 Dec 2025 12:44:32 +0000 Subject: [PATCH 31/40] cmdline fix --- dockerfiles/Dockerfile.build-uki-iso | 4 ++-- dockerfiles/Dockerfile.iso-image | 5 ++--- dockerfiles/Dockerfile.stylus-image-pack | 2 +- rhel-core-images/Dockerfile.rhel8.sat | 2 +- rhel-core-images/Dockerfile.rhel9.sat | 2 +- rhel-fips/Dockerfile.rhel8 | 2 +- rhel-fips/Dockerfile.rhel9 | 2 +- 7 files changed, 9 insertions(+), 10 deletions(-) diff --git a/dockerfiles/Dockerfile.build-uki-iso b/dockerfiles/Dockerfile.build-uki-iso index 272e5703..5c080fcc 100644 --- a/dockerfiles/Dockerfile.build-uki-iso +++ b/dockerfiles/Dockerfile.build-uki-iso @@ -73,7 +73,7 @@ RUN --mount=type=secret,id=db_key,target=/keys/db.key \ --sb-key /keys/db.key \ --sb-cert /keys/db.pem \ --boot-branding "${BRANDING}" \ - $([ -n "$CMDLINE" ] && echo "--extend-cmdline \"$CMDLINE\"") \ + $([ -n "$CMDLINE" ] && echo "--extend-cmdline $CMDLINE") \ $([ "$AUTO_ENROLL_SECUREBOOT_KEYS" = "true" ] && echo "--secure-boot-enroll force") \ dir:/iso-source; \ fi @@ -81,5 +81,5 @@ RUN --mount=type=secret,id=db_key,target=/keys/db.key \ RUN cd /iso && \ sha256sum "${ISO_NAME}.iso" > "${ISO_NAME}.iso.sha256" -FROM scratch as output +FROM scratch AS output COPY --from=builder /iso/ / \ No newline at end of file diff --git a/dockerfiles/Dockerfile.iso-image b/dockerfiles/Dockerfile.iso-image index 0bdcff5d..aac99e03 100644 --- a/dockerfiles/Dockerfile.iso-image +++ b/dockerfiles/Dockerfile.iso-image @@ -1,9 +1,8 @@ -ARG ARCH +FROM base-image AS iso-image + ARG IS_UKI ARG IS_CLOUD_IMAGE=false -FROM base-image AS iso-image - COPY --from=stylus-image / / RUN if [ "$IS_UKI" = "true" ]; then \ diff --git a/dockerfiles/Dockerfile.stylus-image-pack b/dockerfiles/Dockerfile.stylus-image-pack index c6777425..f03d3c87 100644 --- a/dockerfiles/Dockerfile.stylus-image-pack +++ b/dockerfiles/Dockerfile.stylus-image-pack @@ -14,5 +14,5 @@ RUN cd /stylus && \ tar -czf /stylus.tar * && \ luet util pack "$STYLUS_BASE" /stylus.tar /stylus-image.tar -FROM scratch as output +FROM scratch AS output COPY --from=packer /stylus-image.tar / \ No newline at end of file diff --git a/rhel-core-images/Dockerfile.rhel8.sat b/rhel-core-images/Dockerfile.rhel8.sat index 1d8f567f..715a40c1 100644 --- a/rhel-core-images/Dockerfile.rhel8.sat +++ b/rhel-core-images/Dockerfile.rhel8.sat @@ -1,7 +1,7 @@ ARG BASE_IMAGE=registry.access.redhat.com/ubi8/ubi-init:8.7-10 ARG KAIROS_INIT_IMAGE=quay.io/kairos/kairos-init:v0.5.28 -FROM $KAIROS_INIT_IMAGE as kairos-init +FROM $KAIROS_INIT_IMAGE AS kairos-init FROM $BASE_IMAGE diff --git a/rhel-core-images/Dockerfile.rhel9.sat b/rhel-core-images/Dockerfile.rhel9.sat index 7ccf6889..3923b2a4 100644 --- a/rhel-core-images/Dockerfile.rhel9.sat +++ b/rhel-core-images/Dockerfile.rhel9.sat @@ -1,7 +1,7 @@ ARG BASE_IMAGE=registry.access.redhat.com/ubi9-init:9.4-6 ARG KAIROS_INIT_IMAGE=quay.io/kairos/kairos-init:v0.5.28 -FROM $KAIROS_INIT_IMAGE as kairos-init +FROM $KAIROS_INIT_IMAGE AS kairos-init FROM $BASE_IMAGE diff --git a/rhel-fips/Dockerfile.rhel8 b/rhel-fips/Dockerfile.rhel8 index 3a96bc55..7ad839df 100644 --- a/rhel-fips/Dockerfile.rhel8 +++ b/rhel-fips/Dockerfile.rhel8 @@ -1,7 +1,7 @@ # Kairos init image FROM quay.io/kairos/kairos-init:v0.5.28 AS kairos-init -FROM registry.access.redhat.com/ubi8/ubi-init:8.7-10 as base +FROM registry.access.redhat.com/ubi8/ubi-init:8.7-10 AS base ARG USERNAME ARG PASSWORD diff --git a/rhel-fips/Dockerfile.rhel9 b/rhel-fips/Dockerfile.rhel9 index 29641f11..03503ad5 100644 --- a/rhel-fips/Dockerfile.rhel9 +++ b/rhel-fips/Dockerfile.rhel9 @@ -1,7 +1,7 @@ # Kairos init image FROM quay.io/kairos/kairos-init:v0.5.28 AS kairos-init -FROM registry.access.redhat.com/ubi9-init:9.4-6 as base +FROM registry.access.redhat.com/ubi9-init:9.4-6 AS base ARG USERNAME ARG PASSWORD From 1d27b0dde8ce11f5d330a46389cb589372caab4f Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Tue, 9 Dec 2025 09:34:35 +0000 Subject: [PATCH 32/40] refactor and fixes for cloud image --- Makefile | 40 ++-- docker-bake.hcl | 213 ++++++++++++------- dockerfiles/Dockerfile.alpine | 3 +- dockerfiles/Dockerfile.aws-cloud-image | 63 ++++++ dockerfiles/Dockerfile.base-image | 46 +++- dockerfiles/Dockerfile.build-iso | 35 +-- dockerfiles/Dockerfile.build-uki-iso | 56 ++--- dockerfiles/Dockerfile.cloud-image | 46 ++++ dockerfiles/Dockerfile.install-k8s | 12 +- dockerfiles/Dockerfile.iso-efi-size-check | 45 ++++ dockerfiles/Dockerfile.iso-image | 2 +- dockerfiles/Dockerfile.kairos-provider-image | 3 - dockerfiles/Dockerfile.provider-image | 74 +++++-- dockerfiles/Dockerfile.slink | 15 +- dockerfiles/Dockerfile.stylus-image | 3 - dockerfiles/Dockerfile.uki-byok | 2 - dockerfiles/Dockerfile.uki-genkey | 48 ++--- dockerfiles/Dockerfile.uki-provider-image | 18 +- dockerfiles/Dockerfile.validate-ud | 20 +- 19 files changed, 523 insertions(+), 221 deletions(-) create mode 100644 dockerfiles/Dockerfile.aws-cloud-image create mode 100644 dockerfiles/Dockerfile.cloud-image create mode 100644 dockerfiles/Dockerfile.iso-efi-size-check delete mode 100644 dockerfiles/Dockerfile.kairos-provider-image delete mode 100644 dockerfiles/Dockerfile.stylus-image diff --git a/Makefile b/Makefile index 19eb3797..b7358e49 100644 --- a/Makefile +++ b/Makefile @@ -4,8 +4,8 @@ export # ============================================================================== # TARGETS # ============================================================================== -.PHONY: build build-all-images base-image iso build-provider-images iso-disk-image \ - uki-genkey alpine-all validate-user-data help +.PHONY: build build-all-images iso build-provider-images iso-disk-image \ + uki-genkey alpine-all validate-user-data cloud-image aws-cloud-image help .SILENT: uki-genkey validate-user-data @@ -19,10 +19,10 @@ space := $(empty) $(empty) # ============================================================================== # CONFIGURATION DEFAULTS # ============================================================================== -PUSH ?= true -DEBUG ?= false -NO_CACHE ?= false -DRY_RUN ?= false +PUSH := $(or $(PUSH),true) +DEBUG := $(or $(DEBUG),false) +NO_CACHE := $(or $(NO_CACHE),false) +DRY_RUN := $(or $(DRY_RUN),false) # Common Configuration expressions for building targets PUSH_ARGS = $(if $(filter true,$(PUSH)),--set *.output=type=image$(comma)push=$(PUSH),) @@ -52,7 +52,7 @@ ALL_K8S_VERSIONS = $(if $(strip $(K8S_VERSION)),\ # CORE BUILD TARGET # ============================================================================== build: - @$(if $(BAKE_ENV),env $(BAKE_ENV)) \ + $(if $(BAKE_ENV),env $(BAKE_ENV)) \ docker buildx bake ${DRY_RUN_ARGS} ${DOCKER_BUILD_OUT} ${DOCKER_NO_CACHE} ${TARGET} $(BAKE_ARGS) # ============================================================================== @@ -60,15 +60,21 @@ build: # ============================================================================== build-all-images: build-provider-images iso -base-image: - $(MAKE) TARGET=base-image build - iso: $(MAKE) TARGET=$(ISO_TARGET_TYPE) build +iso-image: + $(MAKE) TARGET=iso-image build + iso-disk-image: $(MAKE) TARGET=iso-disk-image build BAKE_ARGS="$(PUSH_ARGS)" +aws-cloud-image: + $(MAKE) TARGET=aws-cloud-image build + +cloud-image: + $(MAKE) TARGET=cloud-image build + # ============================================================================== # PROVIDER IMAGE BUILD TARGETS # ============================================================================== @@ -81,7 +87,7 @@ build-provider-images: .check-provider-prereqs $(addprefix .build-provider-image .build-provider-image-%: .check-provider-prereqs @echo "Building provider image for k8s version: $*" - $(MAKE) TARGET=$(PROVIDER_TARGET_TYPE) \ + @$(MAKE) TARGET=$(PROVIDER_TARGET_TYPE) \ BAKE_ENV="K8S_VERSION=$*" \ BAKE_ARGS="--set *.args.K8S_VERSION=$* $(PUSH_ARGS)" \ build @@ -102,20 +108,28 @@ uki-genkey: validate-user-data: $(MAKE) TARGET=validate-user-data build +internal-slink: + $(MAKE) TARGET=internal-slink build + +iso-efi-size-check: + $(MAKE) TARGET=iso-efi-size-check build + alpine-all: $(MAKE) TARGET=alpine-all BAKE_ARGS="$(PUSH_ARGS)" build help: @echo "Available targets:" @echo " build-all-images - Build all provider images and ISO" - @echo " base-image - Build base image" @echo " iso - Build ISO installer" @echo " iso-disk-image - Build ISO disk image" @echo " build-provider-images - Build all provider images for configured K8S versions" + @echo " cloud-image - Build raw cloud disk image" + @echo " aws-cloud-image - Build AWS AMI from cloud image" @echo " uki-genkey - Generate UKI secure boot keys" @echo " validate-user-data - Validate user-data configuration" @echo "" - @echo "Configuration (set in .arg file or as make variables):" + @echo "Build specific configuration (set in .arg file or as make variables):" @echo " PUSH - Push images to registry (default: true)" @echo " DEBUG - Enable debug output (default: false)" @echo " NO_CACHE - Disable build cache (default: false)" + @echo " DRY_RUN - Print build commands without executing (default: false)" diff --git a/docker-bake.hcl b/docker-bake.hcl index a9e5d15c..942251b6 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -11,10 +11,6 @@ variable "SPECTRO_PUB_REPO" { default = FIPS_ENABLED ? "us-east1-docker.pkg.dev/spectro-images/dev-fips/arun" : "us-east1-docker.pkg.dev/spectro-images/dev/arun" } -variable "KAIROS_BASE_IMAGE_URL" { - default = "${SPECTRO_PUB_REPO}/edge" -} - variable "SPECTRO_THIRD_PARTY_IMAGE" { default = "us-east1-docker.pkg.dev/spectro-images/third-party/spectro-third-party:4.6" } @@ -31,6 +27,13 @@ variable "SPECTRO_LUET_REPO" { default = "us-docker.pkg.dev/palette-images/edge" } +variable "KAIROS_BASE_IMAGE_URL" { + default = "${SPECTRO_PUB_REPO}/edge" +} + +variable AURORABOOT_IMAGE { + default = "quay.io/kairos/auroraboot:v0.14.0" +} variable "PE_VERSION" { default = "v4.8.1" @@ -40,8 +43,12 @@ variable "KAIROS_VERSION" { default = "v3.5.9" } -variable AURORABOOT_IMAGE { - default = "quay.io/kairos/auroraboot:v0.14.0" +variable "K3S_FLAVOR_TAG" { + default = "k3s1" +} + +variable "RKE2_FLAVOR_TAG" { + default = "rke2r1" } variable "K3S_PROVIDER_VERSION" { @@ -64,13 +71,6 @@ variable "CANONICAL_PROVIDER_VERSION" { default = "v1.2.2" } -variable "K3S_FLAVOR_TAG" { - default = "k3s1" -} - -variable "RKE2_FLAVOR_TAG" { - default = "rke2r1" -} variable OS_DISTRIBUTION {} variable OS_VERSION {} @@ -107,6 +107,10 @@ variable "CIS_HARDENING" { variable UBUNTU_PRO_KEY {} +variable DRBD_VERSION { + default = "9.2.13" +} + variable HTTP_PROXY {} variable HTTPS_PROXY {} variable NO_PROXY {} @@ -127,6 +131,10 @@ variable "UPDATE_KERNEL" { default = false } +variable ETCD_VERSION { + default = "v3.5.13" +} + variable KINE_VERSION { default = "0.11.4" } @@ -136,6 +144,11 @@ variable "TWO_NODE" { default = false } +variable "IS_MAAS" { + type = bool + default = false +} + variable "IS_UKI" { type = bool default = false @@ -151,6 +164,11 @@ variable "AUTO_ENROLL_SECUREBOOT_KEYS" { default = false } +variable "UKI_BRING_YOUR_OWN_KEYS" { + type = bool + default = false +} + variable "CMDLINE" { default = "stylus.registration" } @@ -159,12 +177,7 @@ variable "BRANDING" { default = "Palette eXtended Kubernetes Edge" } -variable "DEBUG" { - type = bool - default = false -} - -variable "UKI_BRING_YOUR_OWN_KEYS" { +variable "FORCE_INTERACTIVE_INSTALL"{ type = bool default = false } @@ -177,19 +190,6 @@ variable "EXPIRATION_IN_DAYS" { default = 5475 } -# Secrets for secure boot private keys - used by trustedboot-image and build-uki-iso -variable "SECURE_BOOT_SECRETS" { - default = [ - "id=db_key,src=secure-boot/private-keys/db.key", - "id=db_pem,src=secure-boot/public-keys/db.pem", - "id=kek_key,src=secure-boot/private-keys/KEK.key", - "id=kek_pem,src=secure-boot/public-keys/KEK.pem", - "id=pk_key,src=secure-boot/private-keys/PK.key", - "id=pk_pem,src=secure-boot/public-keys/PK.pem", - "id=tpm2_pcr_private,src=secure-boot/private-keys/tpm2-pcr-private.pem" - ] -} - variable "EFI_MAX_SIZE" { default = "2048" } @@ -202,15 +202,44 @@ variable "GOLANG_VERSION" { default = "1.23" } +variable "IS_CLOUD_IMAGE" { + type = bool + default = false +} + + +variable "DEBUG" { + type = bool + default = false +} + variable "BASE_IMAGE" { default = "" } +variable "REGION" {} + +variable "S3_BUCKET" {} + +variable "S3_KEY" {} + +# Alpine base image provided by platform team variable "ALPINE_BASE_IMAGE" { default = FIPS_ENABLED ? "us-docker.pkg.dev/palette-images-fips/third-party/alpine:${ALPINE_TAG}-fips" : "us-docker.pkg.dev/palette-images/third-party/alpine:${ALPINE_TAG}" } -variable "OSBUILDER_IMAGE" {} +# Secrets for secure boot private keys - used by trustedboot-image and build-uki-iso +variable "SECURE_BOOT_SECRETS" { + default = [ + "id=db_key,src=secure-boot/private-keys/db.key", + "id=db_pem,src=secure-boot/public-keys/db.pem", + "id=kek_key,src=secure-boot/private-keys/KEK.key", + "id=kek_pem,src=secure-boot/public-keys/KEK.pem", + "id=pk_key,src=secure-boot/private-keys/PK.key", + "id=pk_pem,src=secure-boot/public-keys/PK.pem", + "id=tpm2_pcr_private,src=secure-boot/private-keys/tpm2-pcr-private.pem" + ] +} variable "IS_JETSON" { type = bool @@ -260,15 +289,6 @@ function "get_base_image" { ) } -target "stylus-image" { - dockerfile = "dockerfiles/Dockerfile.stylus-image" - target = "stylus-image" - args = { - STYLUS_BASE = STYLUS_BASE - ARCH = ARCH - } - platforms = ["linux/${ARCH}"] -} target "base" { dockerfile = "Dockerfile" @@ -279,6 +299,7 @@ target "base" { HTTP_PROXY = HTTP_PROXY HTTPS_PROXY = HTTPS_PROXY NO_PROXY = NO_PROXY + DRBD_VERSION = DRBD_VERSION } } @@ -298,6 +319,7 @@ target "base-image" { DISABLE_SELINUX = DISABLE_SELINUX ARCH = ARCH FIPS_ENABLED = FIPS_ENABLED + IS_MAAS = IS_MAAS } secret = ["id=ubuntu_pro_key,env=UBUNTU_PRO_KEY"] } @@ -305,33 +327,16 @@ target "base-image" { function "get_provider_base" { params = [k8s_distribution, spectro_pub_repo, kubeadm_version, k3s_version, rke2_version, nodeadm_version, canonical_version] result = ( - k8s_distribution == "kubeadm" ? "${spectro_pub_repo}/edge/kairos-io/provider-kubeadm:${kubeadm_version}" : - k8s_distribution == "kubeadm-fips" ? "${spectro_pub_repo}/edge/kairos-io/provider-kubeadm:${kubeadm_version}" : - k8s_distribution == "k3s" ? "${spectro_pub_repo}/edge/kairos-io/provider-k3s:${k3s_version}" : - k8s_distribution == "rke2" ? "${spectro_pub_repo}/edge/kairos-io/provider-rke2:${rke2_version}" : - k8s_distribution == "nodeadm" ? "${spectro_pub_repo}/edge/kairos-io/provider-nodeadm:${nodeadm_version}" : - k8s_distribution == "canonical" ? "${spectro_pub_repo}/edge/kairos-io/provider-canonical:${canonical_version}" : + k8s_distribution == "kubeadm" ? "docker-image://${spectro_pub_repo}/edge/kairos-io/provider-kubeadm:${kubeadm_version}" : + k8s_distribution == "kubeadm-fips" ? "docker-image://${spectro_pub_repo}/edge/kairos-io/provider-kubeadm:${kubeadm_version}" : + k8s_distribution == "k3s" ? "docker-image://${spectro_pub_repo}/edge/kairos-io/provider-k3s:${k3s_version}" : + k8s_distribution == "rke2" ? "docker-image://${spectro_pub_repo}/edge/kairos-io/provider-rke2:${rke2_version}" : + k8s_distribution == "nodeadm" ? "docker-image://${spectro_pub_repo}/edge/kairos-io/provider-nodeadm:${nodeadm_version}" : + k8s_distribution == "canonical" ? "docker-image://${spectro_pub_repo}/edge/kairos-io/provider-canonical:${canonical_version}" : "" ) } -target "kairos-provider-image" { - dockerfile = "dockerfiles/Dockerfile.kairos-provider-image" - target = "kairos-provider-image" - platforms = ["linux/${ARCH}"] - args = { - PROVIDER_BASE = get_provider_base( - K8S_DISTRIBUTION, - SPECTRO_PUB_REPO, - KUBEADM_PROVIDER_VERSION, - K3S_PROVIDER_VERSION, - RKE2_PROVIDER_VERSION, - NODEADM_PROVIDER_VERSION, - CANONICAL_PROVIDER_VERSION, - ) - } -} - target "install-k8s" { dockerfile = "dockerfiles/Dockerfile.install-k8s" target = "install-k8s" @@ -340,7 +345,7 @@ target "install-k8s" { third-party-luet = "target:third-party-luet" } args = { - BASE_ALPINE_IMAGE = ALPINE_IMG + ALPINE_IMG = ALPINE_IMG ARCH = ARCH K8S_DISTRIBUTION = K8S_DISTRIBUTION K8S_VERSION = K8S_VERSION @@ -357,8 +362,17 @@ target "provider-image" { platforms = ["linux/${ARCH}"] contexts = { base-image = "target:base-image" - kairos-provider-image = "target:kairos-provider-image" - stylus-image = "target:stylus-image" + // kairos-provider-image = "target:kairos-provider-image" + kairos-provider-image = get_provider_base( + K8S_DISTRIBUTION, + SPECTRO_PUB_REPO, + KUBEADM_PROVIDER_VERSION, + K3S_PROVIDER_VERSION, + RKE2_PROVIDER_VERSION, + NODEADM_PROVIDER_VERSION, + CANONICAL_PROVIDER_VERSION, + ) + stylus-image = "docker-image://${STYLUS_BASE}" install-k8s = "target:install-k8s" third-party-luet = "target:third-party-luet" third-party-etcdctl = "target:third-party-etcdctl" @@ -377,6 +391,7 @@ target "provider-image" { KINE_VERSION = KINE_VERSION IMAGE_PATH = IMAGE_PATH IS_UKI = IS_UKI + UPDATE_KERNEL = UPDATE_KERNEL } tags = [IMAGE_PATH] output = ["type=image,push=true"] @@ -389,6 +404,7 @@ target "uki-provider-image" { third-party-luet = "target:third-party-luet" install-k8s = "target:install-k8s" trustedboot-image = "target:trustedboot-image" + stylus-image = "docker-image://${STYLUS_BASE}" } args = { BASE_IMAGE = get_base_image(BASE_IMAGE, OS_DISTRIBUTION, OS_VERSION, IS_UKI) @@ -426,19 +442,23 @@ target "validate-user-data" { platforms = ["linux/${ARCH}"] } + target "iso-image" { dockerfile = "dockerfiles/Dockerfile.iso-image" target = "iso-image" platforms = ["linux/${ARCH}"] contexts = { base-image = "target:base-image" - stylus-image = "target:stylus-image" + stylus-image = "docker-image://${STYLUS_BASE}" } args = { ARCH = ARCH IS_UKI = IS_UKI + IS_CLOUD_IMAGE = IS_CLOUD_IMAGE } - tags = ["palette-installer-image:${IMAGE_TAG}"] + # MAAS uses latest tag, non-MAAS uses version tag + tags = IS_MAAS ? ["palette-installer-image:latest"] : ["palette-installer-image:${IMAGE_TAG}"] + output = ["type=docker"] } target "build-iso" { @@ -455,7 +475,7 @@ target "build-iso" { CLUSTERCONFIG = CLUSTERCONFIG EDGE_CUSTOM_CONFIG = EDGE_CUSTOM_CONFIG AURORABOOT_IMAGE = AURORABOOT_IMAGE - CONTAINER_IMAGE = "palette-installer-image:${IMAGE_TAG}" + FORCE_INTERACTIVE_INSTALL = FORCE_INTERACTIVE_INSTALL } output = ["type=local,dest=./build"] } @@ -540,7 +560,6 @@ target "internal-slink" { GOOS = "linux" GOARCH = "amd64" } - tags = ["internal-slink:latest"] output = ["type=local,dest=build"] } @@ -589,3 +608,53 @@ target "alpine-all" { tags = [ALPINE_IMG] output = ["type=image,push=true"] } + +target "iso-efi-size-check" { + dockerfile = "dockerfiles/Dockerfile.iso-efi-size-check" + context = "." + target = "output" + platforms = ["linux/amd64"] + args = { + UBUNTU_IMAGE = get_ubuntu_image(FIPS_ENABLED, SPECTRO_PUB_REPO) + EFI_MAX_SIZE = EFI_MAX_SIZE + EFI_IMG_SIZE = EFI_IMG_SIZE + } + output = ["type=local,dest=./build/"] +} + +target "cloud-image" { + dockerfile = "dockerfiles/Dockerfile.cloud-image" + context = "." + target = "output" + platforms = ["linux/${ARCH}"] + contexts = { + iso-image = "target:iso-image" + } + args = { + AURORABOOT_IMAGE = AURORABOOT_IMAGE + ARCH = ARCH + } + output = ["type=local,dest=./build/"] +} + +target "aws-cloud-image" { + dockerfile = "dockerfiles/Dockerfile.aws-cloud-image" + context = "." + target = "output" + platforms = ["linux/${ARCH}"] + contexts = { + cloud-image = "target:cloud-image" + } + args = { + UBUNTU_IMAGE = get_ubuntu_image(FIPS_ENABLED, SPECTRO_PUB_REPO) + REGION = REGION + S3_BUCKET = S3_BUCKET + S3_KEY = S3_KEY + } + secret = [ + "id=AWS_PROFILE,env=AWS_PROFILE", + "id=AWS_ACCESS_KEY_ID,env=AWS_ACCESS_KEY_ID", + "id=AWS_SECRET_ACCESS_KEY,env=AWS_SECRET_ACCESS_KEY" + ] + output = ["type=local,dest=./build/"] +} diff --git a/dockerfiles/Dockerfile.alpine b/dockerfiles/Dockerfile.alpine index 1ab1ab39..509201e3 100644 --- a/dockerfiles/Dockerfile.alpine +++ b/dockerfiles/Dockerfile.alpine @@ -5,5 +5,4 @@ FROM ${ALPINE_BASE_IMAGE} RUN apk add --no-cache bash curl jq ca-certificates upx # In FIPS mode, this may fail due to OpenSSL FIPS constraints. -RUN update-ca-certificates || true - +RUN update-ca-certificates || true \ No newline at end of file diff --git a/dockerfiles/Dockerfile.aws-cloud-image b/dockerfiles/Dockerfile.aws-cloud-image new file mode 100644 index 00000000..60cd9334 --- /dev/null +++ b/dockerfiles/Dockerfile.aws-cloud-image @@ -0,0 +1,63 @@ +ARG UBUNTU_IMAGE + +FROM ${UBUNTU_IMAGE} AS builder + +ARG REGION +ARG S3_BUCKET +ARG S3_KEY + +# Install dependencies +RUN apt-get update && apt-get install -y unzip ca-certificates curl && \ + rm -rf /var/lib/apt/lists/* + +# Install AWS CLI +RUN curl --fail -s "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \ + unzip -q awscliv2.zip -d aws_install_temp && \ + ./aws_install_temp/aws/install && \ + rm -rf awscliv2.zip aws_install_temp + +WORKDIR /workdir + +# Copy the cloud image output +COPY --from=cloud-image / /workdir/ + +# Copy the AMI creation script +COPY cloud-images/scripts/create-raw-to-ami.sh /workdir/create-raw-to-ami.sh + +# Run the script to create AMI from RAW file +RUN --mount=type=secret,id=AWS_PROFILE \ + --mount=type=secret,id=AWS_ACCESS_KEY_ID \ + --mount=type=secret,id=AWS_SECRET_ACCESS_KEY \ + RAW_FILE_PATH=$(ls /workdir/*.raw) && \ + echo "RAW_FILE_PATH: $RAW_FILE_PATH" && \ + if [ ! -f "$RAW_FILE_PATH" ]; then \ + echo "Error: RAW file not found." && \ + ls -la /workdir/ && \ + exit 1; \ + else \ + echo "RAW file '$RAW_FILE_PATH' found." && \ + echo "Proceeding with creation of AMI..."; \ + fi && \ + /workdir/create-raw-to-ami.sh "$RAW_FILE_PATH" + +FROM scratch AS output +COPY --from=builder /workdir/ / + + + + + + + + + + + + + + + + + + + diff --git a/dockerfiles/Dockerfile.base-image b/dockerfiles/Dockerfile.base-image index 8c215d2a..f532c99c 100644 --- a/dockerfiles/Dockerfile.base-image +++ b/dockerfiles/Dockerfile.base-image @@ -3,25 +3,28 @@ FROM base ARG OS_DISTRIBUTION ARG OS_VERSION -ARG IS_JETSON -ARG IS_UKI +ARG IS_JETSON=false +ARG IS_UKI=false ARG UPDATE_KERNEL ARG CIS_HARDENING ARG KAIROS_VERSION ARG DISABLE_SELINUX -ARG ARCH -ARG FIPS_ENABLED +ARG ARCH=amd64 +ARG FIPS_ENABLED=false +ARG IS_MAAS=false COPY . /tmp/build-context + RUN if [ "$IS_JETSON" = "true" ]; then \ cp /tmp/build-context/cloudconfigs/mount.yaml /system/oem/mount.yaml; \ fi + RUN if [ "$IS_UKI" = "true" ]; then \ cp /tmp/build-context/cloudconfigs/80_stylus_uki.yaml /system/oem/80_stylus_uki.yaml; \ fi # Use secret for UBUNTU_PRO_KEY - not cached, not stored in image layers -RUN --mount=type=secret,id=ubuntu_pro_key \ +RUN --mount=type=secret,id=ubuntu_pro_key,target=/run/secrets/ubuntu_pro_key \ if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ]; then \ if [ -f /run/secrets/ubuntu_pro_key ] && [ -s /run/secrets/ubuntu_pro_key ]; then \ sed -i '/^[[:space:]]*$/d' /etc/os-release && \ @@ -50,7 +53,18 @@ RUN --mount=type=secret,id=ubuntu_pro_key \ if [ "$IS_UKI" = "false" ]; then \ DEBIAN_FRONTEND=noninteractive apt-get update && \ apt-get upgrade $APT_UPGRADE_FLAGS && \ - DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y cloud-guest-utils && \ + DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \ + util-linux \ + parted \ + cloud-guest-utils \ + gawk \ + fdisk \ + gdisk \ + e2fsprogs \ + dosfstools \ + rsync \ + cryptsetup-bin \ + udev && \ \ latest_kernel=$(printf '%s\n' /lib/modules/* | xargs -n1 basename | sort -V | tail -1 | awk -F '-' '{print $1"-"$2}') && \ if [ "$FIPS_ENABLED" = "true" ]; then \ @@ -70,9 +84,8 @@ RUN --mount=type=secret,id=ubuntu_pro_key \ apt-get autoremove -y && \ rm -rf /var/lib/apt/lists/* && \ kernel=$(ls /boot/vmlinuz-* 2>/dev/null | tail -n1) && \ - # if [ -n "$kernel" ]; then \ - ln -sf "${kernel#/boot/}" /boot/vmlinuz; \ - # fi && \ + ln -sf "${kernel#/boot/}" /boot/vmlinuz && \ + \ if [ "$FIPS_ENABLED" = "false" ]; then \ kernel=$(printf '%s\n' /lib/modules/* | xargs -n1 basename | sort -V | tail -1) && \ dracut -f "/boot/initrd-${kernel}" "${kernel}" && \ @@ -105,7 +118,7 @@ RUN if [ "$OS_DISTRIBUTION" = "opensuse-leap" ]; then \ zypper refresh && zypper update -y && \ \ if [ -e "/usr/bin/dracut" ]; then \ - kernel=$(ls /lib/modules | tail -n1) && \ + kernel=$(printf '%s\n' /lib/modules/* | xargs -n1 basename | sort -V | tail -1) && \ depmod -a "${kernel}" && \ dracut -f "/boot/initrd-${kernel}" "${kernel}" && \ ln -sf "initrd-${kernel}" /boot/initrd; \ @@ -148,6 +161,19 @@ RUN export OS_ID=${OS_DISTRIBUTION} && \ export KAIROS_RELEASE=${KAIROS_VERSION} && \ envsubst >>/etc/os-release < /tmp/build-context/overlay/files/usr/lib/os-release.tmpl +RUN KAIROS_IMAGE_LABEL="${OS_VERSION}-standard-${ARCH}-generic" && \ + if [ "$IS_MAAS" = "true" ]; then \ + KAIROS_IMAGE_LABEL="${KAIROS_IMAGE_LABEL}-maas";\ + fi; \ + if [ -f /etc/kairos-release ]; then \ + sed -i 's/^KAIROS_NAME=.*/KAIROS_NAME="kairos-core-'"$OS_DISTRIBUTION"'-'"$OS_VERSION"'"/' /etc/kairos-release; \ + sed -i '/^KAIROS_IMAGE_LABEL=/d' /etc/kairos-release; \ + echo 'KAIROS_IMAGE_LABEL="'"$KAIROS_IMAGE_LABEL"'"' >> /etc/kairos-release; \ + else \ + echo 'KAIROS_NAME="kairos-core-'"$OS_DISTRIBUTION"'-'"$OS_VERSION"'"' >> /etc/kairos-release; \ + echo 'KAIROS_IMAGE_LABEL="'"$KAIROS_IMAGE_LABEL"'"' >> /etc/kairos-release; \ + fi + RUN rm -rf /var/cache/* && \ journalctl --vacuum-size=1K && \ rm -rf /etc/machine-id && \ diff --git a/dockerfiles/Dockerfile.build-iso b/dockerfiles/Dockerfile.build-iso index 6140c8ae..73314aed 100644 --- a/dockerfiles/Dockerfile.build-iso +++ b/dockerfiles/Dockerfile.build-iso @@ -2,27 +2,24 @@ ARG AURORABOOT_IMAGE FROM ${AURORABOOT_IMAGE} AS builder -ARG ARCH +ARG ARCH=amd64 ARG ISO_NAME ARG CLUSTERCONFIG ARG EDGE_CUSTOM_CONFIG -ARG CONTAINER_IMAGE +ARG FORCE_INTERACTIVE_INSTALL=false COPY overlay/files-iso/ /overlay/ -COPY --from=validate-user-data /tmp/context /tmp/validate-context -RUN if [ -f /tmp/validate-context/user-data ]; then \ - cp /tmp/validate-context/user-data /cloud-config.yaml; \ - fi +COPY --from=validate-user-data /validated /validated COPY --from=iso-image / /iso-source/ COPY . /tmp/build-context/ -RUN mkdir -p /overlay/opt/spectrocloud/content -RUN if [ -d /tmp/build-context/content-* ]; then \ - find /tmp/build-context -name "content-*" -type d -exec cp -r {}/*.zst /overlay/opt/spectrocloud/content/ \; 2>/dev/null || true; \ - fi +RUN mkdir -p /overlay/opt/spectrocloud/content && \ + for dir in /tmp/build-context/content-*/; do \ + [ -d "$dir" ] && cp "$dir"*.zst /overlay/opt/spectrocloud/content/ 2>/dev/null || true; \ + done RUN if [ -n "$EDGE_CUSTOM_CONFIG" ] && [ -f /tmp/build-context/"$EDGE_CUSTOM_CONFIG" ]; then \ cp /tmp/build-context/"$EDGE_CUSTOM_CONFIG" /overlay/.edge_custom_config.yaml; \ @@ -35,24 +32,34 @@ RUN if [ -n "$(ls /overlay/opt/spectrocloud/content/*.zst 2>/dev/null)" ]; then rm -f /overlay/opt/spectrocloud/content/*.zst; \ fi -RUN if [ "$CLUSTERCONFIG" != "" ] && [ -f /tmp/build-context/"$CLUSTERCONFIG" ]; then \ +RUN if [ -n "$CLUSTERCONFIG" ] && [ -f /tmp/build-context/"$CLUSTERCONFIG" ]; then \ mkdir -p /overlay/opt/spectrocloud/clusterconfig && \ cp /tmp/build-context/"$CLUSTERCONFIG" /overlay/opt/spectrocloud/clusterconfig/spc.tgz; \ fi RUN if [ -f /tmp/build-context/local-ui.tar ]; then \ - mkdir -p /overlay/opt/spectrocloud && \ tar -xf /tmp/build-context/local-ui.tar -C /overlay/opt/spectrocloud; \ fi +# Generate grub.cfg based on FORCE_INTERACTIVE_INSTALL setting +RUN if [ "$FORCE_INTERACTIVE_INSTALL" = "true" ]; then \ + sed 's/{{DEFAULT_ENTRY}}/2/g' /overlay/boot/grub2/grub.cfg > /overlay/boot/grub2/grub.cfg.tmp && \ + mv /overlay/boot/grub2/grub.cfg.tmp /overlay/boot/grub2/grub.cfg; \ + else \ + sed 's/{{DEFAULT_ENTRY}}/0/g' /overlay/boot/grub2/grub.cfg > /overlay/boot/grub2/grub.cfg.tmp && \ + mv /overlay/boot/grub2/grub.cfg.tmp /overlay/boot/grub2/grub.cfg; \ + fi + RUN mkdir -p /output RUN /usr/bin/auroraboot \ - --debug build-iso \ + --debug \ + build-iso \ --output /output \ --override-name ${ISO_NAME} \ --overlay-iso /overlay \ - $(if [ -f /cloud-config.yaml ] && [ -s /cloud-config.yaml ]; then echo "--cloud-config /cloud-config.yaml"; fi) \ + --set "arch=${ARCH}" \ + $(if [ -f /validated/config.yaml ] && [ -s /validated/config.yaml ]; then echo "--cloud-config /validated/config.yaml"; fi) \ dir:/iso-source RUN mkdir -p /iso && \ diff --git a/dockerfiles/Dockerfile.build-uki-iso b/dockerfiles/Dockerfile.build-uki-iso index 5c080fcc..375c3ad8 100644 --- a/dockerfiles/Dockerfile.build-uki-iso +++ b/dockerfiles/Dockerfile.build-uki-iso @@ -14,39 +14,38 @@ ENV ISO_NAME=${ISO_NAME} COPY overlay/files-iso/ /overlay/ -COPY --from=validate-user-data /tmp/context /tmp/validate-context -RUN if [ -f /tmp/validate-context/user-data ]; then \ - cp /tmp/validate-context/user-data /overlay/cloud-config.yaml; \ - fi +COPY --from=validate-user-data /validated /overlay/ COPY --from=stylus-image-pack /stylus-image.tar /overlay/stylus-image.tar + COPY --from=third-party-luet /WORKDIR/luet /overlay/luet -ARG EDGE_CUSTOM_CONFIG -RUN if [ -n "$EDGE_CUSTOM_CONFIG" ] && [ -f "$EDGE_CUSTOM_CONFIG" ]; then \ - cp "$EDGE_CUSTOM_CONFIG" /overlay/.edge_custom_config.yaml; \ - fi +COPY . /tmp/build-context/ RUN mkdir -p /overlay/opt/spectrocloud/content && \ - (cp content-*/*.zst /overlay/opt/spectrocloud/content/ 2>/dev/null || echo "No content files found") && \ - if ls /overlay/opt/spectrocloud/content/*.zst >/dev/null 2>&1; then \ - for file in /overlay/opt/spectrocloud/content/*.zst; do \ - split --bytes=3GB --numeric-suffixes "$file" /overlay/opt/spectrocloud/content/$(basename "$file")_part; \ - done && \ - rm -f /overlay/opt/spectrocloud/content/*.zst; \ - fi + for dir in /tmp/build-context/content-*/; do \ + [ -d "$dir" ] && cp "$dir"*.zst /overlay/opt/spectrocloud/content/ 2>/dev/null || true; \ + done -RUN if [ -n "$CLUSTERCONFIG" ] && [ -f "$CLUSTERCONFIG" ]; then \ - cp "$CLUSTERCONFIG" /overlay/opt/spectrocloud/clusterconfig/spc.tgz; \ +RUN if [ -n "$EDGE_CUSTOM_CONFIG" ] && [ -f /tmp/build-context/"$EDGE_CUSTOM_CONFIG" ]; then \ + cp /tmp/build-context/"$EDGE_CUSTOM_CONFIG" /overlay/.edge_custom_config.yaml; \ fi -RUN if [ -f "local-ui.tar" ]; then \ - cp local-ui.tar /overlay/opt/spectrocloud/ && \ - tar -xf /overlay/opt/spectrocloud/local-ui.tar -C /overlay/opt/spectrocloud && \ - rm -f /overlay/opt/spectrocloud/local-ui.tar; \ +RUN if [ -n "$(ls /overlay/opt/spectrocloud/content/*.zst 2>/dev/null)" ]; then \ + for file in /overlay/opt/spectrocloud/content/*.zst; do \ + split --bytes=3GB --numeric-suffixes "$file" /overlay/opt/spectrocloud/content/$(basename "$file")_part; \ + done; \ + rm -f /overlay/opt/spectrocloud/content/*.zst; \ +fi + +RUN if [ -n "$CLUSTERCONFIG" ] && [ -f /tmp/build-context/"$CLUSTERCONFIG" ]; then \ + mkdir -p /overlay/opt/spectrocloud/clusterconfig && \ + cp /tmp/build-context/"$CLUSTERCONFIG" /overlay/opt/spectrocloud/clusterconfig/spc.tgz; \ fi -WORKDIR /build +RUN if [ -f /tmp/build-context/local-ui.tar ]; then \ + tar -xf /tmp/build-context/local-ui.tar -C /overlay/opt/spectrocloud; \ +fi COPY --from=iso-image / /iso-source/ @@ -59,8 +58,17 @@ RUN --mount=type=secret,id=db_key,target=/keys/db.key \ --mount=type=secret,id=pk_key,target=/keys/PK.key \ --mount=type=secret,id=pk_pem,target=/keys/PK.pem \ --mount=type=secret,id=tpm2_pcr_private,target=/keys/tpm2-pcr-private.pem \ - if [ "$ARCH" = "amd64" ]; then \ - mkdir -p /iso && \ + mkdir -p /iso && \ + if [ "$ARCH" = "arm64" ]; then \ + /usr/bin/auroraboot \ + $([ "$DEBUG" = "true" ] && echo "--debug") \ + build-iso \ + --output /iso \ + --override-name "${ISO_NAME}" \ + --overlay-iso /overlay \ + --arch "$ARCH" \ + dir:/iso-source; \ + elif [ "$ARCH" = "amd64" ]; then \ /usr/bin/auroraboot \ $([ "$DEBUG" = "true" ] && echo "--debug") \ build-uki \ diff --git a/dockerfiles/Dockerfile.cloud-image b/dockerfiles/Dockerfile.cloud-image new file mode 100644 index 00000000..6496a978 --- /dev/null +++ b/dockerfiles/Dockerfile.cloud-image @@ -0,0 +1,46 @@ +ARG AURORABOOT_IMAGE + +FROM ${AURORABOOT_IMAGE} AS builder + +ARG ARCH=amd64 + +# Copy the cloud-init config file +COPY cloud-images/config/user-data.yaml /config.yaml + +# Copy the iso-image content +COPY --from=iso-image / /iso-source/ + +RUN mkdir -p /output + +# Run auroraboot to create the cloud image (raw disk) +RUN /usr/bin/auroraboot \ + --debug \ + --set "disable_http_server=true" \ + --set "container_image=oci:/iso-source" \ + --set "disable_netboot=true" \ + --set "disk.raw=true" \ + --set "state_dir=/output" \ + --set "arch=${ARCH}" \ + --cloud-config /config.yaml + +FROM scratch AS output +COPY --from=builder /output/ / + + + + + + + + + + + + + + + + + + + diff --git a/dockerfiles/Dockerfile.install-k8s b/dockerfiles/Dockerfile.install-k8s index 00412b7b..48b1eb22 100644 --- a/dockerfiles/Dockerfile.install-k8s +++ b/dockerfiles/Dockerfile.install-k8s @@ -1,7 +1,7 @@ ARG ARCH -ARG BASE_ALPINE_IMAGE +ARG ALPINE_IMG -FROM --platform=linux/${ARCH} ${BASE_ALPINE_IMAGE} AS install-k8s +FROM --platform=linux/${ARCH} ${ALPINE_IMG} AS install-k8s ARG K8S_DISTRIBUTION ARG K8S_VERSION @@ -11,21 +11,21 @@ ARG SPECTRO_LUET_REPO ARG ARCH ARG LUET_REPO -RUN [ -d "certs" ] && cp -r certs/. /etc/ssl/certs/ || true +COPY . /tmp/build-context/ + +RUN [ -d "/tmp/build-context/certs" ] && cp -r /tmp/build-context/certs/. /etc/ssl/certs/ || true RUN update-ca-certificates -RUN apk add curl COPY --from=third-party-luet /WORKDIR/luet /usr/bin/luet WORKDIR /output -COPY . /tmp/build-context/ RUN mkdir -p /etc/luet/repos.conf.d && \ luet repo add spectro --type docker --url $SPECTRO_LUET_REPO/$LUET_REPO --priority 1 -y RUN if [ -f /tmp/build-context/spectro-luet-auth.yaml ]; then \ - cat /tmp/build-context/spectro-luet-auth.yaml >> /etc/luet/repos.conf.d/spectro.yaml; \ + cat /tmp/build-context/spectro-luet-auth.yaml >> /etc/luet/repos.conf.d/spectro.yaml; \ fi RUN luet repo update diff --git a/dockerfiles/Dockerfile.iso-efi-size-check b/dockerfiles/Dockerfile.iso-efi-size-check new file mode 100644 index 00000000..1040045a --- /dev/null +++ b/dockerfiles/Dockerfile.iso-efi-size-check @@ -0,0 +1,45 @@ +ARG UBUNTU_IMAGE +# Stage 1: Build the EFI binary +FROM rust:1.78-bookworm AS rust-deps + +RUN apt-get update -qq && \ + apt-get install --no-install-recommends -qq autoconf autotools-dev libtool-bin clang cmake bsdmainutils + +RUN ls -lrth + +WORKDIR /build +COPY efi-size-check efi-size-check + +WORKDIR /build/efi-size-check +RUN cargo build --target x86_64-unknown-uefi + +# Stage 2: Create the ISO +FROM ${UBUNTU_IMAGE} AS iso-builder + +ARG EFI_MAX_SIZE +ARG EFI_IMG_SIZE + +RUN apt-get update && \ + apt-get install -y mtools xorriso && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /build + +COPY --from=rust-deps /build/efi-size-check/target/x86_64-unknown-uefi/debug/efi-size-check.efi /build/efi-size-check.efi + +RUN mkdir -p esp && \ + dd if=/dev/urandom of=esp/ABC bs=1M count=${EFI_MAX_SIZE} && \ + dd if=/dev/zero of=fat.img bs=1M count=${EFI_IMG_SIZE} && \ + mformat -i fat.img -F :: && \ + mmd -i fat.img ::/EFI && \ + mmd -i fat.img ::/EFI/BOOT && \ + mcopy -i fat.img efi-size-check.efi ::/EFI/BOOT/BOOTX64.EFI && \ + mcopy -i fat.img esp/ABC :: && \ + mkdir -p iso && \ + cp fat.img iso && \ + xorriso -as mkisofs -e fat.img -no-emul-boot -o efi-size-check.iso iso + +# Output stage +FROM scratch AS output +COPY --from=iso-builder /build/efi-size-check.iso / + diff --git a/dockerfiles/Dockerfile.iso-image b/dockerfiles/Dockerfile.iso-image index aac99e03..a8614dfa 100644 --- a/dockerfiles/Dockerfile.iso-image +++ b/dockerfiles/Dockerfile.iso-image @@ -1,6 +1,6 @@ FROM base-image AS iso-image -ARG IS_UKI +ARG IS_UKI=false ARG IS_CLOUD_IMAGE=false COPY --from=stylus-image / / diff --git a/dockerfiles/Dockerfile.kairos-provider-image b/dockerfiles/Dockerfile.kairos-provider-image deleted file mode 100644 index 1cd58a0b..00000000 --- a/dockerfiles/Dockerfile.kairos-provider-image +++ /dev/null @@ -1,3 +0,0 @@ -ARG PROVIDER_BASE - -FROM ${PROVIDER_BASE} AS kairos-provider-image \ No newline at end of file diff --git a/dockerfiles/Dockerfile.provider-image b/dockerfiles/Dockerfile.provider-image index 60237eaf..da01d4f9 100644 --- a/dockerfiles/Dockerfile.provider-image +++ b/dockerfiles/Dockerfile.provider-image @@ -14,18 +14,48 @@ ARG KINE_VERSION ARG IMAGE_PATH ARG IS_UKI ARG ARCH +ARG UPDATE_KERNEL=false -RUN if [ "$K8S_DISTRIBUTION" = "kubeadm" ] || [ "$K8S_DISTRIBUTION" = "kubeadm-fips" ] || [ "$K8S_DISTRIBUTION" = "nodeadm" ]; then \ - BASE_K8S_VERSION="$K8S_VERSION"; \ - if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ] && [ "$K8S_DISTRIBUTION" = "kubeadm" ]; then \ - kernel=$(ls /lib/modules | tail -n1) && if ! ls /usr/src | grep linux-headers-$kernel; then apt-get update && apt-get install -y "linux-headers-${kernel}"; fi; \ +RUN if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ] && [ "$K8S_DISTRIBUTION" = "kubeadm" ]; then \ + kernel=$(printf '%s\n' /lib/modules/* | xargs -n1 basename | sort -V | tail -1) && \ + if ! ls /usr/src | grep linux-headers-$kernel; then apt-get update && apt-get install -y "linux-headers-${kernel}"; fi; \ + fi + +# UPDATE_KERNEL handling for different OS distributions +RUN if [ "$UPDATE_KERNEL" = "true" ]; then \ + if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ]; then \ + kernel=$(printf '%s\n' /lib/modules/* | xargs -n1 basename | sort -V | tail -1) && \ + if ! ls /usr/src | grep linux-headers-$kernel; then apt-get update && apt-get install -y "linux-headers-${kernel}"; fi; \ + elif [ "$OS_DISTRIBUTION" = "opensuse-leap" ] || [ "$OS_DISTRIBUTION" = "sles" ]; then \ + zypper --non-interactive ref && \ + kernel=$(printf '%s\n' /lib/modules/* | xargs -n1 basename | sort -V | tail -1) && \ + echo "kernel module: $kernel" && \ + version=$(echo $kernel | sed 's/-default$//') && \ + echo "kernel version: $version" && \ + if ! zypper --non-interactive install --no-recommends kernel-default-devel-$version; then \ + echo "Exact kernel-default-devel-$version not found, searching for closest match..."; \ + match=$(zypper se -s kernel-default-devel | awk -F'|' '/kernel-default-devel/ && $3 ~ /^ *[0-9]/ {gsub(/^ +| +$/,"",$3); if (index($3,"'"$version"'")==1) print $3}' | sort -Vr | head -n1); \ + if [ -n "$match" ]; then \ + echo "Trying to install kernel-default-devel-$match"; \ + zypper --non-interactive install --no-recommends kernel-default-devel-$match || echo "Failed to install kernel-default-devel-$match"; \ + else \ + echo "No matching kernel-default-devel package found, trying generic kernel-devel"; \ + zypper --non-interactive install --no-recommends kernel-devel || echo "kernel development packages not available, continuing without them"; \ + fi; \ + fi; \ + elif [ "$OS_DISTRIBUTION" = "rhel" ]; then \ + yum clean all && yum makecache && \ + yum-config-manager --enable ubi-8-baseos-rpms ubi-8-appstream-rpms ubi-8-codeready-builder-rpms 2>/dev/null || true && \ + yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm 2>/dev/null || echo "EPEL repo not available" && \ + yum makecache && \ + kernel=$(printf '%s\n' /lib/modules/* | xargs -n1 basename | sort -V | tail -1) && echo "kernel version: $kernel" && \ + if ! yum install -y kernel-devel-$kernel; then \ + echo "kernel-devel-$kernel not available, trying alternative packages" && \ + yum install -y kernel-devel || \ + echo "Trying to install from different source..." && \ + yum install -y gcc make || echo "kernel development packages not available, continuing without them"; \ + fi; \ fi; \ - elif [ "$K8S_DISTRIBUTION" = "k3s" ]; then \ - K8S_DISTRIBUTION_TAG="$K3S_FLAVOR_TAG"; \ - BASE_K8S_VERSION="$K8S_VERSION-$K8S_DISTRIBUTION_TAG"; \ - elif [ "$K8S_DISTRIBUTION" = "rke2" ]; then \ - K8S_DISTRIBUTION_TAG="$RKE2_FLAVOR_TAG"; \ - BASE_K8S_VERSION="$K8S_VERSION-$K8S_DISTRIBUTION_TAG"; \ fi COPY overlay/files/etc/ /etc/ @@ -39,24 +69,29 @@ COPY --from=stylus-image /etc/kairos/branding /etc/kairos/branding COPY --from=stylus-image /oem/stylus_config.yaml /etc/kairos/branding/stylus_config.yaml COPY --from=stylus-image /etc/elemental/config.yaml /etc/elemental/config.yaml +COPY --from=stylus-image / /tmp/stylus-image/ +RUN if [ -f /tmp/stylus-image/system/oem/80_stylus.yaml ]; then \ + mkdir -p /system/oem && \ + cp /tmp/stylus-image/system/oem/80_stylus.yaml /system/oem/80_stylus.yaml; \ + fi && \ + rm -rf /tmp/stylus-image + COPY . /tmp/build-context/ RUN if [ -f /tmp/build-context/"$EDGE_CUSTOM_CONFIG" ]; then \ cp /tmp/build-context/"$EDGE_CUSTOM_CONFIG" /oem/.edge_custom_config.yaml; \ fi -COPY --from=install-k8s /output/ /tmp/k8s-output/ +COPY --from=install-k8s /output/ /k8s COPY --from=internal-slink /slink /usr/bin/slink RUN if [ "$IS_UKI" = "true" ]; then \ - mkdir -p /k8s && cp -r /tmp/k8s-output/* /k8s/ && \ slink --source /k8s/ --target /opt/k8s && \ - rm -f /usr/bin/slink && \ rm -rf /k8s && \ ln -sf /opt/spectrocloud/bin/agent-provider-stylus /usr/local/bin/agent-provider-stylus; \ else \ - cp -r /tmp/k8s-output/* /; \ + cp -r /k8s/* /; \ fi && \ - rm -rf /tmp/k8s-output + rm -rf /k8s /usr/bin/slink RUN rm -f /etc/ssh/ssh_host_* /etc/ssh/moduli @@ -78,12 +113,15 @@ RUN if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$K8S_DISTRIBUTION" = "nodeadm" ]; RUN if [ "$TWO_NODE" = "true" ]; then \ if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ]; then \ - apt install -y ca-certificates curl && \ + apt-get update && \ + echo "tzdata tzdata/Areas select Etc" | debconf-set-selections && \ + echo "tzdata tzdata/Zones/Etc select UTC" | debconf-set-selections && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y ca-certificates curl && \ install -d /usr/share/postgresql-common/pgdg && \ curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc && \ echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list && \ - apt update && \ - apt install -y postgresql-16 postgresql-contrib-16 iputils-ping; \ + apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y postgresql-16 postgresql-contrib-16 iputils-ping; \ elif [ "$OS_DISTRIBUTION" = "opensuse-leap" ] && [ "$ARCH" = "amd64" ]; then \ zypper --non-interactive --quiet addrepo --refresh -p 90 http://download.opensuse.org/repositories/server:database:postgresql/openSUSE_Tumbleweed/ PostgreSQL && \ zypper --gpg-auto-import-keys ref && \ diff --git a/dockerfiles/Dockerfile.slink b/dockerfiles/Dockerfile.slink index b69cb2bb..aa42d9bb 100644 --- a/dockerfiles/Dockerfile.slink +++ b/dockerfiles/Dockerfile.slink @@ -7,15 +7,12 @@ RUN apk add libc-dev binutils-gold clang FROM go-deps AS build -WORKDIR /build +COPY internal /build/internal -COPY internal internal +WORKDIR /build/internal -ARG BUILD_DIR=/build/internal -WORKDIR ${BUILD_DIR} - -ARG VERSION -ARG BIN +ARG VERSION=dev +ARG BIN=slink ARG SRC ARG GOOS ARG GOARCH @@ -27,7 +24,7 @@ ENV CC=clang RUN go mod download -RUN go-build-static.sh -a -o ${BIN} ./${SRC} +RUN go-build-static.sh -a -o /build/bin/${BIN} ./${SRC} FROM scratch AS export -COPY --from=build /build/internal/${BIN} /${BIN} \ No newline at end of file +COPY --from=build /build/bin/${BIN} /${BIN} \ No newline at end of file diff --git a/dockerfiles/Dockerfile.stylus-image b/dockerfiles/Dockerfile.stylus-image deleted file mode 100644 index 448b5d4d..00000000 --- a/dockerfiles/Dockerfile.stylus-image +++ /dev/null @@ -1,3 +0,0 @@ -ARG STYLUS_BASE -ARG ARCH -FROM --platform=linux/${ARCH} ${STYLUS_BASE} AS stylus-image \ No newline at end of file diff --git a/dockerfiles/Dockerfile.uki-byok b/dockerfiles/Dockerfile.uki-byok index ad22cf73..a75e328c 100644 --- a/dockerfiles/Dockerfile.uki-byok +++ b/dockerfiles/Dockerfile.uki-byok @@ -18,8 +18,6 @@ RUN mkdir -p /exported-keys /keys /tmp/secure-boot /private-keys /public-keys COPY secure-boot/ /tmp/secure-boot -RUN ls -ltrh /tmp/secure-boot - # Copy keys from /tmp/secure-boot to their destinations # Preserve original structure in /private-keys and /public-keys for output RUN if [ -d "/tmp/secure-boot/private-keys" ]; then \ diff --git a/dockerfiles/Dockerfile.uki-genkey b/dockerfiles/Dockerfile.uki-genkey index 7f39f791..81ba3253 100644 --- a/dockerfiles/Dockerfile.uki-genkey +++ b/dockerfiles/Dockerfile.uki-genkey @@ -16,40 +16,28 @@ RUN mkdir -p /custom-keys && \ cp -r secure-boot/exported-keys/* /custom-keys/ 2>/dev/null || true; \ fi && \ \ + # Build flags and message dynamically + GENKEY_FLAGS="" && \ + MSG="Generating Secure Boot keys" && \ + \ + if [ -f /custom-keys/KEK ] && [ -f /custom-keys/db ]; then \ + GENKEY_FLAGS="--custom-cert-dir /custom-keys" && \ + MSG="$MSG, including exported UEFI keys"; \ + fi && \ + \ if [ "$INCLUDE_MS_SECUREBOOT_KEYS" != "true" ]; then \ - if [[ -f /custom-keys/KEK && -f /custom-keys/db ]]; then \ - echo "Generating Secure Boot keys, including exported UEFI keys..." && \ - /usr/bin/auroraboot genkey \ - "$MY_ORG" \ - --custom-cert-dir /custom-keys \ - --skip-microsoft-certs-I-KNOW-WHAT-IM-DOING \ - --expiration-days $EXPIRATION_IN_DAYS \ - --output /keys; \ - else \ - echo "Generating Secure Boot keys..." && \ - /usr/bin/auroraboot genkey \ - "$MY_ORG" \ - --skip-microsoft-certs-I-KNOW-WHAT-IM-DOING \ - --expiration-days $EXPIRATION_IN_DAYS \ - --output /keys; \ - fi; \ + GENKEY_FLAGS="$GENKEY_FLAGS --skip-microsoft-certs-I-KNOW-WHAT-IM-DOING"; \ else \ - if [[ -f /custom-keys/KEK && -f /custom-keys/db ]]; then \ - echo "Generating Secure Boot keys, including exported UEFI keys and Microsoft keys..." && \ - /usr/bin/auroraboot genkey \ - "$MY_ORG" \ - --custom-cert-dir /custom-keys \ - --expiration-days $EXPIRATION_IN_DAYS \ - --output /keys; \ - else \ - echo "Generating Secure Boot keys, including Microsoft keys..." && \ - /usr/bin/auroraboot genkey \ - "$MY_ORG" \ - --expiration-days $EXPIRATION_IN_DAYS \ - --output /keys; \ - fi; \ + MSG="$MSG and Microsoft keys"; \ fi && \ \ + echo "$MSG..." && \ + /usr/bin/auroraboot genkey \ + "$MY_ORG" \ + $GENKEY_FLAGS \ + --expiration-days $EXPIRATION_IN_DAYS \ + --output /keys && \ + \ ls -ltrh /keys && \ mkdir -p /private-keys /public-keys && \ cd /keys && mv *.key tpm2-pcr-private.pem /private-keys/ 2>/dev/null || true && \ diff --git a/dockerfiles/Dockerfile.uki-provider-image b/dockerfiles/Dockerfile.uki-provider-image index 1c127325..8f901496 100644 --- a/dockerfiles/Dockerfile.uki-provider-image +++ b/dockerfiles/Dockerfile.uki-provider-image @@ -1,6 +1,5 @@ ARG UBUNTU_IMAGE ARG BASE_IMAGE -ARG OSBUILDER_IMAGE FROM ${BASE_IMAGE} AS kairos-agent RUN mkdir -p /output @@ -29,6 +28,17 @@ COPY --from=kairos-agent /output/kairos-agent /usr/bin/kairos-agent COPY --from=trust-boot-unpack /trusted-boot/ /trusted-boot/ COPY --from=install-k8s /output/ /k8s/ -RUN if [ -f "$EDGE_CUSTOM_CONFIG" ]; then \ - cp "$EDGE_CUSTOM_CONFIG" /oem/.edge_custom_config.yaml; \ - fi \ No newline at end of file +# Copy build context to handle optional files +COPY . /tmp/build-context/ +RUN if [ -f /tmp/build-context/"$EDGE_CUSTOM_CONFIG" ]; then \ + cp /tmp/build-context/"$EDGE_CUSTOM_CONFIG" /oem/.edge_custom_config.yaml; \ + fi + +# Copy stylus-image to temp location to handle optional 80_stylus.yaml (Docker doesn't have --if-exists) +COPY --from=stylus-image / /tmp/stylus-image/ +RUN if [ -f /tmp/stylus-image/system/oem/80_stylus.yaml ]; then \ + mkdir -p /system/oem && \ + cp /tmp/stylus-image/system/oem/80_stylus.yaml /system/oem/80_stylus.yaml; \ + fi + +RUN rm -rf /tmp/stylus-image /tmp/build-context \ No newline at end of file diff --git a/dockerfiles/Dockerfile.validate-ud b/dockerfiles/Dockerfile.validate-ud index 7c110507..e504631e 100644 --- a/dockerfiles/Dockerfile.validate-ud +++ b/dockerfiles/Dockerfile.validate-ud @@ -1,16 +1,16 @@ ARG CLI_IMAGE ARG ARCH FROM --platform=linux/${ARCH} ${CLI_IMAGE} AS validate-user-data -COPY . /tmp/context -RUN if [ -f /tmp/context/user-data ]; then \ - cp /tmp/context/user-data /user-data; \ - else \ - echo "user-data file does not exist (skipping copy)"; \ - fi RUN chmod +x /usr/local/bin/palette-edge-cli -RUN if [ -f /user-data ]; then \ - /usr/local/bin/palette-edge-cli validate -f /user-data; \ + +COPY . /tmp/context + +RUN mkdir -p /validated && \ + if [ -f /tmp/context/user-data ]; then \ + /usr/local/bin/palette-edge-cli validate -f /tmp/context/user-data && \ + cp /tmp/context/user-data /validated/config.yaml; \ else \ - echo "user-data file does not exist."; \ - fi \ No newline at end of file + echo "user-data file does not exist (skipping validation)"; \ + fi; \ + rm -rf /tmp/context \ No newline at end of file From 8d4994d90252e5e0a038879623f3dc6dfa934181 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Tue, 9 Dec 2025 20:34:36 +0000 Subject: [PATCH 33/40] fix cloud image targets --- Makefile | 66 ++++++++++++++++++----- docker-bake.hcl | 74 ++++++++++++++------------ dockerfiles/Dockerfile.aws-cloud-image | 13 +++-- dockerfiles/Dockerfile.cloud-image | 46 ---------------- 4 files changed, 102 insertions(+), 97 deletions(-) delete mode 100644 dockerfiles/Dockerfile.cloud-image diff --git a/Makefile b/Makefile index b7358e49..a992af40 100644 --- a/Makefile +++ b/Makefile @@ -5,9 +5,20 @@ export # TARGETS # ============================================================================== .PHONY: build build-all-images iso build-provider-images iso-disk-image \ - uki-genkey alpine-all validate-user-data cloud-image aws-cloud-image help + uki-genkey alpine-all validate-user-data raw-image aws-cloud-image \ + iso-image-cloud internal-slink iso-efi-size-check \ + clean clean-all clean-raw-image clean-keys help + +.SILENT: uki-genkey validate-user-data clean-raw-image + +# ============================================================================== +# CONSTANTS +# ============================================================================== +AURORABOOT_IMAGE := quay.io/kairos/auroraboot:v0.14.0 +RAW_IMAGE_DIR := $(CURDIR)/build/raw-image +ISO_IMAGE_CLOUD := palette-installer-image-cloud:latest +ISO_IMAGE_MAAS := palette-installer-image-maas:latest -.SILENT: uki-genkey validate-user-data # ============================================================================== # HELPER VARIABLES @@ -23,6 +34,7 @@ PUSH := $(or $(PUSH),true) DEBUG := $(or $(DEBUG),false) NO_CACHE := $(or $(NO_CACHE),false) DRY_RUN := $(or $(DRY_RUN),false) +ARCH := $(or $(ARCH),amd64) # Common Configuration expressions for building targets PUSH_ARGS = $(if $(filter true,$(PUSH)),--set *.output=type=image$(comma)push=$(PUSH),) @@ -53,7 +65,7 @@ ALL_K8S_VERSIONS = $(if $(strip $(K8S_VERSION)),\ # ============================================================================== build: $(if $(BAKE_ENV),env $(BAKE_ENV)) \ - docker buildx bake ${DRY_RUN_ARGS} ${DOCKER_BUILD_OUT} ${DOCKER_NO_CACHE} ${TARGET} $(BAKE_ARGS) + docker buildx bake $(DRY_RUN_ARGS) $(DOCKER_BUILD_OUT) $(DOCKER_NO_CACHE) $(TARGET) $(BAKE_ARGS) # ============================================================================== # MAIN BUILD TARGETS @@ -63,17 +75,29 @@ build-all-images: build-provider-images iso iso: $(MAKE) TARGET=$(ISO_TARGET_TYPE) build -iso-image: - $(MAKE) TARGET=iso-image build - iso-disk-image: $(MAKE) TARGET=iso-disk-image build BAKE_ARGS="$(PUSH_ARGS)" -aws-cloud-image: +aws-cloud-image: raw-image $(MAKE) TARGET=aws-cloud-image build -cloud-image: - $(MAKE) TARGET=cloud-image build +raw-image: clean-raw-image iso-image-cloud + mkdir -p $(RAW_IMAGE_DIR) + docker run --net host --privileged -v /var/run/docker.sock:/var/run/docker.sock \ + -v $(RAW_IMAGE_DIR):/build \ + -v $(CURDIR)/cloud-images/config/user-data.yaml:/config.yaml \ + --rm -it $(AURORABOOT_IMAGE) \ + --debug \ + --set "disable_http_server=true" \ + --set "disable_netboot=true" \ + --set "disk.efi=true" \ + --set "arch=$(ARCH)" \ + --set "container_image=$(ISO_IMAGE_CLOUD)" \ + --set "state_dir=/build" \ + --cloud-config /config.yaml + +iso-image-cloud: + $(MAKE) TARGET=iso-image-cloud build BAKE_ARGS="--set *.tags.ISO_IMAGE_CLOUD=$(ISO_IMAGE_CLOUD)" # ============================================================================== # PROVIDER IMAGE BUILD TARGETS @@ -81,7 +105,6 @@ cloud-image: build-provider-images: .check-provider-prereqs $(addprefix .build-provider-image-,$(strip $(ALL_K8S_VERSIONS))) @echo "All provider images built successfully" -# ============================================================================== # PROVIDER IMAGE BUILD TARGETS (INTERNAL) # ============================================================================== @@ -117,16 +140,35 @@ iso-efi-size-check: alpine-all: $(MAKE) TARGET=alpine-all BAKE_ARGS="$(PUSH_ARGS)" build +# ============================================================================== +# CLEAN TARGETS +# ============================================================================== +clean-all: clean clean-keys + +clean: + rm -rf build + +clean-raw-image: + rm -rf build/raw-image + +clean-keys: + rm -rf secure-boot + +# ============================================================================== help: @echo "Available targets:" @echo " build-all-images - Build all provider images and ISO" @echo " iso - Build ISO installer" @echo " iso-disk-image - Build ISO disk image" @echo " build-provider-images - Build all provider images for configured K8S versions" - @echo " cloud-image - Build raw cloud disk image" - @echo " aws-cloud-image - Build AWS AMI from cloud image" + @echo " raw-image - Build raw cloud disk image(Requires root privileges)" + @echo " aws-cloud-image - Build AWS AMI from raw image(Requires root privileges)" @echo " uki-genkey - Generate UKI secure boot keys" @echo " validate-user-data - Validate user-data configuration" + @echo " clean-all - Remove the build directory and secure boot keys" + @echo " clean - Remove the build directory" + @echo " clean-raw-image - Remove the $(RAW_IMAGE_DIR) build directory" + @echo " clean-keys - Clean secure boot keys" @echo "" @echo "Build specific configuration (set in .arg file or as make variables):" @echo " PUSH - Push images to registry (default: true)" diff --git a/docker-bake.hcl b/docker-bake.hcl index 942251b6..e530881e 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -152,6 +152,10 @@ variable "IS_MAAS" { variable "IS_UKI" { type = bool default = false + validation{ + condition = ((IS_UKI && (OS_VERSION == "24" || OS_VERSION == "24.04")) || IS_UKI == false) + error_message = "OS_VERSION must be 24.04 for UKI" + } } variable "INCLUDE_MS_SECUREBOOT_KEYS" { @@ -275,15 +279,19 @@ function "get_ubuntu_image" { result = fips_enabled ? "${spectro_pub_repo}/third-party/ubuntu-fips:22.04" : "${spectro_pub_repo}/third-party/ubuntu:22.04" } +function "normalized_os_version" { + params = [os_distribution, os_version] + // For Ubuntu: if version is like 20, 22, 24, append .04 + result = os_distribution != "ubuntu" ? os_version : (length(regexall("\\.", os_version)) > 0 ? os_version : "${os_version}.04") +} + function "get_base_image" { params = [base_image, os_distribution, os_version, is_uki] result = base_image != "" ? base_image : ( - # Format version: add .04 if not present, then build image URL - os_distribution == "ubuntu" && length(regexall("^(20|22|24)(\\.04)?$", os_version)) > 0 ? - "${KAIROS_BASE_IMAGE_URL}/kairos-${OS_DISTRIBUTION}:${length(regexall("\\.04", os_version)) > 0 ? os_version : os_version + ".04"}-core-${ARCH}-generic-${KAIROS_VERSION}${is_uki && length(regexall("^24", os_version)) > 0 ? "-uki" : ""}" : + os_distribution == "ubuntu" ? "${KAIROS_BASE_IMAGE_URL}/kairos-${os_distribution}:${os_version}-core-${ARCH}-generic-${KAIROS_VERSION}${is_uki ? "-uki" : ""}" : os_distribution == "opensuse-leap" && os_version == "15.6" ? - "${KAIROS_BASE_IMAGE_URL}/kairos-opensuse:leap-${OS_VERSION}-core-${ARCH}-generic-${KAIROS_VERSION}" : + "${KAIROS_BASE_IMAGE_URL}/kairos-opensuse:leap-${os_version}-core-${ARCH}-generic-${KAIROS_VERSION}" : "" ) @@ -293,7 +301,9 @@ function "get_base_image" { target "base" { dockerfile = "Dockerfile" args = { - BASE = get_base_image(BASE_IMAGE, OS_DISTRIBUTION, OS_VERSION, IS_UKI) + BASE = get_base_image(BASE_IMAGE, OS_DISTRIBUTION, + normalized_os_version(OS_DISTRIBUTION, OS_VERSION), + IS_UKI) OS_DISTRIBUTION = OS_DISTRIBUTION PROXY_CERT_PATH = PROXY_CERT_PATH HTTP_PROXY = HTTP_PROXY @@ -310,7 +320,7 @@ target "base-image" { } args = { OS_DISTRIBUTION = OS_DISTRIBUTION - OS_VERSION = OS_VERSION + OS_VERSION = normalized_os_version(OS_DISTRIBUTION, OS_VERSION) IS_JETSON = IS_JETSON IS_UKI = IS_UKI UPDATE_KERNEL = UPDATE_KERNEL @@ -324,15 +334,19 @@ target "base-image" { secret = ["id=ubuntu_pro_key,env=UBUNTU_PRO_KEY"] } +variable "provider_prefix" { + default = "docker-image://${SPECTRO_PUB_REPO}/edge/kairos-io/provider" +} + function "get_provider_base" { - params = [k8s_distribution, spectro_pub_repo, kubeadm_version, k3s_version, rke2_version, nodeadm_version, canonical_version] + params = [k8s_distribution, kubeadm_version, k3s_version, rke2_version, nodeadm_version, canonical_version] result = ( - k8s_distribution == "kubeadm" ? "docker-image://${spectro_pub_repo}/edge/kairos-io/provider-kubeadm:${kubeadm_version}" : - k8s_distribution == "kubeadm-fips" ? "docker-image://${spectro_pub_repo}/edge/kairos-io/provider-kubeadm:${kubeadm_version}" : - k8s_distribution == "k3s" ? "docker-image://${spectro_pub_repo}/edge/kairos-io/provider-k3s:${k3s_version}" : - k8s_distribution == "rke2" ? "docker-image://${spectro_pub_repo}/edge/kairos-io/provider-rke2:${rke2_version}" : - k8s_distribution == "nodeadm" ? "docker-image://${spectro_pub_repo}/edge/kairos-io/provider-nodeadm:${nodeadm_version}" : - k8s_distribution == "canonical" ? "docker-image://${spectro_pub_repo}/edge/kairos-io/provider-canonical:${canonical_version}" : + k8s_distribution == "kubeadm" ? "${provider_prefix}-kubeadm:${kubeadm_version}" : + k8s_distribution == "kubeadm-fips" ? "${provider_prefix}-kubeadm:${kubeadm_version}" : + k8s_distribution == "k3s" ? "${provider_prefix}-k3s:${k3s_version}" : + k8s_distribution == "rke2" ? "${provider_prefix}-rke2:${rke2_version}" : + k8s_distribution == "nodeadm" ? "${provider_prefix}-nodeadm:${nodeadm_version}" : + k8s_distribution == "canonical" ? "${provider_prefix}-canonical:${canonical_version}" : "" ) } @@ -362,10 +376,8 @@ target "provider-image" { platforms = ["linux/${ARCH}"] contexts = { base-image = "target:base-image" - // kairos-provider-image = "target:kairos-provider-image" kairos-provider-image = get_provider_base( K8S_DISTRIBUTION, - SPECTRO_PUB_REPO, KUBEADM_PROVIDER_VERSION, K3S_PROVIDER_VERSION, RKE2_PROVIDER_VERSION, @@ -407,7 +419,9 @@ target "uki-provider-image" { stylus-image = "docker-image://${STYLUS_BASE}" } args = { - BASE_IMAGE = get_base_image(BASE_IMAGE, OS_DISTRIBUTION, OS_VERSION, IS_UKI) + BASE_IMAGE = get_base_image(BASE_IMAGE, OS_DISTRIBUTION, + normalized_os_version(OS_DISTRIBUTION, OS_VERSION), + IS_UKI) UBUNTU_IMAGE = get_ubuntu_image(FIPS_ENABLED, SPECTRO_PUB_REPO) EDGE_CUSTOM_CONFIG = EDGE_CUSTOM_CONFIG IMAGE_PATH = IMAGE_PATH @@ -456,8 +470,7 @@ target "iso-image" { IS_UKI = IS_UKI IS_CLOUD_IMAGE = IS_CLOUD_IMAGE } - # MAAS uses latest tag, non-MAAS uses version tag - tags = IS_MAAS ? ["palette-installer-image:latest"] : ["palette-installer-image:${IMAGE_TAG}"] + tags = ["palette-installer-image:${IMAGE_TAG}"] output = ["type=docker"] } @@ -622,31 +635,25 @@ target "iso-efi-size-check" { output = ["type=local,dest=./build/"] } -target "cloud-image" { - dockerfile = "dockerfiles/Dockerfile.cloud-image" - context = "." - target = "output" - platforms = ["linux/${ARCH}"] - contexts = { - iso-image = "target:iso-image" - } - args = { - AURORABOOT_IMAGE = AURORABOOT_IMAGE - ARCH = ARCH - } - output = ["type=local,dest=./build/"] +variable "RAW_IMAGE_DIR" { + default = "./build/raw-image" +} + +target "iso-image-cloud" { + inherits = ["iso-image"] + tags = ["palette-installer-image-cloud:latest"] } target "aws-cloud-image" { dockerfile = "dockerfiles/Dockerfile.aws-cloud-image" context = "." - target = "output" platforms = ["linux/${ARCH}"] contexts = { - cloud-image = "target:cloud-image" + raw-image = RAW_IMAGE_DIR } args = { UBUNTU_IMAGE = get_ubuntu_image(FIPS_ENABLED, SPECTRO_PUB_REPO) + ARCH = ARCH REGION = REGION S3_BUCKET = S3_BUCKET S3_KEY = S3_KEY @@ -656,5 +663,4 @@ target "aws-cloud-image" { "id=AWS_ACCESS_KEY_ID,env=AWS_ACCESS_KEY_ID", "id=AWS_SECRET_ACCESS_KEY,env=AWS_SECRET_ACCESS_KEY" ] - output = ["type=local,dest=./build/"] } diff --git a/dockerfiles/Dockerfile.aws-cloud-image b/dockerfiles/Dockerfile.aws-cloud-image index 60cd9334..1e9ca89b 100644 --- a/dockerfiles/Dockerfile.aws-cloud-image +++ b/dockerfiles/Dockerfile.aws-cloud-image @@ -5,13 +5,18 @@ FROM ${UBUNTU_IMAGE} AS builder ARG REGION ARG S3_BUCKET ARG S3_KEY +ARG ARCH # Install dependencies RUN apt-get update && apt-get install -y unzip ca-certificates curl && \ rm -rf /var/lib/apt/lists/* # Install AWS CLI -RUN curl --fail -s "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \ +RUN AWS_CLI_ARCH=$(case "$ARCH" in \ + amd64) echo "x86_64" ;; \ + arm64) echo "aarch64" ;; \ + esac) && \ + curl --fail -s "https://awscli.amazonaws.com/awscli-exe-linux-${AWS_CLI_ARCH}.zip" -o "awscliv2.zip" && \ unzip -q awscliv2.zip -d aws_install_temp && \ ./aws_install_temp/aws/install && \ rm -rf awscliv2.zip aws_install_temp @@ -19,7 +24,7 @@ RUN curl --fail -s "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o WORKDIR /workdir # Copy the cloud image output -COPY --from=cloud-image / /workdir/ +COPY --from=raw-image / /workdir/raw-image/ # Copy the AMI creation script COPY cloud-images/scripts/create-raw-to-ami.sh /workdir/create-raw-to-ami.sh @@ -28,7 +33,7 @@ COPY cloud-images/scripts/create-raw-to-ami.sh /workdir/create-raw-to-ami.sh RUN --mount=type=secret,id=AWS_PROFILE \ --mount=type=secret,id=AWS_ACCESS_KEY_ID \ --mount=type=secret,id=AWS_SECRET_ACCESS_KEY \ - RAW_FILE_PATH=$(ls /workdir/*.raw) && \ + RAW_FILE_PATH=$(ls /workdir/raw-image/*.raw) && \ echo "RAW_FILE_PATH: $RAW_FILE_PATH" && \ if [ ! -f "$RAW_FILE_PATH" ]; then \ echo "Error: RAW file not found." && \ @@ -40,8 +45,6 @@ RUN --mount=type=secret,id=AWS_PROFILE \ fi && \ /workdir/create-raw-to-ami.sh "$RAW_FILE_PATH" -FROM scratch AS output -COPY --from=builder /workdir/ / diff --git a/dockerfiles/Dockerfile.cloud-image b/dockerfiles/Dockerfile.cloud-image deleted file mode 100644 index 6496a978..00000000 --- a/dockerfiles/Dockerfile.cloud-image +++ /dev/null @@ -1,46 +0,0 @@ -ARG AURORABOOT_IMAGE - -FROM ${AURORABOOT_IMAGE} AS builder - -ARG ARCH=amd64 - -# Copy the cloud-init config file -COPY cloud-images/config/user-data.yaml /config.yaml - -# Copy the iso-image content -COPY --from=iso-image / /iso-source/ - -RUN mkdir -p /output - -# Run auroraboot to create the cloud image (raw disk) -RUN /usr/bin/auroraboot \ - --debug \ - --set "disable_http_server=true" \ - --set "container_image=oci:/iso-source" \ - --set "disable_netboot=true" \ - --set "disk.raw=true" \ - --set "state_dir=/output" \ - --set "arch=${ARCH}" \ - --cloud-config /config.yaml - -FROM scratch AS output -COPY --from=builder /output/ / - - - - - - - - - - - - - - - - - - - From 46905021df1d932d6ea9bff4981d25d761f65a16 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Tue, 9 Dec 2025 21:28:12 +0000 Subject: [PATCH 34/40] refactor base alpine image and iso disk image changes --- docker-bake.hcl | 27 +++++++++++++++++++++++---- dockerfiles/Dockerfile.alpine | 20 ++++++++++++++++++-- dockerfiles/Dockerfile.install-k8s | 8 +------- dockerfiles/Dockerfile.iso-disk-image | 5 ----- dockerfiles/Dockerfile.third-party | 3 +-- 5 files changed, 43 insertions(+), 20 deletions(-) delete mode 100644 dockerfiles/Dockerfile.iso-disk-image diff --git a/docker-bake.hcl b/docker-bake.hcl index e530881e..24347072 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -356,10 +356,10 @@ target "install-k8s" { target = "install-k8s" platforms = ["linux/${ARCH}"] contexts = { + alpine-certs = "target:alpine-certs" third-party-luet = "target:third-party-luet" } args = { - ALPINE_IMG = ALPINE_IMG ARCH = ARCH K8S_DISTRIBUTION = K8S_DISTRIBUTION K8S_VERSION = K8S_VERSION @@ -579,9 +579,11 @@ target "internal-slink" { target "third-party-luet" { dockerfile = "dockerfiles/Dockerfile.third-party" target = "third-party" + contexts = { + alpine-certs = "target:alpine-certs" + } args = { SPECTRO_THIRD_PARTY_IMAGE = SPECTRO_THIRD_PARTY_IMAGE - ALPINE_IMG = ALPINE_IMG binary = "luet" BIN_TYPE = BIN_TYPE ARCH = ARCH @@ -592,9 +594,11 @@ target "third-party-luet" { target "third-party-etcdctl" { dockerfile = "dockerfiles/Dockerfile.third-party" target = "third-party" + contexts = { + alpine-certs = "target:alpine-certs" + } args = { SPECTRO_THIRD_PARTY_IMAGE = SPECTRO_THIRD_PARTY_IMAGE - ALPINE_IMG = ALPINE_IMG binary = "etcdctl" BIN_TYPE = BIN_TYPE ARCH = ARCH @@ -603,17 +607,21 @@ target "third-party-etcdctl" { } target "iso-disk-image" { - dockerfile = "dockerfiles/Dockerfile.iso-disk-image" platforms = ["linux/${ARCH}"] contexts = { build-iso = IS_UKI ? "target:build-uki-iso" : "target:build-iso" } + dockerfile-inline = <<-EOF + FROM scratch + COPY --from=build-iso /*.iso /disk/ + EOF tags = ["${IMAGE_REGISTRY}/${IMAGE_REPO}/${ISO_NAME}:${IMAGE_TAG}"] output = ["type=image,push=true"] } target "alpine-all" { dockerfile = "dockerfiles/Dockerfile.alpine" + target = "alpine" platforms = ["linux/amd64", "linux/arm64"] args = { ALPINE_BASE_IMAGE = ALPINE_BASE_IMAGE @@ -622,6 +630,17 @@ target "alpine-all" { output = ["type=image,push=true"] } +# Alpine with custom certificates from build context - used as base for install-k8s and third-party targets +target "alpine-certs" { + dockerfile = "dockerfiles/Dockerfile.alpine" + context = "." + target = "alpine-certs" + platforms = ["linux/${ARCH}"] + args = { + ALPINE_BASE_IMAGE = ALPINE_BASE_IMAGE + } +} + target "iso-efi-size-check" { dockerfile = "dockerfiles/Dockerfile.iso-efi-size-check" context = "." diff --git a/dockerfiles/Dockerfile.alpine b/dockerfiles/Dockerfile.alpine index 509201e3..dab424a9 100644 --- a/dockerfiles/Dockerfile.alpine +++ b/dockerfiles/Dockerfile.alpine @@ -1,8 +1,24 @@ ARG ALPINE_BASE_IMAGE -FROM ${ALPINE_BASE_IMAGE} +FROM ${ALPINE_BASE_IMAGE} AS alpine-base RUN apk add --no-cache bash curl jq ca-certificates upx + +FROM alpine-base AS alpine + # In FIPS mode, this may fail due to OpenSSL FIPS constraints. -RUN update-ca-certificates || true \ No newline at end of file +RUN update-ca-certificates || true + + +FROM alpine-base AS alpine-certs + +COPY . /tmp/build-context/ + +# Copy custom certs if present, update CA store +# Note: update-ca-certificates may fail in FIPS mode due to OpenSSL constraints +RUN if [ -d "/tmp/build-context/certs" ]; then \ + cp -r /tmp/build-context/certs/. /etc/ssl/certs/; \ + fi && \ + update-ca-certificates || true && \ + rm -rf /tmp/build-context \ No newline at end of file diff --git a/dockerfiles/Dockerfile.install-k8s b/dockerfiles/Dockerfile.install-k8s index 48b1eb22..0a2ef961 100644 --- a/dockerfiles/Dockerfile.install-k8s +++ b/dockerfiles/Dockerfile.install-k8s @@ -1,7 +1,6 @@ ARG ARCH -ARG ALPINE_IMG -FROM --platform=linux/${ARCH} ${ALPINE_IMG} AS install-k8s +FROM --platform=linux/${ARCH} alpine-certs AS install-k8s ARG K8S_DISTRIBUTION ARG K8S_VERSION @@ -11,11 +10,6 @@ ARG SPECTRO_LUET_REPO ARG ARCH ARG LUET_REPO -COPY . /tmp/build-context/ - -RUN [ -d "/tmp/build-context/certs" ] && cp -r /tmp/build-context/certs/. /etc/ssl/certs/ || true -RUN update-ca-certificates - COPY --from=third-party-luet /WORKDIR/luet /usr/bin/luet WORKDIR /output diff --git a/dockerfiles/Dockerfile.iso-disk-image b/dockerfiles/Dockerfile.iso-disk-image deleted file mode 100644 index 5d0227ce..00000000 --- a/dockerfiles/Dockerfile.iso-disk-image +++ /dev/null @@ -1,5 +0,0 @@ -FROM scratch - -COPY --from=build-iso /*.iso /disk/ - -LABEL org.opencontainers.image.title="CanvOS Installer Disk Image" diff --git a/dockerfiles/Dockerfile.third-party b/dockerfiles/Dockerfile.third-party index 2e71339b..cdb8ec98 100644 --- a/dockerfiles/Dockerfile.third-party +++ b/dockerfiles/Dockerfile.third-party @@ -1,10 +1,9 @@ ARG SPECTRO_THIRD_PARTY_IMAGE ARG TARGETPLATFORM -ARG ALPINE_IMG FROM --platform=${TARGETPLATFORM} ${SPECTRO_THIRD_PARTY_IMAGE} AS source -FROM --platform=${TARGETPLATFORM} ${ALPINE_IMG} AS third-party +FROM --platform=${TARGETPLATFORM} alpine-certs AS third-party ARG ARCH ARG BIN_TYPE From a20bcec0cdf06cfcc474e267fd0776b22dc43d8f Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Thu, 11 Dec 2025 05:05:49 +0000 Subject: [PATCH 35/40] build iso arch fix --- docker-bake.hcl | 1 - dockerfiles/Dockerfile.build-iso | 2 -- 2 files changed, 3 deletions(-) diff --git a/docker-bake.hcl b/docker-bake.hcl index 24347072..2c218af9 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -483,7 +483,6 @@ target "build-iso" { iso-image = "target:iso-image" } args = { - ARCH = ARCH ISO_NAME = ISO_NAME CLUSTERCONFIG = CLUSTERCONFIG EDGE_CUSTOM_CONFIG = EDGE_CUSTOM_CONFIG diff --git a/dockerfiles/Dockerfile.build-iso b/dockerfiles/Dockerfile.build-iso index 73314aed..92d4c077 100644 --- a/dockerfiles/Dockerfile.build-iso +++ b/dockerfiles/Dockerfile.build-iso @@ -2,7 +2,6 @@ ARG AURORABOOT_IMAGE FROM ${AURORABOOT_IMAGE} AS builder -ARG ARCH=amd64 ARG ISO_NAME ARG CLUSTERCONFIG ARG EDGE_CUSTOM_CONFIG @@ -58,7 +57,6 @@ RUN /usr/bin/auroraboot \ --output /output \ --override-name ${ISO_NAME} \ --overlay-iso /overlay \ - --set "arch=${ARCH}" \ $(if [ -f /validated/config.yaml ] && [ -s /validated/config.yaml ]; then echo "--cloud-config /validated/config.yaml"; fi) \ dir:/iso-source From 7745df692a6147bc68169f2bb8f3509a4e6c88f0 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Thu, 11 Dec 2025 12:34:22 +0000 Subject: [PATCH 36/40] arch fix auroraboot --- Makefile | 2 +- docker-bake.hcl | 5 +++-- dockerfiles/Dockerfile.build-uki-iso | 1 - dockerfiles/Dockerfile.slink | 3 ++- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index a992af40..4901e8cc 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,7 @@ PUSH_ARGS = $(if $(filter true,$(PUSH)),--set *.output=type=image$(comma)push=$( # Dry run flag DRY_RUN_ARGS = $(if $(filter true,$(DRY_RUN)),--print,) # Progress output flag -DOCKER_BUILD_OUT = $(if $(filter true,$(DEBUG)),--progress=plain,) +DOCKER_BUILD_OUT = $(if $(filter true,$(DEBUG)),--progress=plain --debug,) # No cache flag DOCKER_NO_CACHE = $(if $(filter true,$(NO_CACHE)),--no-cache,) diff --git a/docker-bake.hcl b/docker-bake.hcl index 2c218af9..2736acf2 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -8,7 +8,7 @@ variable "ARCH" { } variable "SPECTRO_PUB_REPO" { - default = FIPS_ENABLED ? "us-east1-docker.pkg.dev/spectro-images/dev-fips/arun" : "us-east1-docker.pkg.dev/spectro-images/dev/arun" + default = FIPS_ENABLED ? "us-docker.pkg.dev/palette-images-fips" : "us-docker.pkg.dev/palette-images" } variable "SPECTRO_THIRD_PARTY_IMAGE" { @@ -564,13 +564,14 @@ target "uki-byok" { target "internal-slink" { dockerfile = "dockerfiles/Dockerfile.slink" context = "." + platforms = ["linux/${ARCH}"] args = { SPECTRO_PUB_REPO = SPECTRO_PUB_REPO GOLANG_VERSION = GOLANG_VERSION BIN = "slink" SRC = "cmd/slink/slink.go" GOOS = "linux" - GOARCH = "amd64" + GOARCH = ARCH } output = ["type=local,dest=build"] } diff --git a/dockerfiles/Dockerfile.build-uki-iso b/dockerfiles/Dockerfile.build-uki-iso index 375c3ad8..b9e63326 100644 --- a/dockerfiles/Dockerfile.build-uki-iso +++ b/dockerfiles/Dockerfile.build-uki-iso @@ -66,7 +66,6 @@ RUN --mount=type=secret,id=db_key,target=/keys/db.key \ --output /iso \ --override-name "${ISO_NAME}" \ --overlay-iso /overlay \ - --arch "$ARCH" \ dir:/iso-source; \ elif [ "$ARCH" = "amd64" ]; then \ /usr/bin/auroraboot \ diff --git a/dockerfiles/Dockerfile.slink b/dockerfiles/Dockerfile.slink index aa42d9bb..f1e80fdc 100644 --- a/dockerfiles/Dockerfile.slink +++ b/dockerfiles/Dockerfile.slink @@ -12,7 +12,7 @@ COPY internal /build/internal WORKDIR /build/internal ARG VERSION=dev -ARG BIN=slink +ARG BIN ARG SRC ARG GOOS ARG GOARCH @@ -27,4 +27,5 @@ RUN go mod download RUN go-build-static.sh -a -o /build/bin/${BIN} ./${SRC} FROM scratch AS export +ARG BIN COPY --from=build /build/bin/${BIN} /${BIN} \ No newline at end of file From c7cb2b378de1dd1133f2ccd118b3b87102d1421a Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Thu, 11 Dec 2025 15:51:16 +0000 Subject: [PATCH 37/40] revert ubuntu-kairos-base dockerfile --- Earthfile | 6 - dockerfiles/Dockerfile.aws-cloud-image | 20 -- ubuntu-kairos-base/Dockerfile | 360 +++++++++++++++++++++++++ 3 files changed, 360 insertions(+), 26 deletions(-) create mode 100644 ubuntu-kairos-base/Dockerfile diff --git a/Earthfile b/Earthfile index a77583dc..4f41b732 100644 --- a/Earthfile +++ b/Earthfile @@ -185,8 +185,6 @@ BASE_ALPINE: COPY --if-exists certs/ /etc/ssl/certs/ RUN update-ca-certificates - SAVE IMAGE --push gcr.io/spectro-dev-public/canvos/alpine:$ALPINE_TAG - iso-image-rootfs: FROM --platform=linux/${ARCH} +iso-image SAVE ARTIFACT --keep-own /. rootfs @@ -871,10 +869,6 @@ iso-image: RUN rm -f /usr/bin/luet END COPY overlay/files/ / - IF [ "$IS_CLOUD_IMAGE" = "true" ] - COPY cloud-images/workaround/grubmenu.cfg /etc/kairos/branding/grubmenu.cfg - COPY cloud-images/workaround/custom-post-reset.yaml /system/oem/custom-post-reset.yaml - END IF [ -f /etc/logrotate.d/stylus.conf ] RUN chmod 644 /etc/logrotate.d/stylus.conf diff --git a/dockerfiles/Dockerfile.aws-cloud-image b/dockerfiles/Dockerfile.aws-cloud-image index 1e9ca89b..738e9cf5 100644 --- a/dockerfiles/Dockerfile.aws-cloud-image +++ b/dockerfiles/Dockerfile.aws-cloud-image @@ -44,23 +44,3 @@ RUN --mount=type=secret,id=AWS_PROFILE \ echo "Proceeding with creation of AMI..."; \ fi && \ /workdir/create-raw-to-ami.sh "$RAW_FILE_PATH" - - - - - - - - - - - - - - - - - - - - diff --git a/ubuntu-kairos-base/Dockerfile b/ubuntu-kairos-base/Dockerfile new file mode 100644 index 00000000..df8aadf0 --- /dev/null +++ b/ubuntu-kairos-base/Dockerfile @@ -0,0 +1,360 @@ +# This file is auto-generated with the command: earthly +kairos-dockerfile --FAMILY=ubuntu +############################################################### +#### ARGS #### +############################################################### +ARG FAMILY=ubuntu +# Currently supported flavors are: +# - ubuntu +ARG FLAVOR +# - 20.04 +# - 22.04 +# - 23.04 +ARG FLAVOR_RELEASE +# Currently supported models are: +# - generic +# - rpi4 +# - rpi3 +ARG MODEL=generic +ARG BASE_IMAGE +ARG VARIANT +ARG VERSION +ARG FRAMEWORK_VERSION=v2.11.7 +# Not to be confused with the concept of MODEL, this is either fips or generic +ARG SECURITY_PROFILE=generic +# TARGETARCH is used to determine the architecture of the image +# it is already set by Docker so it doesn't need to be defined here + +############################################################### +#### Upstream Images #### +############################################################### +FROM ${BASE_IMAGE} AS ubuntu-23.04-upstream + +FROM ${BASE_IMAGE} AS ubuntu-20.04-upstream + +FROM ${BASE_IMAGE} AS ubuntu-22.04-upstream + + +############################################################### +#### Pre-Process Common to All #### +############################################################### +FROM ${FLAVOR}-${FLAVOR_RELEASE}-upstream AS common +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + gnupg \ + software-properties-common \ + && add-apt-repository ppa:oibaf/test \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + conntrack \ + console-data \ + cloud-guest-utils \ + coreutils \ + cryptsetup \ + curl \ + debianutils \ + dosfstools \ + dracut \ + dracut-network \ + e2fsprogs \ + fdisk \ + file \ + gawk \ + gdisk \ + grub2-common \ + haveged \ + iproute2 \ + iptables \ + iputils-ping \ + jq \ + kbd \ + krb5-locales \ + less \ + lldpd \ + lvm2 \ + nano \ + nbd-client \ + neovim \ + nohang \ + open-iscsi \ + open-vm-tools \ + openssh-server \ + parted \ + rsync \ + snmpd \ + squashfs-tools \ + sudo \ + systemd \ + systemd-timesyncd \ + tar \ + ubuntu-advantage-tools \ + xz-utils \ + zstd \ + && apt-get remove -y unattended-upgrades && apt-get clean && rm -rf /var/lib/apt/lists/* + +############################################################### +#### Common to a Single Architecture #### +############################################################### + +FROM common AS amd64 +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + dmsetup \ + efibootmgr \ + grub2 \ + grub-efi-amd64-bin \ + grub-efi-amd64-signed \ + grub-pc-bin \ + isc-dhcp-common \ + mdadm \ + ncurses-term \ + networkd-dispatcher \ + nfs-common \ + os-prober \ + packagekit-tools \ + publicsuffix \ + shared-mime-info \ + thermald \ + xdg-user-dirs \ + xxd \ + zerofree \ + zfsutils-linux \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + +FROM common AS arm64 +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + grub-efi-arm64 \ + grub-efi-arm64-bin \ + grub-efi-arm64-signed \ + keyutils \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + +############################################################### +#### Common to an Arch and Flavor #### +############################################################### +FROM ${TARGETARCH} AS base-ubuntu-20.04 +RUN apt-get update && apt-get install -y --no-install-recommends \ + file \ + fuse \ + patch \ + policykit-1 \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + +FROM ${TARGETARCH} AS base-ubuntu-22.04 +RUN apt-get update && apt-get install -y --no-install-recommends \ + dracut-live \ + firmware-sof-signed \ + fuse3 \ + pigz \ + polkitd \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + +FROM base-ubuntu-20.04 AS amd64-base-ubuntu-20.04 +# If a kernel is already installed, don't try to install it again, this way the base image can +# be non-hwe for older releases +RUN apt-get update +RUN [ -z "$(ls -A /lib/modules/)" ] && apt-get install -y --no-install-recommends \ + linux-image-generic-hwe-20.04 || true +RUN apt-get clean && rm -rf /var/lib/apt/lists/* + +FROM base-ubuntu-22.04 AS amd64-base-ubuntu-22.04 +RUN apt-get update +# If a kernel is already installed, don't try to install it again, this way the base image can +# be non-hwe for older releases +RUN [ -z "$(ls -A /lib/modules)" ] && apt-get install -y --no-install-recommends \ + linux-image-generic-hwe-22.04 || true +RUN apt-get clean && rm -rf /var/lib/apt/lists/* + +FROM amd64-base-ubuntu-22.04 AS amd64-ubuntu-23.04 +FROM amd64-base-ubuntu-22.04 AS amd64-ubuntu-22.04 +FROM amd64-base-ubuntu-20.04 AS amd64-ubuntu-20.04 + +FROM base-ubuntu-22.04 AS arm64-ubuntu-23.04 +FROM base-ubuntu-22.04 AS arm64-ubuntu-22.04 +FROM base-ubuntu-20.04 AS arm64-ubuntu-20.04 + +############################################################### +#### Common to a Single Model #### +############################################################### +FROM ${TARGETARCH}-${FLAVOR}-${FLAVOR_RELEASE} AS generic +RUN apt-get update && apt-get install -y --no-install-recommends \ + linux-base \ + qemu-guest-agent \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + +FROM arm64-${FLAVOR}-${FLAVOR_RELEASE} AS rpicommon +RUN apt-get update && apt-get install -y --no-install-recommends \ + linux-raspi \ + && apt-get clean && rm -rf /var/lib/apt/lists/* +COPY rpi/config.txt /boot/config.txt + +FROM rpicommon AS ubuntu-20.04-rpi +RUN apt-get update && apt-get install -y --no-install-recommends \ + linux-firmware-raspi2 \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + +FROM rpicommon AS ubuntu-23.04-rpi +RUN apt-get update && apt-get install -y --no-install-recommends \ + linux-firmware-raspi \ + linux-modules-extra-raspi \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + +FROM generic AS amd64-ubuntu-23.04-generic +FROM generic AS amd64-ubuntu-22.04-generic +FROM generic AS amd64-ubuntu-20.04-generic +FROM generic AS arm64-ubuntu-23.04-generic +FROM ubuntu-23.04-rpi AS arm64-ubuntu-23.04-rpi3 +FROM ubuntu-23.04-rpi AS arm64-ubuntu-23.04-rpi4 +FROM ubuntu-23.04-rpi AS arm64-ubuntu-22.04-rpi3 +FROM ubuntu-23.04-rpi AS arm64-ubuntu-22.04-rpi4 +FROM ubuntu-20.04-rpi AS arm64-ubuntu-20.04-rpi3 +FROM ubuntu-20.04-rpi AS arm64-ubuntu-20.04-rpi4 +FROM ubuntu-20.04-upstream AS arm64-ubuntu-20.04-nvidia-jetson-agx-orin + +############################################################### +#### Common to a Single Flavor #### +############################################################### +FROM ${TARGETARCH}-${FLAVOR}-${FLAVOR_RELEASE}-${MODEL} AS ubuntu-23.04 +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + dbus-user-session \ + pkg-config \ + systemd-hwe-hwdb \ + systemd-resolved \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + +FROM ${TARGETARCH}-${FLAVOR}-${FLAVOR_RELEASE}-${MODEL} AS ubuntu-22.04 +RUN apt-get update +# If the generic kernel is installed we don't want to install HWE related packages +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +RUN apt-cache search linux-image-generic | grep hwe &> /dev/null && apt-get install -y --no-install-recommends \ + systemd-hwe-hwdb +RUN apt-get clean && rm -rf /var/lib/apt/lists/* + +FROM ${TARGETARCH}-${FLAVOR}-${FLAVOR_RELEASE}-${MODEL} AS ubuntu-20.04 + +############################################################### +#### Post-Process Common to All #### +############################################################### +FROM ${FLAVOR}-${FLAVOR_RELEASE} AS all + +# compress firmware +RUN find /usr/lib/firmware -type f -execdir zstd --rm -9 {} \+ +# compress modules +RUN find /usr/lib/modules -type f -name "*.ko" -execdir zstd --rm -9 {} \+ + +RUN systemctl enable systemd-networkd +RUN systemctl enable ssh + +# Fixup sudo perms +RUN chown root:root /usr/bin/sudo && chmod 4755 /usr/bin/sudo + +RUN journalctl --vacuum-size=1K && rm /etc/machine-id && rm /var/lib/dbus/machine-id && rm /etc/hostname + +FROM --platform="linux/${TARGETARCH}" quay.io/kairos/framework:${FRAMEWORK_VERSION}_${SECURITY_PROFILE} AS framework + +FROM all AS base-kairos + +# Symlinks to make elemental installer work +RUN ORIG=/usr/sbin/grub-install; DEST=/usr/sbin/grub2-install; [ -e $ORIG ] && [ ! -e $DEST ] && ln -s $ORIG $DEST || true +RUN ORIG=/usr/bin/grub-editenv; DEST=/usr/sbin/grub2-editenv; [ -e $ORIG ] && [ ! -e $DEST ] && ln -s $ORIG $DEST || true + +# Originally done in Earthly +COPY --from=framework / / + +RUN rm -rf /etc/ssh/ssh_host_* + +COPY naming.sh /usr/local/bin/naming.sh +COPY which-init.sh /usr/local/bin/which-init.sh + +RUN sed -i -n '/KAIROS_/!p' /etc/os-release + +# need to be defined after FROM for them to be replaced in the RUN bellow +ARG FLAVOR +ARG FLAVOR_RELEASE +ARG VARIANT +ARG OS_ID=kairos +ARG HOME_URL="https://github.com/kairos-io/kairos" +ARG BUG_REPORT_URL="https://github.com/kairos-io/kairos/issues" +ARG GITHUB_REPO="kairos-io/kairos" +# TODO: merge these +ARG VERSION +ARG FAMILY +ARG MODEL +ARG REGISTRY_AND_ORG="quay.io/kairos" +ARG K3S_VERSION +ARG TARGETARCH +ARG OS_NAME=kairos-${VARIANT}-${FLAVOR}-${FLAVOR_RELEASE} +ENV KAIROS_VERSION="${VERSION}${K3S_VERSION:+-k3s$K3S_VERSION}" +ENV OS_VERSION=${KAIROS_VERSION} +ENV OS_LABEL=${KAIROS_VERSION} +RUN OS_LABEL=$(naming.sh container_artifact_label) \ + OS_REPO=$(naming.sh container_artifact_repo) \ + ARTIFACT=$(naming.sh bootable_artifact_name) \ + envsubst >>/etc/os-release /IMAGE + +RUN rm -rf /etc/machine-id + +FROM base-kairos AS kairos-core + +FROM base-kairos AS kairos-standard +ARG K3S_VERSION +LABEL io.kairos.k3s_version="${K3S_VERSION}" +RUN luet install -y system/provider-kairos +RUN luet install -y "k8s/k3s-$(which-init.sh)@${K3S_VERSION}" utils/edgevpn utils/k9s utils/nerdctl container/kubectl utils/kube-vip + +FROM kairos-${VARIANT} AS kairos-final +ARG BASE_IMAGE +ARG VARIANT +ARG FAMILY +ARG FLAVOR +ARG FLAVOR_RELEASE +ARG MODEL +ARG VERSION +ARG FRAMEWORK_VERSION +ARG SECURITY_PROFILE +LABEL org.opencontainers.image.authors="Kairos Maintainers " +LABEL org.opencontainers.image.licenses="Apache-2.0" +LABEL org.opencontainers.image.url="https://github.com/kairos-io/kairos" +LABEL org.opencontainers.image.source="https://github.com/kairos-io/kairos.git" +LABEL io.kairos.base_image="${BASE_IMAGE}" +LABEL io.kairos.variant="${VARIANT}" +LABEL io.kairos.family="${FAMILY}" +LABEL io.kairos.flavor="${FLAVOR}" +LABEL io.kairos.flavor_release="${FLAVOR_RELEASE}" +LABEL io.kairos.model="${MODEL}" +LABEL io.kairos.version="${VERSION}" +LABEL io.kairos.framework-version="${FRAMEWORK_VERSION}" +LABEL io.kairos.security-profile="${SECURITY_PROFILE}" + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +RUN luet database get-all-installed --output /etc/kairos/versions.yaml + +# TODO what about caches? +RUN kernel=$(ls /lib/modules | head -n1) && depmod -a "${kernel}" +# Regenerate initrd if necessary, proper config files with immucore and custom initrd should already be in there installed by framework +# for systemd distros +RUN if [ -f "/usr/bin/dracut" ]; then \ + kernel=$(ls /lib/modules | head -n1) && \ + dracut -f "/boot/initrd-${kernel}" "${kernel}" && \ + ln -sf "initrd-${kernel}" /boot/initrd; \ + fi +# for alpine (openrc based) +RUN if [ -f "/sbin/mkinitfs" ]; then \ + kernel=$(ls /lib/modules | head -n1) && \ + mkinitfs -o /boot/initrd "${kernel}"; \ + fi + +# symlink kernel to /boot/vmlinuz +RUN kernel=$(ls /boot/vmlinuz-* 2>/dev/null | head -n1) && if [ -e "$kernel" ]; then ln -sf "$kernel" /boot/vmlinuz; fi || true +RUN kernel=$(ls /boot/Image-* 2>/dev/null | head -n1) && if [ -e "$kernel" ]; then ln -sf "$kernel" /boot/vmlinuz; fi || true + +# this is generally present on rhel based systems, but it doesn't hurt to remove in any case +RUN rm -rf /boot/initramfs-* || true + +RUN rm -rf /tmp/* +RUN luet cleanup +RUN rm -rf /var/luet \ No newline at end of file From ddbc8cf2f979c31cb55a848cb35a15a1bd1e28b1 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Thu, 11 Dec 2025 15:53:56 +0000 Subject: [PATCH 38/40] remove unwanted files --- .github/workflows/release.yaml | 48 +++++++++++++++++++++++++++++ .github/workflows/test-workflow.yml | 14 --------- 2 files changed, 48 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/release.yaml delete mode 100644 .github/workflows/test-workflow.yml diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 00000000..c50d3d68 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,48 @@ +# name: Release + +# on: +# push: +# tags: +# - v* + +# permissions: +# contents: write + +# concurrency: +# group: ${{ github.workflow }}-${{ github.ref }} +# cancel-in-progress: true + + +# jobs: +# release-iso-image: +# runs-on: ubuntu-latest +# steps: +# - name: Login to Docker Hub +# uses: docker/login-action@v2 +# with: +# username: ${{ secrets.DOCKERHUB_USERNAME }} +# password: ${{ secrets.DOCKERHUB_TOKEN }} +# - uses: actions/checkout@v3 +# - name: create .netrc file +# env: +# REPO_USER: ${{ secrets.REPO_USER }} +# REPO_TOKEN: ${{ secrets.REPO_TOKEN }} +# shell: bash +# run: | +# echo "machine github.com" > .netrc +# echo " login $REPO_USER" >> .netrc +# echo " password $REPO_TOKEN" >> .netrc +# echo "machine api.github.com" >> .netrc +# echo " login $REPO_USER" >> .netrc +# echo " password $REPO_TOKEN" >> .netrc +# - uses: earthly/actions-setup@v1 +# - run: ./earthly --ci --push -P --output +build-all-images --PE_VERSION=${{ github.ref_name }} +# - run: | +# if [[ "${{ github.ref }}" =~ .*-.*$ ]]; then +# echo "IS_PRERELEASE=true" > $GITHUB_ENV +# fi +# - uses: softprops/action-gh-release@v1 +# with: +# files: build/* +# prerelease: ${{ env.IS_PRERELEASE }} +# generate_release_notes: true \ No newline at end of file diff --git a/.github/workflows/test-workflow.yml b/.github/workflows/test-workflow.yml deleted file mode 100644 index f68679c0..00000000 --- a/.github/workflows/test-workflow.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: Test Dispatch -on: - workflow_dispatch: - inputs: - test_input: - description: 'Test input' - required: false - type: string - default: 'hello' -jobs: - test: - runs-on: ubuntu-latest - steps: - - run: echo "Input was ${{ github.event.inputs.test_input }}" \ No newline at end of file From a8bf48d8f9d68aea55e5da5acf3641152b2f7497 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Thu, 11 Dec 2025 20:17:36 +0000 Subject: [PATCH 39/40] PE-4460: fix --- Makefile | 49 ++++++++++++++++++++++++------------------ sb-private-ca/howto.md | 2 +- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index 4901e8cc..c8aa7fd9 100644 --- a/Makefile +++ b/Makefile @@ -5,11 +5,11 @@ export # TARGETS # ============================================================================== .PHONY: build build-all-images iso build-provider-images iso-disk-image \ - uki-genkey alpine-all validate-user-data raw-image aws-cloud-image \ + uki-genkey secure-boot-dirs alpine-all validate-user-data raw-image aws-cloud-image \ iso-image-cloud internal-slink iso-efi-size-check \ clean clean-all clean-raw-image clean-keys help -.SILENT: uki-genkey validate-user-data clean-raw-image +.SILENT: uki-genkey validate-user-data clean-raw-image secure-boot-dirs help # ============================================================================== # CONSTANTS @@ -128,6 +128,12 @@ uki-genkey: $(MAKE) TARGET=uki-genkey build ./keys.sh secure-boot/ +secure-boot-dirs: + mkdir -p secure-boot/enrollment secure-boot/exported-keys secure-boot/private-keys secure-boot/public-keys + find secure-boot -type d -exec chmod 0700 {} \; + find secure-boot -type f -exec chmod 0600 {} \; + echo "Created secure-boot directory structure" + validate-user-data: $(MAKE) TARGET=validate-user-data build @@ -156,22 +162,23 @@ clean-keys: # ============================================================================== help: - @echo "Available targets:" - @echo " build-all-images - Build all provider images and ISO" - @echo " iso - Build ISO installer" - @echo " iso-disk-image - Build ISO disk image" - @echo " build-provider-images - Build all provider images for configured K8S versions" - @echo " raw-image - Build raw cloud disk image(Requires root privileges)" - @echo " aws-cloud-image - Build AWS AMI from raw image(Requires root privileges)" - @echo " uki-genkey - Generate UKI secure boot keys" - @echo " validate-user-data - Validate user-data configuration" - @echo " clean-all - Remove the build directory and secure boot keys" - @echo " clean - Remove the build directory" - @echo " clean-raw-image - Remove the $(RAW_IMAGE_DIR) build directory" - @echo " clean-keys - Clean secure boot keys" - @echo "" - @echo "Build specific configuration (set in .arg file or as make variables):" - @echo " PUSH - Push images to registry (default: true)" - @echo " DEBUG - Enable debug output (default: false)" - @echo " NO_CACHE - Disable build cache (default: false)" - @echo " DRY_RUN - Print build commands without executing (default: false)" + echo "Available targets:" + echo " build-all-images - Build all provider images and ISO" + echo " iso - Build ISO installer" + echo " iso-disk-image - Build ISO disk image" + echo " build-provider-images - Build all provider images for configured K8S versions" + echo " raw-image - Build raw cloud disk image(Requires root privileges)" + echo " aws-cloud-image - Build AWS AMI from raw image(Requires root privileges)" + echo " uki-genkey - Generate UKI secure boot keys" + echo " secure-boot-dirs - Create secure-boot directory structure for BYOK" + echo " validate-user-data - Validate user-data configuration" + echo " clean-all - Remove the build directory and secure boot keys" + echo " clean - Remove the build directory" + echo " clean-raw-image - Remove the $(RAW_IMAGE_DIR) build directory" + echo " clean-keys - Clean secure boot keys" + echo "" + echo "Build specific configuration (set in .arg file or as make variables):" + echo " PUSH - Push images to registry (default: true)" + echo " DEBUG - Enable debug output (default: false)" + echo " NO_CACHE - Disable build cache (default: false)" + echo " DRY_RUN - Print build commands without executing (default: false)" diff --git a/sb-private-ca/howto.md b/sb-private-ca/howto.md index d9434945..9c177f8d 100644 --- a/sb-private-ca/howto.md +++ b/sb-private-ca/howto.md @@ -16,7 +16,7 @@ PK.pem KEK.pem db.pem -5. Run `./earthly.sh +secure-boot-dirs` to create the secure-boot directory structure in CanvOS. +5. Run `./earthly.sh +secure-boot-dirs` or `make secure-boot-dirs` to create the secure-boot directory structure in CanvOS. 6. Place the files in the following directory structure: ``` CanvOS/ From 699bf2c73c97f91475c66a3628701ac5ef1a0613 Mon Sep 17 00:00:00 2001 From: Dr-N00B Date: Mon, 9 Feb 2026 16:31:25 +0000 Subject: [PATCH 40/40] Add docker-bake-common.hcl for shared variables and refactor docker-bake.hcl - Introduced docker-bake-common.hcl to centralize common variables such as KAIROS_VERSION, ARCH, and FIPS_ENABLED. - Updated docker-bake.hcl to reference these variables, reducing redundancy. - Adjusted Makefile to include new cloud image and MAAS image targets. - Enhanced Dockerfiles to utilize bind mounts for improved context handling and reduced image size. - Added Dockerfile for cloud-image-tools to support disk operations and content partitioning. --- Makefile | 237 ++++++++++++++++------ cloudconfigs/build-kairos-maas.sh | 20 +- docker-bake-common.hcl | 65 ++++++ docker-bake.hcl | 67 ++++-- dockerfiles/Dockerfile.alpine | 12 +- dockerfiles/Dockerfile.base-image | 29 +-- dockerfiles/Dockerfile.build-iso | 29 +-- dockerfiles/Dockerfile.build-uki-iso | 44 ++-- dockerfiles/Dockerfile.cloud-image-tools | 49 +++++ dockerfiles/Dockerfile.install-k8s | 9 +- dockerfiles/Dockerfile.iso-image | 30 ++- dockerfiles/Dockerfile.provider-image | 10 +- dockerfiles/Dockerfile.uki-provider-image | 14 +- dockerfiles/Dockerfile.validate-ud | 15 +- earthly.sh | 25 +-- 15 files changed, 463 insertions(+), 192 deletions(-) create mode 100644 docker-bake-common.hcl create mode 100644 dockerfiles/Dockerfile.cloud-image-tools diff --git a/Makefile b/Makefile index c8aa7fd9..87848b58 100644 --- a/Makefile +++ b/Makefile @@ -5,20 +5,33 @@ export # TARGETS # ============================================================================== .PHONY: build build-all-images iso build-provider-images iso-disk-image \ - uki-genkey secure-boot-dirs alpine-all validate-user-data raw-image aws-cloud-image \ - iso-image-cloud internal-slink iso-efi-size-check \ - clean clean-all clean-raw-image clean-keys help + uki-genkey secure-boot-dirs alpine-all validate-user-data \ + cloud-image raw-image aws-cloud-image iso-image-cloud cloud-image-tools \ + maas-image iso-image-maas \ + internal-slink iso-efi-size-check \ + clean clean-all clean-cloud-image clean-keys help -.SILENT: uki-genkey validate-user-data clean-raw-image secure-boot-dirs help +.SILENT: uki-genkey validate-user-data clean-cloud-image secure-boot-dirs help cloud-image # ============================================================================== # CONSTANTS # ============================================================================== -AURORABOOT_IMAGE := quay.io/kairos/auroraboot:v0.14.0 -RAW_IMAGE_DIR := $(CURDIR)/build/raw-image +AURORABOOT_IMAGE := quay.io/kairos/auroraboot:v0.19.0 + +# Docker Bake file configuration +COMMON_BAKE_FILE := docker-bake-common.hcl +MAIN_BAKE_FILE := docker-bake.hcl + +# Bake file arguments for main builds (includes common + main bake files) +BAKE_FILES := -f $(COMMON_BAKE_FILE) -f $(MAIN_BAKE_FILE) + +CLOUD_IMAGE_DIR := $(CURDIR)/build/cloud-image +MAAS_IMAGE_DIR := $(CURDIR)/build/maas-image ISO_IMAGE_CLOUD := palette-installer-image-cloud:latest ISO_IMAGE_MAAS := palette-installer-image-maas:latest +CLOUD_IMAGE_TOOLS := us-docker.pkg.dev/palette-images/edge/canvos/cloud-image-tools:latest +MAAS_IMAGE_NAME ?= kairos-ubuntu-maas # ============================================================================== # HELPER VARIABLES @@ -36,36 +49,37 @@ NO_CACHE := $(or $(NO_CACHE),false) DRY_RUN := $(or $(DRY_RUN),false) ARCH := $(or $(ARCH),amd64) + +USER_DATA := $(or $(USER_DATA),user-data) + # Common Configuration expressions for building targets PUSH_ARGS = $(if $(filter true,$(PUSH)),--set *.output=type=image$(comma)push=$(PUSH),) -# Dry run flag DRY_RUN_ARGS = $(if $(filter true,$(DRY_RUN)),--print,) -# Progress output flag DOCKER_BUILD_OUT = $(if $(filter true,$(DEBUG)),--progress=plain --debug,) -# No cache flag DOCKER_NO_CACHE = $(if $(filter true,$(NO_CACHE)),--no-cache,) # ============================================================================== # COMPUTED VARIABLES # ============================================================================== -# Target type selection based on IS_UKI flag PROVIDER_TARGET_TYPE = $(if $(filter true,$(IS_UKI)),uki-provider-image,provider-image) ISO_TARGET_TYPE = $(if $(filter true,$(IS_UKI)),build-uki-iso,build-iso) - - -# K8S versions: either from K8S_VERSION (comma-separated) or k8s_version.json ALL_K8S_VERSIONS = $(if $(strip $(K8S_VERSION)),\ $(subst $(comma),$(space),$(K8S_VERSION)),\ $(shell jq -r --arg key "$(K8S_DISTRIBUTION)" 'if .[$$key] then .[$$key][] else empty end' k8s_version.json)) +# Check for content directories, cluster config, and edge config +HAS_CONTENT := $(shell ls -d content-* 2>/dev/null | head -1) +HAS_CLUSTERCONFIG := $(if $(CLUSTERCONFIG),$(shell test -f "$(CLUSTERCONFIG)" && echo yes),) +HAS_EDGE_CONFIG := $(if $(EDGE_CUSTOM_CONFIG),$(shell test -f "$(EDGE_CUSTOM_CONFIG)" && echo yes),) +HAS_USER_DATA := $(shell test -f "$(USER_DATA)" && echo yes) # ============================================================================== # CORE BUILD TARGET # ============================================================================== build: $(if $(BAKE_ENV),env $(BAKE_ENV)) \ - docker buildx bake $(DRY_RUN_ARGS) $(DOCKER_BUILD_OUT) $(DOCKER_NO_CACHE) $(TARGET) $(BAKE_ARGS) + docker buildx bake $(BAKE_FILES) $(DRY_RUN_ARGS) $(DOCKER_BUILD_OUT) $(DOCKER_NO_CACHE) $(TARGET) $(BAKE_ARGS) # ============================================================================== # MAIN BUILD TARGETS @@ -78,36 +92,12 @@ iso: iso-disk-image: $(MAKE) TARGET=iso-disk-image build BAKE_ARGS="$(PUSH_ARGS)" -aws-cloud-image: raw-image - $(MAKE) TARGET=aws-cloud-image build - -raw-image: clean-raw-image iso-image-cloud - mkdir -p $(RAW_IMAGE_DIR) - docker run --net host --privileged -v /var/run/docker.sock:/var/run/docker.sock \ - -v $(RAW_IMAGE_DIR):/build \ - -v $(CURDIR)/cloud-images/config/user-data.yaml:/config.yaml \ - --rm -it $(AURORABOOT_IMAGE) \ - --debug \ - --set "disable_http_server=true" \ - --set "disable_netboot=true" \ - --set "disk.efi=true" \ - --set "arch=$(ARCH)" \ - --set "container_image=$(ISO_IMAGE_CLOUD)" \ - --set "state_dir=/build" \ - --cloud-config /config.yaml - -iso-image-cloud: - $(MAKE) TARGET=iso-image-cloud build BAKE_ARGS="--set *.tags.ISO_IMAGE_CLOUD=$(ISO_IMAGE_CLOUD)" - # ============================================================================== # PROVIDER IMAGE BUILD TARGETS # ============================================================================== build-provider-images: .check-provider-prereqs $(addprefix .build-provider-image-,$(strip $(ALL_K8S_VERSIONS))) @echo "All provider images built successfully" -# PROVIDER IMAGE BUILD TARGETS (INTERNAL) -# ============================================================================== - .build-provider-image-%: .check-provider-prereqs @echo "Building provider image for k8s version: $*" @$(MAKE) TARGET=$(PROVIDER_TARGET_TYPE) \ @@ -121,6 +111,101 @@ build-provider-images: .check-provider-prereqs $(addprefix .build-provider-image @$(if $(strip $(ALL_K8S_VERSIONS)),,\ $(error No versions found for K8S_DISTRIBUTION=$(K8S_DISTRIBUTION))) + +# ------------------------------------------------------------------------------ +# Cloud Image +# ------------------------------------------------------------------------------ +# Build AWS AMI from cloud image +aws-cloud-image: cloud-image + @echo "Creating AWS AMI from cloud image" + $(MAKE) TARGET=aws-cloud-image build BAKE_ARGS="--set *.contexts.raw-image=$(CLOUD_IMAGE_DIR)" + +cloud-image: iso-image-cloud cloud-image-tools content-partition-cloud + $(MAKE) kairos-raw-image OUTPUT_DIR=$(CLOUD_IMAGE_DIR) CONTAINER_IMAGE=$(ISO_IMAGE_CLOUD) + @ls -lh $(CLOUD_IMAGE_DIR)/* 2>/dev/null || true + +iso-image-cloud: + $(MAKE) TARGET=iso-image-cloud build + +content-partition-cloud: + @if [ -n "$(HAS_CONTENT)" ] || [ -n "$(HAS_CLUSTERCONFIG)" ] || [ -n "$(HAS_EDGE_CONFIG)" ]; then \ + echo "Adding content partition to cloud image"; \ + RAW_FILE=$$(ls $(CLOUD_IMAGE_DIR)/*.raw 2>/dev/null || ls $(CLOUD_IMAGE_DIR)/*.img 2>/dev/null | head -1); \ + if [ -z "$$RAW_FILE" ]; then \ + echo "Error: No raw image found in $(CLOUD_IMAGE_DIR)"; \ + exit 1; \ + fi; \ + echo "Adding content partition to: $$RAW_FILE"; \ + docker run --rm --privileged --net host \ + -v /dev:/dev \ + -v $(CLOUD_IMAGE_DIR):/workdir \ + $(foreach dir,$(wildcard content-*),-v $(CURDIR)/$(dir):/workdir/$(dir):ro) \ + $(if $(HAS_CLUSTERCONFIG),-v $(CURDIR)/$(CLUSTERCONFIG):/workdir/spc.tgz:ro,) \ + $(if $(HAS_EDGE_CONFIG),-v $(CURDIR)/$(EDGE_CUSTOM_CONFIG):/workdir/edge_custom_config.yaml:ro,) \ + -e CLUSTERCONFIG=$(if $(HAS_CLUSTERCONFIG),/workdir/spc.tgz,) \ + -e EDGE_CUSTOM_CONFIG=$(if $(HAS_EDGE_CONFIG),/workdir/edge_custom_config.yaml,) \ + $(CLOUD_IMAGE_TOOLS) \ + -c "/scripts/add-content-partition.sh /workdir/$$(basename $$RAW_FILE)"; \ + else \ + echo "Skipped adding content partition (no content files)"; \ + fi + +# ------------------------------------------------------------------------------ +# MAAS Image +# ------------------------------------------------------------------------------ +maas-image: raw-disk-maas build-maas-composite + @echo "MAAS image build complete" + @ls -lh $(MAAS_IMAGE_DIR)/* 2>/dev/null || true + +# raw-disk-maas: iso-image-maas cloud-image-tools +raw-disk-maas: + @echo "Creating base raw disk image for MAAS" + $(MAKE) kairos-raw-image OUTPUT_DIR=$(MAAS_IMAGE_DIR) CONTAINER_IMAGE=$(ISO_IMAGE_MAAS) + +# Build MAAS composite image (adds Ubuntu rootfs + content partition) +build-maas-composite: cloud-image-tools + @RAW_FILE=$$(ls $(MAAS_IMAGE_DIR)/*.raw 2>/dev/null || ls $(MAAS_IMAGE_DIR)/*.img 2>/dev/null | head -1); \ + if [ -z "$$RAW_FILE" ]; then \ + echo "Error: No raw image found in $(MAAS_IMAGE_DIR)"; \ + exit 1; \ + fi; \ + echo "Building MAAS composite from: $$RAW_FILE"; \ + docker run --rm --privileged --net host \ + -v /dev:/dev \ + -v $(MAAS_IMAGE_DIR):/workdir \ + $(foreach dir,$(wildcard content-*),-v $(CURDIR)/$(dir):/input/$(dir):ro) \ + $(if $(HAS_CLUSTERCONFIG),-v $(CURDIR)/$(CLUSTERCONFIG):/input/spc.tgz:ro,) \ + $(if $(HAS_EDGE_CONFIG),-v $(CURDIR)/$(EDGE_CUSTOM_CONFIG):/input/edge_custom_config.yaml:ro,) \ + -e CURTIN_HOOKS_SCRIPT=/scripts/curtin-hooks \ + -e CONTENT_BASE_DIR=/input \ + -e CLUSTERCONFIG=$(if $(HAS_CLUSTERCONFIG),/input/spc.tgz,) \ + -e EDGE_CUSTOM_CONFIG=$(if $(HAS_EDGE_CONFIG),/input/edge_custom_config.yaml,) \ + -e MAAS_IMAGE_NAME=$(MAAS_IMAGE_NAME) \ + $(CLOUD_IMAGE_TOOLS) \ + -c "/scripts/build-kairos-maas.sh /workdir/$$(basename $$RAW_FILE) $(MAAS_IMAGE_NAME)" + +iso-image-maas: + $(MAKE) TARGET=iso-image-maas build + +# ============================================================================== +# INTERNAL TARGETs (for MAAS and Cloud images) +# ============================================================================== +kairos-raw-image: validate-user-data + @mkdir -p $(OUTPUT_DIR) + docker run --rm --net host --privileged \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v $(OUTPUT_DIR):/output \ + $(if $(HAS_USER_DATA),-v $(CURDIR)/$(USER_DATA):/config.yaml:ro,) \ + $(AURORABOOT_IMAGE) \ + $(if $(filter true,$(DEBUG)),--debug,) \ + --set "disable_http_server=true" \ + --set "disable_netboot=true" \ + --set "disk.efi=true" \ + --set "arch=$(ARCH)" \ + --set "container_image=$(CONTAINER_IMAGE)" \ + --set "state_dir=/output" \ + $(if $(HAS_USER_DATA),--cloud-config /config.yaml,--set "no_default_cloud_config=true") + # ============================================================================== # UTILITY TARGETS # ============================================================================== @@ -146,6 +231,9 @@ iso-efi-size-check: alpine-all: $(MAKE) TARGET=alpine-all BAKE_ARGS="$(PUSH_ARGS)" build +cloud-image-tools: + $(MAKE) TARGET=cloud-image-tools BAKE_ARGS="$(PUSH_ARGS)" build + # ============================================================================== # CLEAN TARGETS # ============================================================================== @@ -154,31 +242,60 @@ clean-all: clean clean-keys clean: rm -rf build -clean-raw-image: - rm -rf build/raw-image +clean-cloud-image: + rm -rf $(CLOUD_IMAGE_DIR) $(MAAS_IMAGE_DIR) clean-keys: rm -rf secure-boot # ============================================================================== +# Colors for help output +BOLD := $(shell printf '\033[1m') +CYAN := $(shell printf '\033[36m') +GREEN := $(shell printf '\033[32m') +YELLOW := $(shell printf '\033[33m') +RESET := $(shell printf '\033[0m') + help: - echo "Available targets:" - echo " build-all-images - Build all provider images and ISO" - echo " iso - Build ISO installer" - echo " iso-disk-image - Build ISO disk image" - echo " build-provider-images - Build all provider images for configured K8S versions" - echo " raw-image - Build raw cloud disk image(Requires root privileges)" - echo " aws-cloud-image - Build AWS AMI from raw image(Requires root privileges)" - echo " uki-genkey - Generate UKI secure boot keys" - echo " secure-boot-dirs - Create secure-boot directory structure for BYOK" - echo " validate-user-data - Validate user-data configuration" - echo " clean-all - Remove the build directory and secure boot keys" - echo " clean - Remove the build directory" - echo " clean-raw-image - Remove the $(RAW_IMAGE_DIR) build directory" - echo " clean-keys - Clean secure boot keys" - echo "" - echo "Build specific configuration (set in .arg file or as make variables):" - echo " PUSH - Push images to registry (default: true)" - echo " DEBUG - Enable debug output (default: false)" - echo " NO_CACHE - Disable build cache (default: false)" - echo " DRY_RUN - Print build commands without executing (default: false)" + @echo "" + @echo "$(BOLD)CanvOS Build System$(RESET)" + @echo "" + @echo "$(CYAN)Build Targets:$(RESET)" + @echo " $(GREEN)build-all-images$(RESET) Build all provider images and ISO" + @echo " $(GREEN)iso$(RESET) Build ISO installer" + @echo " $(GREEN)iso-disk-image$(RESET) Build ISO disk image and push to registry" + @echo " $(GREEN)build-provider-images$(RESET) Build provider images for configured K8S versions" + @echo "" + @echo "$(CYAN)Cloud Image Targets:$(RESET) $(YELLOW)(require privileged Docker)$(RESET)" + @echo " $(GREEN)cloud-image$(RESET) Build raw cloud disk image with content partition" + @echo " $(GREEN)aws-cloud-image$(RESET) Build AWS AMI from cloud image" + @echo " $(GREEN)raw-image$(RESET) Alias for cloud-image" + @echo "" + @echo "$(CYAN)MAAS Image Targets:$(RESET) $(YELLOW)(require privileged Docker)$(RESET)" + @echo " $(GREEN)maas-image$(RESET) Build MAAS raw disk image with content partition" + @echo "" + @echo "$(CYAN)Utility Targets:$(RESET)" + @echo " $(GREEN)uki-genkey$(RESET) Generate UKI secure boot keys" + @echo " $(GREEN)secure-boot-dirs$(RESET) Create secure-boot directory structure" + @echo " $(GREEN)validate-user-data$(RESET) Validate user-data configuration" + @echo "" + @echo "$(CYAN)Clean Targets:$(RESET)" + @echo " $(GREEN)clean$(RESET) Remove build directory" + @echo " $(GREEN)clean-all$(RESET) Remove build directory and secure boot keys" + @echo " $(GREEN)clean-cloud-image$(RESET) Remove cloud/MAAS image artifacts" + @echo " $(GREEN)clean-keys$(RESET) Remove secure boot keys" + @echo "" + @echo "$(CYAN)Configuration:$(RESET) (set in .arg file or as make variables)" + @echo " PUSH=true|false Push images to registry (default: true)" + @echo " DEBUG=true|false Enable debug output (default: false)" + @echo " NO_CACHE=true|false Disable build cache (default: false)" + @echo " DRY_RUN=true|false Print commands without executing" + @echo "" + @echo "$(CYAN)Cloud/MAAS Configuration:$(RESET)" + @echo " USER_DATA= Cloud config file (default: user-data)" + @echo " CLUSTERCONFIG= Cluster config archive (spc.tgz)" + @echo " EDGE_CUSTOM_CONFIG= Edge custom config yaml" + @echo " content-*/ Content bundle directories (auto-detected)" + @echo "" + @echo "$(YELLOW)For base image builds:$(RESET) make -f Makefile.base-images help" + @echo "" \ No newline at end of file diff --git a/cloudconfigs/build-kairos-maas.sh b/cloudconfigs/build-kairos-maas.sh index b785e5a2..524fdecb 100644 --- a/cloudconfigs/build-kairos-maas.sh +++ b/cloudconfigs/build-kairos-maas.sh @@ -46,12 +46,14 @@ UBUNTU_ROOT_SIZE="3G" # The size of the content partition (for Stylus content files) # Default to 2G, but will be calculated based on actual content size if content files exist CONTENT_SIZE="2G" -# Path to the curtin hooks script (relative to the original directory) -CURTIN_HOOKS_SCRIPT="$ORIG_DIR/curtin-hooks" + +CURTIN_HOOKS_SCRIPT="${CURTIN_HOOKS_SCRIPT:-$ORIG_DIR/curtin-hooks}" + +CONTENT_BASE_DIR="${CONTENT_BASE_DIR:-$ORIG_DIR}" # Path to content directory (if content files are provided) # Look for content-* directories (e.g., content-3a456a58) CONTENT_DIR="" -for dir in "$ORIG_DIR"/content-*; do +for dir in "$CONTENT_BASE_DIR"/content-*; do if [ -d "$dir" ]; then CONTENT_DIR="$dir" echo "Found content directory: $CONTENT_DIR" @@ -59,8 +61,8 @@ for dir in "$ORIG_DIR"/content-*; do fi done # Fallback to plain content directory if no content-* found -if [ -z "$CONTENT_DIR" ] && [ -d "$ORIG_DIR/content" ]; then - CONTENT_DIR="$ORIG_DIR/content" +if [ -z "$CONTENT_DIR" ] && [ -d "$CONTENT_BASE_DIR/content" ]; then + CONTENT_DIR="$CONTENT_BASE_DIR/content" echo "Found content directory: $CONTENT_DIR" fi @@ -579,8 +581,16 @@ if [ -f "$INPUT_IMG" ]; then rm -f "$INPUT_IMG" fi +# Generate SHA256 checksum +echo "Generating SHA256 checksum..." +sha256sum "$COMPRESSED_IMG" > "${COMPRESSED_IMG}.sha256" +CHECKSUM=$(cat "${COMPRESSED_IMG}.sha256" | cut -d' ' -f1) +echo "SHA256: $CHECKSUM" + echo "" echo "✅ Composite image created and compressed successfully: $COMPRESSED_IMG" +echo " Size: $COMP_SIZE" +echo " Checksum: ${COMPRESSED_IMG}.sha256" echo "You can now upload this compressed raw image to MAAS (MAAS will automatically decompress it)." # Exit with success code diff --git a/docker-bake-common.hcl b/docker-bake-common.hcl new file mode 100644 index 00000000..60adb7c8 --- /dev/null +++ b/docker-bake-common.hcl @@ -0,0 +1,65 @@ +# ============================================================================= +# Docker Bake Common Variables +# ============================================================================= +# This file contains shared variables used across all docker-bake configurations. +# Include this file with your specific bake file using multiple -f flags: +# +# Usage: +# docker buildx bake -f docker-bake-common.hcl -f docker-bake.hcl +# docker buildx bake -f docker-bake-common.hcl -f docker-bake-base-images.hcl +# +# Variables defined in later files (-f order) will override earlier ones. +# ============================================================================= + +# ----------------------------------------------------------------------------- +# Core Version Variables +# ----------------------------------------------------------------------------- + +variable "KAIROS_VERSION" { + default = "v3.5.9" + description = "Kairos framework version" +} + +variable "KAIROS_INIT_IMAGE" { + default = "quay.io/kairos/kairos-init:v0.5.28" + description = "Kairos init image for kairosification" +} + +# ----------------------------------------------------------------------------- +# Architecture and Platform +# ----------------------------------------------------------------------------- + +variable "ARCH" { + default = "amd64" + description = "Target architecture (amd64, arm64)" +} + +# ----------------------------------------------------------------------------- +# Image Registry and Tagging +# ----------------------------------------------------------------------------- + +variable "IMAGE_REGISTRY" { + default = "" + description = "Container registry to push images (e.g., ghcr.io/myorg, us-docker.pkg.dev/project)" +} + +variable "IMAGE_TAG" { + default = "latest" + description = "Tag for built images (can be overridden by specific bake files)" +} + +variable "PUSH_IMAGES" { + type = bool + default = false + description = "Whether to push images to registry" +} + +# ----------------------------------------------------------------------------- +# FIPS Configuration +# ----------------------------------------------------------------------------- + +variable "FIPS_ENABLED" { + type = bool + default = false + description = "Enable FIPS-compliant builds" +} diff --git a/docker-bake.hcl b/docker-bake.hcl index 2736acf2..7af3a1ba 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -1,11 +1,5 @@ -variable "FIPS_ENABLED" { - type = bool - default = false -} - -variable "ARCH" { - default = "amd64" -} +# Note: FIPS_ENABLED and ARCH are defined in docker-bake-common.hcl +# Include with: docker buildx bake -f docker-bake-common.hcl -f docker-bake.hcl variable "SPECTRO_PUB_REPO" { default = FIPS_ENABLED ? "us-docker.pkg.dev/palette-images-fips" : "us-docker.pkg.dev/palette-images" @@ -31,17 +25,19 @@ variable "KAIROS_BASE_IMAGE_URL" { default = "${SPECTRO_PUB_REPO}/edge" } +variable AURORABOOT_VERSION { + default = "v0.19.0" +} + variable AURORABOOT_IMAGE { - default = "quay.io/kairos/auroraboot:v0.14.0" + default = "quay.io/kairos/auroraboot:${AURORABOOT_VERSION}" } variable "PE_VERSION" { default = "v4.8.1" } -variable "KAIROS_VERSION" { - default = "v3.5.9" -} +# Note: KAIROS_VERSION is defined in docker-bake-common.hcl variable "K3S_FLAVOR_TAG" { default = "k3s1" @@ -315,6 +311,7 @@ target "base" { target "base-image" { dockerfile = "dockerfiles/Dockerfile.base-image" + context = "." contexts = { base = "target:base" } @@ -353,6 +350,7 @@ function "get_provider_base" { target "install-k8s" { dockerfile = "dockerfiles/Dockerfile.install-k8s" + context = "." target = "install-k8s" platforms = ["linux/${ARCH}"] contexts = { @@ -372,6 +370,7 @@ target "install-k8s" { target "provider-image" { dockerfile = "dockerfiles/Dockerfile.provider-image" + context = "." target = "provider-image" platforms = ["linux/${ARCH}"] contexts = { @@ -411,6 +410,7 @@ target "provider-image" { target "uki-provider-image" { dockerfile = "dockerfiles/Dockerfile.uki-provider-image" + context = "." platforms = ["linux/${ARCH}"] contexts = { third-party-luet = "target:third-party-luet" @@ -459,6 +459,7 @@ target "validate-user-data" { target "iso-image" { dockerfile = "dockerfiles/Dockerfile.iso-image" + context = "." target = "iso-image" platforms = ["linux/${ARCH}"] contexts = { @@ -469,6 +470,7 @@ target "iso-image" { ARCH = ARCH IS_UKI = IS_UKI IS_CLOUD_IMAGE = IS_CLOUD_IMAGE + IS_MAAS = IS_MAAS } tags = ["palette-installer-image:${IMAGE_TAG}"] output = ["type=docker"] @@ -654,21 +656,42 @@ target "iso-efi-size-check" { output = ["type=local,dest=./build/"] } -variable "RAW_IMAGE_DIR" { - default = "./build/raw-image" +variable "CLOUD_IMAGE_DIR" { + default = "./build/cloud-image" } +# Build installer image and load to Docker daemon +# Used by: make cloud-image (which then runs auroraboot to create raw disk) target "iso-image-cloud" { inherits = ["iso-image"] + args = { + IS_CLOUD_IMAGE = true + } tags = ["palette-installer-image-cloud:latest"] + output = ["type=docker"] } +# Build MAAS installer image and load to Docker daemon +# Used by: make maas-image (which then runs auroraboot to create raw disk) +target "iso-image-maas" { + inherits = ["iso-image"] + args = { + IS_MAAS = true + } + tags = ["palette-installer-image-maas:latest"] + output = ["type=docker"] +} + + + + + target "aws-cloud-image" { dockerfile = "dockerfiles/Dockerfile.aws-cloud-image" context = "." platforms = ["linux/${ARCH}"] contexts = { - raw-image = RAW_IMAGE_DIR + raw-image = CLOUD_IMAGE_DIR } args = { UBUNTU_IMAGE = get_ubuntu_image(FIPS_ENABLED, SPECTRO_PUB_REPO) @@ -683,3 +706,17 @@ target "aws-cloud-image" { "id=AWS_SECRET_ACCESS_KEY,env=AWS_SECRET_ACCESS_KEY" ] } + +// Tools image for cloud/MAAS disk operations (content partition for cloud image, MAAS builder) +target "cloud-image-tools" { + dockerfile = "dockerfiles/Dockerfile.cloud-image-tools" + context = "." + platforms = ["linux/${ARCH}"] + args = { + BASE_IMAGE = ALPINE_BASE_IMAGE + } + tags = [ + "${SPECTRO_PUB_REPO}/edge/canvos/cloud-image-tools:latest" + ] + output = ["type=docker"] +} diff --git a/dockerfiles/Dockerfile.alpine b/dockerfiles/Dockerfile.alpine index dab424a9..c35ceb7d 100644 --- a/dockerfiles/Dockerfile.alpine +++ b/dockerfiles/Dockerfile.alpine @@ -13,12 +13,10 @@ RUN update-ca-certificates || true FROM alpine-base AS alpine-certs -COPY . /tmp/build-context/ - -# Copy custom certs if present, update CA store +# Use bind mount to conditionally copy certs without adding to image layers # Note: update-ca-certificates may fail in FIPS mode due to OpenSSL constraints -RUN if [ -d "/tmp/build-context/certs" ]; then \ - cp -r /tmp/build-context/certs/. /etc/ssl/certs/; \ +RUN --mount=type=bind,target=/build-context \ + if [ -d "/build-context/certs" ]; then \ + cp -r /build-context/certs/. /etc/ssl/certs/; \ fi && \ - update-ca-certificates || true && \ - rm -rf /tmp/build-context \ No newline at end of file + update-ca-certificates || true diff --git a/dockerfiles/Dockerfile.base-image b/dockerfiles/Dockerfile.base-image index f532c99c..fbd64fc0 100644 --- a/dockerfiles/Dockerfile.base-image +++ b/dockerfiles/Dockerfile.base-image @@ -13,18 +13,21 @@ ARG ARCH=amd64 ARG FIPS_ENABLED=false ARG IS_MAAS=false -COPY . /tmp/build-context - -RUN if [ "$IS_JETSON" = "true" ]; then \ - cp /tmp/build-context/cloudconfigs/mount.yaml /system/oem/mount.yaml; \ - fi - -RUN if [ "$IS_UKI" = "true" ]; then \ - cp /tmp/build-context/cloudconfigs/80_stylus_uki.yaml /system/oem/80_stylus_uki.yaml; \ +# Copy platform-specific OEM configurations +RUN --mount=type=bind,target=/build-context \ + if [ "$IS_JETSON" = "true" ]; then \ + cp /build-context/cloudconfigs/mount.yaml /system/oem/mount.yaml; \ + fi && \ + if [ "$IS_UKI" = "true" ]; then \ + cp /build-context/cloudconfigs/80_stylus_uki.yaml /system/oem/80_stylus_uki.yaml; \ + fi && \ + if [ "$IS_MAAS" = "true" ]; then \ + cp /build-context/cloudconfigs/80_stylus_maas.yaml /system/oem/80_stylus_maas.yaml; \ fi # Use secret for UBUNTU_PRO_KEY - not cached, not stored in image layers RUN --mount=type=secret,id=ubuntu_pro_key,target=/run/secrets/ubuntu_pro_key \ + --mount=type=bind,target=/build-context \ if [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ]; then \ if [ -f /run/secrets/ubuntu_pro_key ] && [ -s /run/secrets/ubuntu_pro_key ]; then \ sed -i '/^[[:space:]]*$/d' /etc/os-release && \ @@ -100,7 +103,7 @@ RUN --mount=type=secret,id=ubuntu_pro_key,target=/run/secrets/ubuntu_pro_key \ fi && \ \ if [ "$CIS_HARDENING" = "true" ]; then \ - cp /tmp/build-context/cis-harden/harden.sh /tmp/harden.sh && \ + cp /build-context/cis-harden/harden.sh /tmp/harden.sh && \ /tmp/harden.sh && rm /tmp/harden.sh; \ fi && \ \ @@ -148,7 +151,9 @@ RUN if [ "$OS_DISTRIBUTION" = "sles" ]; then \ fi; \ fi -RUN export OS_ID=${OS_DISTRIBUTION} && \ +# Generate os-release using bind mount for template +RUN --mount=type=bind,target=/build-context \ + export OS_ID=${OS_DISTRIBUTION} && \ export OS_VERSION=${OS_VERSION} && \ export OS_LABEL=latest && \ export VARIANT=${OS_DISTRIBUTION} && \ @@ -159,7 +164,7 @@ RUN export OS_ID=${OS_DISTRIBUTION} && \ export OS_NAME=${kairos-core-${OS_DISTRIBUTION}} && \ export ARTIFACT=${kairos-core-${OS_DISTRIBUTION}-${OS_VERSION}} && \ export KAIROS_RELEASE=${KAIROS_VERSION} && \ - envsubst >>/etc/os-release < /tmp/build-context/overlay/files/usr/lib/os-release.tmpl + envsubst >>/etc/os-release < /build-context/overlay/files/usr/lib/os-release.tmpl RUN KAIROS_IMAGE_LABEL="${OS_VERSION}-standard-${ARCH}-generic" && \ if [ "$IS_MAAS" = "true" ]; then \ @@ -190,5 +195,3 @@ RUN if [ "$DISABLE_SELINUX" = "true" ]; then \ sed -i 's/selinux=1/selinux=0/g' /etc/cos/bootargs.cfg; \ fi; \ fi - -RUN rm -rf /tmp/build-context \ No newline at end of file diff --git a/dockerfiles/Dockerfile.build-iso b/dockerfiles/Dockerfile.build-iso index 92d4c077..3f4814ee 100644 --- a/dockerfiles/Dockerfile.build-iso +++ b/dockerfiles/Dockerfile.build-iso @@ -13,31 +13,24 @@ COPY --from=validate-user-data /validated /validated COPY --from=iso-image / /iso-source/ -COPY . /tmp/build-context/ -RUN mkdir -p /overlay/opt/spectrocloud/content && \ - for dir in /tmp/build-context/content-*/; do \ +RUN --mount=type=bind,target=/build-context \ + mkdir -p /overlay/opt/spectrocloud/content && \ + for dir in /build-context/content-*/; do \ [ -d "$dir" ] && cp "$dir"*.zst /overlay/opt/spectrocloud/content/ 2>/dev/null || true; \ - done - -RUN if [ -n "$EDGE_CUSTOM_CONFIG" ] && [ -f /tmp/build-context/"$EDGE_CUSTOM_CONFIG" ]; then \ - cp /tmp/build-context/"$EDGE_CUSTOM_CONFIG" /overlay/.edge_custom_config.yaml; \ - fi - -RUN if [ -n "$(ls /overlay/opt/spectrocloud/content/*.zst 2>/dev/null)" ]; then \ + done && \ + if [ -n "$EDGE_CUSTOM_CONFIG" ] && [ -f /build-context/"$EDGE_CUSTOM_CONFIG" ]; then \ + cp /build-context/"$EDGE_CUSTOM_CONFIG" /overlay/.edge_custom_config.yaml; \ + fi && \ + if [ -n "$(ls /overlay/opt/spectrocloud/content/*.zst 2>/dev/null)" ]; then \ for file in /overlay/opt/spectrocloud/content/*.zst; do \ split --bytes=3GB --numeric-suffixes "$file" /overlay/opt/spectrocloud/content/$(basename "$file")_part; \ done; \ rm -f /overlay/opt/spectrocloud/content/*.zst; \ - fi - -RUN if [ -n "$CLUSTERCONFIG" ] && [ -f /tmp/build-context/"$CLUSTERCONFIG" ]; then \ + fi && \ + if [ -n "$CLUSTERCONFIG" ] && [ -f /build-context/"$CLUSTERCONFIG" ]; then \ mkdir -p /overlay/opt/spectrocloud/clusterconfig && \ - cp /tmp/build-context/"$CLUSTERCONFIG" /overlay/opt/spectrocloud/clusterconfig/spc.tgz; \ - fi - -RUN if [ -f /tmp/build-context/local-ui.tar ]; then \ - tar -xf /tmp/build-context/local-ui.tar -C /overlay/opt/spectrocloud; \ + cp /build-context/"$CLUSTERCONFIG" /overlay/opt/spectrocloud/clusterconfig/spc.tgz; \ fi # Generate grub.cfg based on FORCE_INTERACTIVE_INSTALL setting diff --git a/dockerfiles/Dockerfile.build-uki-iso b/dockerfiles/Dockerfile.build-uki-iso index b9e63326..901e78a4 100644 --- a/dockerfiles/Dockerfile.build-uki-iso +++ b/dockerfiles/Dockerfile.build-uki-iso @@ -20,34 +20,32 @@ COPY --from=stylus-image-pack /stylus-image.tar /overlay/stylus-image.tar COPY --from=third-party-luet /WORKDIR/luet /overlay/luet -COPY . /tmp/build-context/ +COPY --from=iso-image / /iso-source/ -RUN mkdir -p /overlay/opt/spectrocloud/content && \ - for dir in /tmp/build-context/content-*/; do \ +RUN --mount=type=bind,target=/build-context \ + mkdir -p /overlay/opt/spectrocloud/content && \ + for dir in /build-context/content-*/; do \ [ -d "$dir" ] && cp "$dir"*.zst /overlay/opt/spectrocloud/content/ 2>/dev/null || true; \ - done - -RUN if [ -n "$EDGE_CUSTOM_CONFIG" ] && [ -f /tmp/build-context/"$EDGE_CUSTOM_CONFIG" ]; then \ - cp /tmp/build-context/"$EDGE_CUSTOM_CONFIG" /overlay/.edge_custom_config.yaml; \ - fi - -RUN if [ -n "$(ls /overlay/opt/spectrocloud/content/*.zst 2>/dev/null)" ]; then \ - for file in /overlay/opt/spectrocloud/content/*.zst; do \ - split --bytes=3GB --numeric-suffixes "$file" /overlay/opt/spectrocloud/content/$(basename "$file")_part; \ - done; \ - rm -f /overlay/opt/spectrocloud/content/*.zst; \ -fi - -RUN if [ -n "$CLUSTERCONFIG" ] && [ -f /tmp/build-context/"$CLUSTERCONFIG" ]; then \ + done && \ + if [ -n "$EDGE_CUSTOM_CONFIG" ] && [ -f /build-context/"$EDGE_CUSTOM_CONFIG" ]; then \ + cp /build-context/"$EDGE_CUSTOM_CONFIG" /overlay/.edge_custom_config.yaml; \ + fi && \ + if [ -n "$(ls /overlay/opt/spectrocloud/content/*.zst 2>/dev/null)" ]; then \ + for file in /overlay/opt/spectrocloud/content/*.zst; do \ + split --bytes=3GB --numeric-suffixes "$file" /overlay/opt/spectrocloud/content/$(basename "$file")_part; \ + done; \ + rm -f /overlay/opt/spectrocloud/content/*.zst; \ + fi && \ + if [ -n "$CLUSTERCONFIG" ] && [ -f /build-context/"$CLUSTERCONFIG" ]; then \ mkdir -p /overlay/opt/spectrocloud/clusterconfig && \ - cp /tmp/build-context/"$CLUSTERCONFIG" /overlay/opt/spectrocloud/clusterconfig/spc.tgz; \ + cp /build-context/"$CLUSTERCONFIG" /overlay/opt/spectrocloud/clusterconfig/spc.tgz; \ fi -RUN if [ -f /tmp/build-context/local-ui.tar ]; then \ - tar -xf /tmp/build-context/local-ui.tar -C /overlay/opt/spectrocloud; \ -fi - -COPY --from=iso-image / /iso-source/ +# For UKI: move local-ui from squashfs to overlay to reduce EFI size +RUN if [ -d /iso-source/opt/spectrocloud/local-ui ]; then \ + mkdir -p /overlay/opt/spectrocloud && \ + mv /iso-source/opt/spectrocloud/local-ui /overlay/opt/spectrocloud/ ; \ + fi COPY secure-boot/enrollment/ /keys/ diff --git a/dockerfiles/Dockerfile.cloud-image-tools b/dockerfiles/Dockerfile.cloud-image-tools new file mode 100644 index 00000000..ffeea784 --- /dev/null +++ b/dockerfiles/Dockerfile.cloud-image-tools @@ -0,0 +1,49 @@ +ARG BASE_IMAGE=alpine:3.20 + +FROM ${BASE_IMAGE} + +# Install all required tools for disk operations +# Grouped by purpose for clarity +RUN apk add --no-cache \ + # Core utilities + bash \ + coreutils \ + util-linux \ + # Partitioning tools + parted \ + gptfdisk \ + multipath-tools \ + # Filesystem tools + e2fsprogs \ + dosfstools \ + # Disk image tools + qemu-img \ + # File operations + rsync \ + tar \ + gzip \ + # Docker CLI for auroraboot + docker-cli \ + # Utilities + jq \ + curl \ + wget \ + # GRUB tools (for MAAS) + grub \ + && rm -rf /var/cache/apk/* + +# Create scripts directory +RUN mkdir -p /scripts + +# Copy all disk operation scripts +COPY cloud-images/scripts/add-content-partition.sh /scripts/ +COPY cloudconfigs/build-kairos-maas.sh /scripts/ +COPY cloudconfigs/curtin-hooks /scripts/ + +# Make scripts executable +RUN chmod +x /scripts/*.sh + +# Set working directory +WORKDIR /workdir + +ENTRYPOINT ["/bin/bash"] diff --git a/dockerfiles/Dockerfile.install-k8s b/dockerfiles/Dockerfile.install-k8s index 0a2ef961..a7caf61b 100644 --- a/dockerfiles/Dockerfile.install-k8s +++ b/dockerfiles/Dockerfile.install-k8s @@ -14,12 +14,13 @@ COPY --from=third-party-luet /WORKDIR/luet /usr/bin/luet WORKDIR /output - RUN mkdir -p /etc/luet/repos.conf.d && \ luet repo add spectro --type docker --url $SPECTRO_LUET_REPO/$LUET_REPO --priority 1 -y -RUN if [ -f /tmp/build-context/spectro-luet-auth.yaml ]; then \ - cat /tmp/build-context/spectro-luet-auth.yaml >> /etc/luet/repos.conf.d/spectro.yaml; \ +# Use bind mount for optional luet auth config +RUN --mount=type=bind,target=/build-context \ + if [ -f /build-context/spectro-luet-auth.yaml ]; then \ + cat /build-context/spectro-luet-auth.yaml >> /etc/luet/repos.conf.d/spectro.yaml; \ fi RUN luet repo update @@ -40,4 +41,4 @@ RUN if [ "$K8S_DISTRIBUTION" = "kubeadm" ] || \ echo "Installing k8s/$K8S_DISTRIBUTION@$BASE_K8S_VERSION for K8S_VERSION=$K8S_VERSION" && \ luet install -y k8s/$K8S_DISTRIBUTION@$BASE_K8S_VERSION --system-target /output && luet cleanup -RUN rm -rf /output/var/cache/* \ No newline at end of file +RUN rm -rf /output/var/cache/* diff --git a/dockerfiles/Dockerfile.iso-image b/dockerfiles/Dockerfile.iso-image index a8614dfa..a02a2245 100644 --- a/dockerfiles/Dockerfile.iso-image +++ b/dockerfiles/Dockerfile.iso-image @@ -2,6 +2,7 @@ FROM base-image AS iso-image ARG IS_UKI=false ARG IS_CLOUD_IMAGE=false +ARG IS_MAAS=false COPY --from=stylus-image / / @@ -16,14 +17,29 @@ RUN if [ -f /etc/logrotate.d/stylus.conf ]; then \ chmod 644 /etc/logrotate.d/stylus.conf; \ fi -COPY cloud-images/workaround/ /tmp/cloud-images/workaround/ - -RUN if [ "$IS_CLOUD_IMAGE" = "true" ]; then \ - cp /tmp/cloud-images/workaround/grubmenu.cfg /etc/kairos/branding/grubmenu.cfg && \ - cp /tmp/cloud-images/workaround/custom-post-reset.yaml /system/oem/custom-post-reset.yaml; \ +RUN --mount=type=bind,target=/build-context \ + # Extract local-ui for all build types (ISO, UKI, Cloud, MAAS) + if [ -f /build-context/local-ui.tar ]; then \ + mkdir -p /opt/spectrocloud && \ + tar -xf /build-context/local-ui.tar -C /opt/spectrocloud; \ + fi && \ + # Cloud-specific configuration + if [ "$IS_CLOUD_IMAGE" = "true" ]; then \ + cp /build-context/cloud-images/workaround/grubmenu.cfg /etc/kairos/branding/grubmenu.cfg && \ + cp /build-context/cloud-images/workaround/custom-post-reset.yaml /system/oem/custom-post-reset.yaml && \ + mkdir -p /opt/spectrocloud/scripts && \ + cp /build-context/cloudconfigs/cloud-content.sh /opt/spectrocloud/scripts/cloud-content.sh && \ + chmod 755 /opt/spectrocloud/scripts/cloud-content.sh && \ + cp /build-context/cloudconfigs/cloud-extend-persistent.sh /opt/spectrocloud/scripts/cloud-extend-persistent.sh && \ + chmod 755 /opt/spectrocloud/scripts/cloud-extend-persistent.sh; \ + fi && \ + # MAAS-specific configuration + if [ "$IS_MAAS" = "true" ]; then \ + mkdir -p /opt/spectrocloud/scripts && \ + cp /build-context/cloudconfigs/maas-content.sh /opt/spectrocloud/scripts/maas-content.sh && \ + chmod 755 /opt/spectrocloud/scripts/maas-content.sh; \ fi RUN rm -f /etc/ssh/ssh_host_* /etc/ssh/moduli && \ touch /etc/machine-id && \ - chmod 444 /etc/machine-id && \ - rm -rf /tmp/cloud-images \ No newline at end of file + chmod 444 /etc/machine-id diff --git a/dockerfiles/Dockerfile.provider-image b/dockerfiles/Dockerfile.provider-image index da01d4f9..c564f9d6 100644 --- a/dockerfiles/Dockerfile.provider-image +++ b/dockerfiles/Dockerfile.provider-image @@ -76,9 +76,11 @@ RUN if [ -f /tmp/stylus-image/system/oem/80_stylus.yaml ]; then \ fi && \ rm -rf /tmp/stylus-image -COPY . /tmp/build-context/ -RUN if [ -f /tmp/build-context/"$EDGE_CUSTOM_CONFIG" ]; then \ - cp /tmp/build-context/"$EDGE_CUSTOM_CONFIG" /oem/.edge_custom_config.yaml; \ +# Use bind mount to conditionally copy EDGE_CUSTOM_CONFIG without adding to image layers +RUN --mount=type=bind,target=/build-context \ + if [ -n "$EDGE_CUSTOM_CONFIG" ] && [ -f /build-context/"$EDGE_CUSTOM_CONFIG" ]; then \ + mkdir -p /oem && \ + cp /build-context/"$EDGE_CUSTOM_CONFIG" /oem/.edge_custom_config.yaml; \ fi COPY --from=install-k8s /output/ /k8s @@ -133,5 +135,3 @@ RUN if [ "$TWO_NODE" = "true" ]; then \ sed -i 's/After=network.target/After=network-online.target/' /lib/systemd/system/postgresql@.service && \ systemctl disable postgresql; \ fi - -RUN rm -rf /tmp/build-context \ No newline at end of file diff --git a/dockerfiles/Dockerfile.uki-provider-image b/dockerfiles/Dockerfile.uki-provider-image index 8f901496..e6e9c6d3 100644 --- a/dockerfiles/Dockerfile.uki-provider-image +++ b/dockerfiles/Dockerfile.uki-provider-image @@ -28,10 +28,11 @@ COPY --from=kairos-agent /output/kairos-agent /usr/bin/kairos-agent COPY --from=trust-boot-unpack /trusted-boot/ /trusted-boot/ COPY --from=install-k8s /output/ /k8s/ -# Copy build context to handle optional files -COPY . /tmp/build-context/ -RUN if [ -f /tmp/build-context/"$EDGE_CUSTOM_CONFIG" ]; then \ - cp /tmp/build-context/"$EDGE_CUSTOM_CONFIG" /oem/.edge_custom_config.yaml; \ +# Use bind mount to conditionally copy EDGE_CUSTOM_CONFIG without adding to image layers +RUN --mount=type=bind,target=/build-context \ + if [ -n "$EDGE_CUSTOM_CONFIG" ] && [ -f /build-context/"$EDGE_CUSTOM_CONFIG" ]; then \ + mkdir -p /oem && \ + cp /build-context/"$EDGE_CUSTOM_CONFIG" /oem/.edge_custom_config.yaml; \ fi # Copy stylus-image to temp location to handle optional 80_stylus.yaml (Docker doesn't have --if-exists) @@ -39,6 +40,5 @@ COPY --from=stylus-image / /tmp/stylus-image/ RUN if [ -f /tmp/stylus-image/system/oem/80_stylus.yaml ]; then \ mkdir -p /system/oem && \ cp /tmp/stylus-image/system/oem/80_stylus.yaml /system/oem/80_stylus.yaml; \ - fi - -RUN rm -rf /tmp/stylus-image /tmp/build-context \ No newline at end of file + fi && \ + rm -rf /tmp/stylus-image diff --git a/dockerfiles/Dockerfile.validate-ud b/dockerfiles/Dockerfile.validate-ud index e504631e..a722334e 100644 --- a/dockerfiles/Dockerfile.validate-ud +++ b/dockerfiles/Dockerfile.validate-ud @@ -4,13 +4,12 @@ FROM --platform=linux/${ARCH} ${CLI_IMAGE} AS validate-user-data RUN chmod +x /usr/local/bin/palette-edge-cli -COPY . /tmp/context - -RUN mkdir -p /validated && \ - if [ -f /tmp/context/user-data ]; then \ - /usr/local/bin/palette-edge-cli validate -f /tmp/context/user-data && \ - cp /tmp/context/user-data /validated/config.yaml; \ +# Use bind mount to access user-data without copying entire context +RUN --mount=type=bind,target=/build-context \ + mkdir -p /validated && \ + if [ -f /build-context/user-data ]; then \ + /usr/local/bin/palette-edge-cli validate -f /build-context/user-data && \ + cp /build-context/user-data /validated/config.yaml; \ else \ echo "user-data file does not exist (skipping validation)"; \ - fi; \ - rm -rf /tmp/context \ No newline at end of file + fi \ No newline at end of file diff --git a/earthly.sh b/earthly.sh index 9c50e22d..4b35c9b4 100755 --- a/earthly.sh +++ b/earthly.sh @@ -179,9 +179,8 @@ if [[ "$1" == "+maas-image" ]]; then fi # Run the original build-kairos-maas.sh script locally - # The script expects curtin-hooks to be in ORIG_DIR (the directory where the script is invoked from) - # Copy curtin-hooks to the repo root (current directory) so the script can find it - cp "$CURTIN_HOOKS" ./curtin-hooks + # Export path to curtin-hooks so the build script can find it + export CURTIN_HOOKS_SCRIPT="$(readlink -f "$CURTIN_HOOKS")" # Check for files to add to content partition # The build script looks for: @@ -286,26 +285,12 @@ if [[ "$1" == "+maas-image" ]]; then exit 1 fi - # Move the compressed composite image to build directory for consistency + # Move the compressed composite image and checksum to build directory mkdir -p build mv "$COMPOSITE_IMAGE" "build/$COMPOSITE_IMAGE" + mv "${COMPOSITE_IMAGE}.sha256" "build/${COMPOSITE_IMAGE}.sha256" 2>/dev/null || true - # Generate SHA256 checksum file for the final image - echo "=== Generating SHA256 checksum ===" - FINAL_IMAGE_PATH="build/$COMPOSITE_IMAGE" - sha256sum "$FINAL_IMAGE_PATH" > "${FINAL_IMAGE_PATH}.sha256" - echo "✅ SHA256 checksum created: ${FINAL_IMAGE_PATH}.sha256" - - # Clean up temporary curtin-hooks file from repo root - rm -f ./curtin-hooks - - # Show final image size and checksum - FINAL_SIZE=$(du -h "$FINAL_IMAGE_PATH" | cut -f1) - CHECKSUM=$(cat "${FINAL_IMAGE_PATH}.sha256" | cut -d' ' -f1) - echo "✅ MAAS composite image created and compressed successfully: $FINAL_IMAGE_PATH" - echo " Final size: $FINAL_SIZE" - echo " SHA256: $CHECKSUM" - echo " MAAS will automatically decompress this image during upload." + echo "✅ MAAS image build complete: build/$COMPOSITE_IMAGE" exit 0 fi