diff --git a/.github/workflows/reusable-build.yml b/.github/workflows/reusable-build.yml index 0b7b0e6..a472596 100644 --- a/.github/workflows/reusable-build.yml +++ b/.github/workflows/reusable-build.yml @@ -14,9 +14,10 @@ on: env: IMAGE_REGISTRY: ghcr.io/${{ github.repository_owner }} + KERNEL_FLAVOR: ${{ inputs.coreos_version == 'stable' && 'longterm-6.12' || format('coreos-{0}', inputs.coreos_version) }} concurrency: - group: ${{ github.workflow }}-${{ github.ref || github.run_id }}-${{ inputs.fedora_version }} + group: ${{ github.workflow }}-${{ github.ref || github.run_id }}-${{ inputs.coreos_version }} cancel-in-progress: true jobs: @@ -85,7 +86,7 @@ jobs: exit 1 fi - kernel=$(skopeo inspect docker://ghcr.io/ublue-os/akmods:coreos-${{ inputs.coreos_version }}-${fedora} | jq -r '.["Labels"]["ostree.linux"]') + kernel=$(skopeo inspect docker://ghcr.io/ublue-os/akmods-zfs:${{ env.KERNEL_FLAVOR }}-${fedora} | jq -r '.["Labels"]["ostree.linux"]') if [ -z "$kernel" ] || [ "null" = "$kernel" ]; then echo "inspected linux (kernel) version must not be empty or null" >&2 exit 1 @@ -114,7 +115,6 @@ jobs: contents: read packages: write env: - KERNEL_FLAVOR: coreos-${{ inputs.coreos_version }} PR_PREFIX: ${{ needs.workflow_info.outputs.pr_prefix }} strategy: fail-fast: false @@ -161,10 +161,8 @@ jobs: # pull the base image used for FROM in containerfile so # we can retry on that unfortunately common failure case podman pull quay.io/fedora/fedora-coreos:${{ env.IMAGE_VERSION }} - podman pull ${{ env.IMAGE_REGISTRY }}/akmods:${{ env.KERNEL_FLAVOR }}-${{ env.FEDORA_VERSION }} podman pull ${{ env.IMAGE_REGISTRY }}/akmods-nvidia:${{ env.KERNEL_FLAVOR }}-${{ env.FEDORA_VERSION }} podman pull ${{ env.IMAGE_REGISTRY }}/akmods-zfs:${{ env.KERNEL_FLAVOR }}-${{ env.FEDORA_VERSION }} - podman pull ${{ env.IMAGE_REGISTRY }}/config:latest - name: Verify versions (image, kernel, zfs) run: | @@ -181,12 +179,6 @@ jobs: echo "env.KERNEL_VERSION must not be empty or null" >&2 exit 1 fi - podman inspect ${{ env.IMAGE_REGISTRY }}/akmods:${{ env.KERNEL_FLAVOR }}-${{ env.FEDORA_VERSION }} > inspect.json - kernel=$(jq -r '.[]["Config"]["Labels"]["ostree.linux"]' inspect.json) - if [[ "${{ env.KERNEL_VERSION }}" != "$kernel"* ]]; then - echo "pulled akmods image kernel ($kernel) does not match expected kernel (${{ env.KERNEL_VERSION }})" >&2 - exit 1 - fi podman inspect ${{ env.IMAGE_REGISTRY }}/akmods-zfs:${{ env.KERNEL_FLAVOR }}-${{ env.FEDORA_VERSION }} > inspect.json kernel=$(jq -r '.[]["Config"]["Labels"]["ostree.linux"]' inspect.json) if [[ "${{ env.KERNEL_VERSION }}" != "$kernel"* ]]; then @@ -265,8 +257,8 @@ jobs: podman cp checksb:/usr/lib/modules/${{ env.KERNEL_VERSION }}/vmlinuz . podman rm -f checksb sbverify --list vmlinuz - curl --retry 3 -Lo kernel-sign.der https://github.com/ublue-os/kernel-cache/raw/main/certs/public_key.der - curl --retry 3 -Lo akmods.der https://github.com/ublue-os/kernel-cache/raw/main/certs/public_key_2.der + curl --retry 3 --retry-delay 5 -Lo kernel-sign.der https://github.com/ublue-os/kernel-cache/raw/main/certs/public_key.der + curl --retry 3 --retry-delay 5 -Lo akmods.der https://github.com/ublue-os/kernel-cache/raw/main/certs/public_key_2.der openssl x509 -in kernel-sign.der -out kernel-sign.crt openssl x509 -in akmods.der -out akmods.crt sbverify --cert kernel-sign.crt vmlinuz || exit 1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2eea525 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.env \ No newline at end of file diff --git a/README.md b/README.md index 1e03531..e26c143 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Please take a look at the included modifications, and help us improve uCore if t - [NAS - Storage](#nas---storage) - [NFS](#nfs) - [Samba](#samba) - - [SecureBoot w/ kmods](#secureboot-w-kmods) + - [SecureBoot](#secureboot) - [NVIDIA](#nvidia) - [Included Drivers](#included-drivers) - [Other Drivers](#other-drivers) @@ -45,6 +45,28 @@ Please take a look at the included modifications, and help us improve uCore if t ## Announcements +### 2025.11.20 - uCore (Fedora 43) Available with LTS Kernel + +Thank you to all for being patient as this update was a bit delayed beyond CoreOS' normal cadence. + +What's new: + +- Based on [Fedora CoreOS 43.20251024.3.0](https://fedoraproject.org/coreos/release-notes?stream=stable) +- uCore stable now uses an [LTS(longterm) 6.12 kernel](https://github.com/ublue-os/ucore/issues/317) +- uCore testing continues to use the upstream kernel +- mergerfs and snapraid have been updated to latest releases and are available for both aarch64/x86_64 + +LTS Kernel Impact: + +- the primary goal is to provide more consistent behavior for servers between updates, thus it is not + the latest (6.17) which could mean some recent hardware is not well supported. +- the primary concern is for users with [SecureBoot enabled](#secureboot); the ublue-os MOK must be + imported before rebooting else the first boot will fail. See the [SecureBoot section](#secureboot) + of this README +- if the LTS kernel is a problem for your use case, we suggest using `ucore:testing` + +Enjoy, and as always if any bugs or problems are found, please [file an issue](https://github.com/ublue-os/ucore/issues)! + ### 2025.11.08 - uCore aarch64(ARM64) is Available It's been [over two years](https://github.com/ublue-os/ucore/issues/15) since originally requested, but ARM64 is finally available in uCore builds! @@ -488,17 +510,38 @@ sudo systemctl enable --now smb.service sudo systemctl status smb.service ``` -### SecureBoot w/ kmods +### SecureBoot -For those wishing to use `nvidia` or `zfs` images with pre-built kmods AND run SecureBoot, the kernel will not load those kmods until the public signing key has been imported as a MOK (Machine-Owner Key). +Those wishing to run SecureBoot for a `stable` image, will need to first import the ublue-os public signing key as a MOK (Machine-Owner Key). -Do so like this: +1. before installing, disable SecureBoot in the system UEFI firmware +2. after confirming ucore is the running image, import the key: ```bash sudo mokutil --import /etc/pki/akmods/certs/akmods-ublue.der ``` -The utility will prompt for a password. The password will be used to verify this key is the one you meant to import, after rebooting and entering the UEFI MOK import utility. +The utility will prompt for a password. The password will be used to verify this key is the one you meant to import, after rebooting and entering the system's UEFI MOK import utility. + +Note: this import process is also required for users of the `testing` image if using nvidia or zfs, though instead of failing to boot only the respective drivers will fail to load. + +#### SecureBoot failure to boot recovery / troubleshooting + +If your system fails to boot with an error like: + +``` +error: ../../grub-core/kern/efi/sb.sc:102:bad shim_signature. +error: ../../grub-core/loader/i386/efi/linux.c:250:you need to load the kernel first. + +Press any key to continue... +``` + +You can either: + +1. rollback to previous deployment of uCore to run the import command above +2. if there is no previous uCore deployment, enter UEFI firmware setup by: + - pressing `ESC` + - at the `grub>` prompt, type `fwsetup` ### NVIDIA diff --git a/ucore/Containerfile b/ucore/Containerfile index f1ca96c..8740354 100644 --- a/ucore/Containerfile +++ b/ucore/Containerfile @@ -1,14 +1,12 @@ -ARG COREOS_VERSION="${COREOS_VERSION:-stable}" -ARG FEDORA_VERSION="${FEDORA_VERSION:-42}" -ARG IMAGE_VERSION="${IMAGE_VERSION:-stable}" -ARG IMAGE_REGISTRY="${IMAGE_REGISTRY:-ghcr.io/ublue-os}" -ARG KERNEL_FLAVOR="${KERNEL_FLAVOR:-coreos-stable}" +ARG COREOS_VERSION +ARG FEDORA_VERSION +ARG IMAGE_VERSION +ARG IMAGE_REGISTRY +ARG KERNEL_FLAVOR # FROMs for copying -ARG AKMODS_COMMON="${IMAGE_REGISTRY}/akmods:${KERNEL_FLAVOR}-${FEDORA_VERSION}" ARG AKMODS_NVIDIA="${IMAGE_REGISTRY}/akmods-nvidia:${KERNEL_FLAVOR}-${FEDORA_VERSION}" ARG AKMODS_ZFS="${IMAGE_REGISTRY}/akmods-zfs:${KERNEL_FLAVOR}-${FEDORA_VERSION}" -FROM ${AKMODS_COMMON} AS akmods-common FROM ${AKMODS_NVIDIA} AS akmods-nvidia FROM ${AKMODS_ZFS} AS akmods-zfs @@ -18,9 +16,10 @@ COPY / / # ucore-minimal image section FROM quay.io/fedora/fedora-coreos:${IMAGE_VERSION} AS ucore-minimal -ARG COREOS_VERSION="${COREOS_VERSION:-stable}" -# build with --build-arg NVIDA_TAG="-nvidia" to install nvidia -ARG NVIDIA_TAG="${NVIDIA_TAG}" +ARG COREOS_VERSION +ARG KERNEL_FLAVOR +# build with --build-arg NVIDIA_TAG="-nvidia" to install nvidia +ARG NVIDIA_TAG COPY system_files/etc /etc COPY system_files/usr/lib /usr/lib/ @@ -29,10 +28,9 @@ COPY system_files/usr/sbin /usr/sbin/ RUN --mount=type=cache,dst=/var/cache/libdnf5 \ --mount=type=cache,dst=/var/cache/rpm-ostree \ --mount=type=bind,from=ctx,src=/,dst=/ctx \ - --mount=type=bind,from=akmods-common,src=/rpms/ucore,dst=/tmp/rpms/akmods-common \ --mount=type=bind,from=akmods-nvidia,src=/rpms,dst=/tmp/rpms/akmods-nvidia \ --mount=type=bind,from=akmods-zfs,src=/rpms,dst=/tmp/rpms/akmods-zfs \ - --mount=type=bind,from=akmods-common,src=/kernel-rpms,dst=/tmp/rpms/kernel \ + --mount=type=bind,from=akmods-zfs,src=/kernel-rpms,dst=/tmp/rpms/kernel \ /ctx/install-ucore-minimal.sh \ && /ctx/post-install-ucore-minimal.sh \ && /ctx/cleanup.sh @@ -42,8 +40,8 @@ RUN ["bootc", "container", "lint"] # ucore image section FROM ucore-minimal AS ucore -ARG COREOS_VERSION="${COREOS_VERSION:-stable}" -ARG NVIDIA_TAG="${NVIDIA_TAG}" +ARG COREOS_VERSION +ARG NVIDIA_TAG RUN --mount=type=cache,dst=/var/cache/libdnf5 \ --mount=type=cache,dst=/var/cache/rpm-ostree \ @@ -56,8 +54,8 @@ RUN ["bootc", "container", "lint"] # ucore-hci image section FROM ucore AS ucore-hci -ARG COREOS_VERSION="${COREOS_VERSION:-stable}" -ARG NVIDIA_TAG="${NVIDIA_TAG}" +ARG COREOS_VERSION +ARG NVIDIA_TAG RUN --mount=type=cache,dst=/var/cache/libdnf5 \ --mount=type=cache,dst=/var/cache/rpm-ostree \ diff --git a/ucore/Justfile b/ucore/Justfile new file mode 100644 index 0000000..aa72770 --- /dev/null +++ b/ucore/Justfile @@ -0,0 +1,38 @@ +set dotenv-load := true + +COREOS_VERSION := env("COREOS_VERSION", "stable") +FEDORA_VERSION := env("FEDORA_VERSION", "43") +IMAGE_REGISTRY := env("IMAGE_REGISTRY", "ghcr.io/ublue-os") +KERNEL_FLAVOR := env("KERNEL_FLAVOR", if COREOS_VERSION == 'stable' { "longterm-6.12" } else { 'coreos-' + COREOS_VERSION }) +NVIDIA_TAG := env("NVIDIA_TAG", "") +PR_PREFIX := env("PR_PREFIX", "") +SELINUX := path_exists('/sys/fs/selinux') +TARGET_IMAGE := env("TARGET_IMAGE", "ucore-minimal") + +_default: + @just --list --unsorted + +get-image-version: + #!/usr/bin/env bash + image=$(skopeo inspect docker://quay.io/fedora/fedora-coreos:{{ COREOS_VERSION }} | \ + jq -r '.["Labels"]["org.opencontainers.image.version"]') + if [ -z "$image" ] || [ "null" = "$image" ]; then + echo "inspected image version must not be empty or null" >&2 + exit 1 + fi + echo "$image" + +build: + #!/usr/bin/env bash + set -euxo pipefail + IMAGE_VERSION=$(just get-image-version) + podman build -f Containerfile \ + --build-arg COREOS_VERSION={{ COREOS_VERSION }} \ + --build-arg FEDORA_VERSION={{ FEDORA_VERSION }} \ + --build-arg IMAGE_VERSION=$IMAGE_VERSION \ + --build-arg IMAGE_REGISTRY={{ IMAGE_REGISTRY }} \ + --build-arg KERNEL_FLAVOR={{ KERNEL_FLAVOR }} \ + --build-arg PR_PREFIX={{ PR_PREFIX }} \ + --build-arg NVIDIA_TAG={{ NVIDIA_TAG }} \ + --target {{ TARGET_IMAGE }} \ + -t "{{ TARGET_IMAGE }}:{{ COREOS_VERSION }}{{ NVIDIA_TAG }}" . diff --git a/ucore/cleanup.sh b/ucore/cleanup.sh index 3ade435..9254505 100755 --- a/ucore/cleanup.sh +++ b/ucore/cleanup.sh @@ -2,7 +2,7 @@ set -eoux pipefail -find /boot/* -maxdepth 0 -exec rm -fr {} \; || true +find /boot/ -maxdepth 1 -mindepth 1 -exec rm -fr {} \; || true find /tmp/* -maxdepth 0 -type d \! -name rpms -exec rm -fr {} \; || true find /var/* -maxdepth 0 -type d \! -name cache -exec rm -fr {} \; find /var/cache/* -maxdepth 0 -type d \! -name libdnf5 \! -name rpm-ostree -exec rm -fr {} \; diff --git a/ucore/install-ucore-minimal.sh b/ucore/install-ucore-minimal.sh index 96a3581..80ff8d7 100755 --- a/ucore/install-ucore-minimal.sh +++ b/ucore/install-ucore-minimal.sh @@ -1,12 +1,21 @@ -#!/bin/sh +#!/usr/bin/env bash set -ouex pipefail ARCH="$(rpm -E %{_arch})" RELEASE="$(rpm -E %fedora)" +case "${KERNEL_FLAVOR}" in +"longterm"*) + KERNEL_NAME="kernel-longterm" + ;; +*) + KERNEL_NAME="kernel" + ;; +esac + pushd /tmp/rpms/kernel -KERNEL_VERSION=$(find kernel-*.rpm | grep -P "kernel-(\d+\.\d+\.\d+)-.*\.fc${RELEASE}\.${ARCH}" | sed -E 's/kernel-//' | sed -E 's/\.rpm//') +KERNEL_VERSION=$(find "$KERNEL_NAME"-*.rpm | grep -P "$KERNEL_NAME-(\d+\.\d+\.\d+)-.*\.fc${RELEASE}\.${ARCH}" | sed -E "s/$KERNEL_NAME-//" | sed -E 's/\.rpm//') popd #### PREPARE @@ -23,7 +32,7 @@ fi # enable ublue-os repos dnf -y install dnf5-plugins dnf -y copr enable ublue-os/packages -dnf -y copr enable ublue-os/ucore +dnf -y copr enable ublue-os/staging # always disable cisco-open264 repo sed -i 's@enabled=1@enabled=0@g' /etc/yum.repos.d/fedora-cisco-openh264.repo @@ -32,30 +41,59 @@ sed -i 's@enabled=1@enabled=0@g' /etc/yum.repos.d/fedora-cisco-openh264.repo # inspect to see what RPMS we copied in find /tmp/rpms/ -dnf -y install /tmp/rpms/akmods-common/ublue-os-ucore-addons*.rpm +# mitigate upstream bug with rpm-ostree failing to layer packages in F43. +# can be removed when rpm-ostree's libdnf submodule is 8eadf440 or newer +if [[ "$(rpm -E %fedora)" -gt 41 ]]; then + dnf5 -y swap --repo='copr:copr.fedorainfracloud.org:ublue-os:staging' \ + rpm-ostree rpm-ostree + dnf5 versionlock add rpm-ostree +fi + +# provide ublue-akmods public_key for MOK enroll +dnf -y install /tmp/rpms/akmods-zfs/ucore/ublue-os-ucore-addons*.rpm + dnf -y install ublue-os-signing # Put the policy file in the correct place and cleanup /usr/etc cp /usr/etc/containers/policy.json /etc/containers/policy.json rm -rf /usr/etc +# mitigate problem on F43 where during kernel install, dracut errors and fails +# create a shim to bypass all of kernel-install... maybe not safe? +#mv /usr/sbin/kernel-install /usr/sbin/kernel-install.bak +#printf '%s\n' '#!/bin/sh' 'exit 0' > /usr/sbin/kernel-install +#mv -f /usr/sbin/kernel-install.bak /usr/sbin/kernel-install +# +# create a shim to bypass kernel install triggering dracut/rpm-ostree +# seems to be minimal impact, but allows progress on build +# NOTE: these shims are left in place permanently to support downstream +# builds, original files kept for reference +cd /usr/lib/kernel/install.d \ +&& mv 05-rpmostree.install 05-rpmostree.install.original \ +&& mv 50-dracut.install 50-dracut.install.original \ +&& printf '%s\n' '#!/bin/sh' 'exit 0' > 05-rpmostree.install \ +&& printf '%s\n' '#!/bin/sh' 'exit 0' > 50-dracut.install \ +&& chmod +x 05-rpmostree.install 50-dracut.install +# instead of shims, could skip scriptlets: dnf install -y --setopt=tsflags=noscripts +# but skipping all scriptlets for kernel install may not be safe + # Replace Existing Kernel with packages from akmods cached kernel for pkg in kernel kernel-core kernel-modules kernel-modules-core kernel-modules-extra; do if rpm -q $pkg >/dev/null 2>&1; then rpm --erase $pkg --nodeps fi done -echo "Install kernel version ${KERNEL_VERSION} from kernel-cache." +echo "Install $KERNEL_NAME version ${KERNEL_VERSION} from kernel-cache." dnf -y install \ - /tmp/rpms/kernel/kernel-[0-9]*.rpm \ - /tmp/rpms/kernel/kernel-core-*.rpm \ - /tmp/rpms/kernel/kernel-modules-*.rpm + /tmp/rpms/kernel/"$KERNEL_NAME"-[0-9]*.rpm \ + /tmp/rpms/kernel/"$KERNEL_NAME"-core-*.rpm \ + /tmp/rpms/kernel/"$KERNEL_NAME"-modules-*.rpm # Ensure kernel packages can't be updated by other dnf operations -dnf versionlock add kernel kernel-core kernel-modules kernel-modules-core kernel-modules-extra +dnf versionlock add "$KERNEL_NAME" "$KERNEL_NAME"-core "$KERNEL_NAME"-modules "$KERNEL_NAME"-modules-core "$KERNEL_NAME"-modules-extra # Regenerate initramfs, for new kernel; not including NVIDIA or ZFS kmods -QUALIFIED_KERNEL="$(rpm -qa | grep -P 'kernel-(\d+\.\d+\.\d+)' | sed -E 's/kernel-//')" +QUALIFIED_KERNEL="$(rpm -qa | grep -P "$KERNEL_NAME-(\d+\.\d+\.\d+)" | sed -E "s/$KERNEL_NAME-//")" /usr/bin/dracut --no-hostonly --kver "$QUALIFIED_KERNEL" --reproducible -v --add ostree -f "/lib/modules/$QUALIFIED_KERNEL/initramfs.img" chmod 0600 "/lib/modules/$QUALIFIED_KERNEL/initramfs.img" @@ -69,6 +107,12 @@ depmod -a "${KERNEL_VERSION}" ## CONDITIONAL: install NVIDIA if [[ "-nvidia" == "${NVIDIA_TAG}" ]]; then # uCore expects NVIDIA drivers are able to hot load/unload, thus does not provide it in the initramfs + + # mitigate upstream packaging bug: https://bugzilla.redhat.com/show_bug.cgi?id=2332429 + # swap the incorrectly installed OpenCL-ICD-Loader for ocl-icd, the expected package + dnf5 -y swap --repo='fedora' \ + OpenCL-ICD-Loader ocl-icd + # repo for nvidia rpms curl --fail --retry 15 --retry-all-errors -sSL https://negativo17.org/repos/fedora-nvidia.repo -o /etc/yum.repos.d/fedora-nvidia.repo @@ -76,9 +120,16 @@ if [[ "-nvidia" == "${NVIDIA_TAG}" ]]; then sed -i '0,/enabled=0/{s/enabled=0/enabled=1/}' /etc/yum.repos.d/nvidia-container-toolkit.repo dnf -y install \ - /tmp/rpms/akmods-nvidia/kmods/kmod-nvidia*.rpm \ - nvidia-driver-cuda \ + /tmp/rpms/akmods-nvidia/kmods/kmod-nvidia*.rpm + + # hack required until nvidia-container-toolkit and dnf6 (fedora43) are playing nice + # per: https://github.com/NVIDIA/nvidia-container-toolkit/issues/1307#issuecomment-3486656389 + echo "%_pkgverify_level none" >/etc/rpm/macros.verify + dnf -y install \ nvidia-container-toolkit + rm /etc/rpm/macros.verify + dnf -y install \ + nvidia-driver-cuda fi ## CONDITIONAL: install packages specific to x86_64 diff --git a/ucore/post-install-ucore-minimal.sh b/ucore/post-install-ucore-minimal.sh index 69b3665..596897c 100755 --- a/ucore/post-install-ucore-minimal.sh +++ b/ucore/post-install-ucore-minimal.sh @@ -13,7 +13,8 @@ fi ## ALWAYS: regular post-install -systemctl disable coreos-oci-migration-motd.service +systemctl mask coreos-container-signing-migration-motd.service +systemctl mask coreos-oci-migration-motd.service systemctl disable docker.socket systemctl disable zincati.service