diff --git a/.github/workflows/build-stable.yml b/.github/workflows/build-stable.yml index 20d8114..96fca89 100644 --- a/.github/workflows/build-stable.yml +++ b/.github/workflows/build-stable.yml @@ -1,9 +1,13 @@ name: stable on: - pull_request: merge_group: + pull_request: + branches: + - main + paths-ignore: + - "**.md" schedule: - - cron: '40 23 * * *' # 11:45PM UTC everyday (approx 1.5 hours after coreos images publish) + - cron: '50 2 * * *' # 2:50am-ish UTC everyday (approx 45 minutes after akmods images run) workflow_dispatch: jobs: diff --git a/.github/workflows/build-testing.yml b/.github/workflows/build-testing.yml index 8baaa11..7bca034 100644 --- a/.github/workflows/build-testing.yml +++ b/.github/workflows/build-testing.yml @@ -1,9 +1,13 @@ name: testing on: - pull_request: merge_group: + pull_request: + branches: + - main + paths-ignore: + - "**.md" schedule: - - cron: '55 23 * * *' # 11:45PM UTC everyday (approx 1.75 hours after coreos images publish) + - cron: '55 2 * * *' # 2:55am-ish UTC everyday (approx 50 minutes after akmods images run) workflow_dispatch: jobs: diff --git a/.github/workflows/reusable-build.yml b/.github/workflows/reusable-build.yml index b87fbf9..94b9399 100644 --- a/.github/workflows/reusable-build.yml +++ b/.github/workflows/reusable-build.yml @@ -9,10 +9,14 @@ on: env: IMAGE_REGISTRY: ghcr.io/${{ github.repository_owner }} +concurrency: + group: ${{ github.workflow }}-${{ github.ref || github.run_id }}-${{ inputs.fedora_version }} + cancel-in-progress: true + jobs: workflow_info: name: Get Workflow Info - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 outputs: pr_prefix: ${{ steps.pr_prefix.outputs.pr_prefix }} steps: @@ -32,14 +36,15 @@ jobs: stream_info: name: Get Stream Info - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 outputs: - linux: ${{ fromJSON(steps.fetch.outputs.outputs).linux }} - version: ${{ fromJSON(steps.fetch.outputs.outputs).version }} + fedora: ${{ fromJSON(steps.fetch.outputs.outputs).fedora}} + image: ${{ fromJSON(steps.fetch.outputs.outputs).image}} + kernel: ${{ fromJSON(steps.fetch.outputs.outputs).kernel}} steps: - name: Fetch CoreOS stream versions id: fetch - uses: Wandalen/wretry.action@v3.0.0 + uses: Wandalen/wretry.action@v3.7.3 with: attempt_limit: 3 attempt_delay: 15000 @@ -48,33 +53,48 @@ jobs: skopeo inspect docker://quay.io/fedora/fedora-coreos:${{ inputs.coreos_version }} > inspect.json - linux=$(jq -r '.["Labels"]["ostree.linux"]' inspect.json) - if [ -z "$linux" ] || [ "null" = "$linux" ]; then - echo "inspected linux version must not be empty or null" + image=$(jq -r '.["Labels"]["org.opencontainers.image.version"]' inspect.json) + if [ -z "$image" ] || [ "null" = "$image" ]; then + echo "inspected image version must not be empty or null" exit 1 fi - version=$(jq -r '.["Labels"]["org.opencontainers.image.version"]' inspect.json) - if [ -z "$version" ] || [ "null" = "$version" ]; then - echo "inspected image version must not be empty or null" + fedora=$(echo "$image" | cut -f1 -d.) + if [ -z "$fedora" ] || [ "null" = "$fedora" ]; then + echo "fedora version must not be empty or null" + exit 1 + fi + + kernel=$(skopeo inspect docker://ghcr.io/ublue-os/coreos-${{ inputs.coreos_version }}-kernel:${fedora} | jq -r '.["Labels"]["ostree.linux"]') + if [ -z "$kernel" ] || [ "null" = "$kernel" ]; then + echo "inspected linux (kernel) version must not be empty or null" exit 1 fi - echo "linux=$linux" >> $GITHUB_OUTPUT - echo "version=$version" >> $GITHUB_OUTPUT + + echo "kernel=$kernel" >> $GITHUB_OUTPUT + echo "image=$image" >> $GITHUB_OUTPUT + echo "fedora=$fedora" >> $GITHUB_OUTPUT - name: Echo outputs run: | echo "${{ steps.fetch.outputs.outputs }}" build_fcos: name: fedora-coreos - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 if: always() && !cancelled() needs: [workflow_info, stream_info] permissions: contents: read packages: write id-token: write + env: + FEDORA_VERSION: ${{ needs.stream_info.outputs.fedora}} + IMAGE_NAME: fedora-coreos + IMAGE_VERSION: ${{ needs.stream_info.outputs.image}} + KERNEL_FLAVOR: coreos-${{ inputs.coreos_version }} + KERNEL_VERSION: ${{ needs.stream_info.outputs.kernel}} + PR_PREFIX: ${{ needs.workflow_info.outputs.pr_prefix }} strategy: fail-fast: false matrix: @@ -84,10 +104,6 @@ jobs: zfs_tag: - "-zfs" - "" - include: - - image_name: fedora-coreos - - image_version: ${{ needs.stream_info.outputs.version }} - - pr_prefix: ${{ needs.workflow_info.outputs.pr_prefix }} exclude: - nvidia_tag: "" zfs_tag: "" @@ -96,11 +112,73 @@ jobs: - name: Checkout Push to Registry action uses: actions/checkout@v4 - - name: Verify version + - name: Pull base and kmod images + uses: Wandalen/wretry.action@v3.7.3 + with: + attempt_limit: 3 + attempt_delay: 15000 + command: | + # 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:${{ inputs.coreos_version }} + podman pull ${{ env.IMAGE_REGISTRY }}/${{ env.KERNEL_FLAVOR }}-kernel:${{ env.FEDORA_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 + shell: bash + run: | + set -x + if [ -z "${{ env.FEDORA_VERSION }}" ] || [ "null" = "${{ env.FEDORA_VERSION }}" ]; then + echo "env.FEDORA_VERSION must not be empty or null" + exit 1 + fi + if [ -z "${{ env.IMAGE_VERSION }}" ] || [ "null" = "${{ env.IMAGE_VERSION }}" ]; then + echo "env.IMAGE_VERSION must not be empty or null" + exit 1 + fi + if [ -z "${{ env.KERNEL_VERSION }}" ] || [ "null" = "${{ env.KERNEL_VERSION }}" ]; then + echo "env.KERNEL_VERSION must not be empty or null" + exit 1 + fi + + #Use Podman Inspect instead of skopeo for local checks. + podman inspect ${{ env.IMAGE_REGISTRY }}/${{ env.KERNEL_FLAVOR }}-kernel:${{ env.FEDORA_VERSION }} > inspect.json + kernel=$(jq -r '.[]["Config"]["Labels"]["ostree.linux"]' inspect.json) + if [[ "${{ env.KERNEL_VERSION }}" != "$kernel"* ]]; then + echo "pulled kernel-cache image kernel ($kernel) does not match expected kernel (${{ env.KERNEL_VERSION }})" + 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 }})" + exit 1 + fi + + - name: Verify versions (nvidia) + if: matrix.nvidia_tag == '-nvidia' shell: bash run: | - if [ -z "${{ matrix.image_version }}" ] || [ "null" = "${{ matrix.image_version }}" ]; then - echo "matrix.image_version must not be empty or null" + set -x + podman inspect ${{ env.IMAGE_REGISTRY }}/akmods-nvidia:${{ 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-nvidia image kernel ($kernel) does not match expected kernel (${{ env.KERNEL_VERSION }})" + exit 1 + fi + + - name: Verify versions (ZFS) + if: matrix.zfs_tag == '-zfs' + shell: bash + run: | + set -x + 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 + echo "pulled akmods-zfs image kernel ($kernel) does not match expected kernel (${{ env.KERNEL_VERSION }})" exit 1 fi @@ -146,23 +224,13 @@ jobs: id: meta with: images: | - ${{ matrix.image_name }} + ${{ env.IMAGE_NAME }} labels: | io.artifacthub.package.logo-url=https://avatars.githubusercontent.com/u/120078124?s=200&v=4 io.artifacthub.package.readme-url=https://raw.githubusercontent.com/ublue-os/ucore/main/README.md org.opencontainers.image.description=An OCI image of Fedora CoreOS with NVIDIA and/or ZFS pre-installed - org.opencontainers.image.title=${{ matrix.image_name }} - org.opencontainers.image.version=${{ matrix.image_version }} - - - name: Pull base image - uses: Wandalen/wretry.action@v3.0.0 - with: - attempt_limit: 3 - attempt_delay: 15000 - command: | - # 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:${{ inputs.coreos_version }} + org.opencontainers.image.title=${{ env.IMAGE_NAME }} + org.opencontainers.image.version=${{ env.IMAGE_VERSION }} # Build image using Buildah action - name: Build Image @@ -172,17 +240,39 @@ jobs: containerfiles: | ./fedora-coreos/Containerfile context: ./fedora-coreos - image: ${{ matrix.image_name }} + image: ${{ env.IMAGE_NAME }} tags: | ${{ steps.generate-tags.outputs.alias_tags }} build-args: | COREOS_VERSION=${{ inputs.coreos_version }} - PR_PREFIX=${{ matrix.pr_prefix }} + FEDORA_VERSION=${{ env.FEDORA_VERSION }} + IMAGE_REGISTRY=${{ env.IMAGE_REGISTRY }} + KERNEL_FLAVOR=${{ env.KERNEL_FLAVOR }} + PR_PREFIX=${{ env.PR_PREFIX }} NVIDIA_TAG=${{ matrix.nvidia_tag }} ZFS_TAG=${{ matrix.zfs_tag }} labels: ${{ steps.meta.outputs.labels }} oci: false + - name: Check Secureboot + shell: bash + run: | + set -x + if [[ ! $(command -v sbverify) || ! $(command -v curl) || ! $(command -v openssl) ]]; then + sudo apt update + sudo apt install sbsigntool curl openssl + fi + podman run -d --rm --name ${{env.IMAGE_NAME}}-$(echo "${{ steps.generate-tags.outputs.alias_tags }}" | cut -d " " -f 1) "${{ env.IMAGE_NAME }}":$(echo "${{ steps.generate-tags.outputs.alias_tags }}" | cut -d " " -f 1) sleep 1000 + podman cp ${{env.IMAGE_NAME}}-$(echo "${{ steps.generate-tags.outputs.alias_tags }}" | cut -d " " -f 1):/usr/lib/modules/${{ env.KERNEL_VERSION }}/vmlinuz . + podman rm -f ${{env.IMAGE_NAME}}-$(echo "${{ steps.generate-tags.outputs.alias_tags }}" | cut -d " " -f 1) + 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 + 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 + sbverify --cert akmods.crt vmlinuz || exit 1 + # Workaround bug where capital letters in your GitHub username make it impossible to push to GHCR. # https://github.com/macbre/push-to-ghcr/issues/12 - name: Lowercase Registry @@ -193,7 +283,7 @@ jobs: # Push the image to GHCR (Image Registry) - name: Push To GHCR - uses: Wandalen/wretry.action@v3.0.0 + uses: Wandalen/wretry.action@v3.7.3 id: push if: github.event_name != 'pull_request' env: @@ -221,7 +311,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} # Sign container - - uses: sigstore/cosign-installer@v3.4.0 + - uses: sigstore/cosign-installer@v3.7.0 if: github.event_name != 'pull_request' - name: Sign container image @@ -240,13 +330,20 @@ jobs: build_ucore: name: ucore - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 if: always() && !cancelled() needs: [workflow_info, stream_info] permissions: contents: read packages: write id-token: write + env: + FEDORA_VERSION: ${{ needs.stream_info.outputs.fedora}} + IMAGE_VERSION: ${{ needs.stream_info.outputs.image}} + KERNEL_FLAVOR: coreos-${{ inputs.coreos_version }} + KERNEL_VERSION: ${{ needs.stream_info.outputs.kernel}} + PR_PREFIX: ${{ needs.workflow_info.outputs.pr_prefix }} + strategy: fail-fast: false matrix: @@ -261,9 +358,6 @@ jobs: - "-zfs" - "" include: - - image_base: ucore - - image_version: ${{ needs.stream_info.outputs.version }} - - pr_prefix: ${{ needs.workflow_info.outputs.pr_prefix }} - image_suffix: "-minimal" description: An OCI image of Fedora CoreOS with a few extra tools and suitable for running in a VM - image_suffix: "" @@ -276,11 +370,79 @@ jobs: - name: Checkout Push to Registry action uses: actions/checkout@v4 - - name: Verify version + # sent env variables which depend on the matrix + - name: Matrix variables shell: bash run: | - if [ -z "${{ matrix.image_version }}" ] || [ "null" = "${{ matrix.image_version }}" ]; then - echo "matrix.image_version must not be empty or null" + set -x + IMAGE_NAME=ucore${{ matrix.image_suffix }} + echo "IMAGE_NAME=$IMAGE_NAME" >> $GITHUB_ENV + + - name: Pull base and kmod images + uses: Wandalen/wretry.action@v3.7.3 + with: + attempt_limit: 3 + attempt_delay: 15000 + command: | + # 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:${{ inputs.coreos_version }} + podman pull ${{ env.IMAGE_REGISTRY }}/${{ env.KERNEL_FLAVOR }}-kernel:${{ env.FEDORA_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 + shell: bash + run: | + set -x + if [ -z "${{ env.FEDORA_VERSION }}" ] || [ "null" = "${{ env.FEDORA_VERSION }}" ]; then + echo "env.FEDORA_VERSION must not be empty or null" + exit 1 + fi + if [ -z "${{ env.IMAGE_VERSION }}" ] || [ "null" = "${{ env.IMAGE_VERSION }}" ]; then + echo "env.IMAGE_VERSION must not be empty or null" + exit 1 + fi + if [ -z "${{ env.KERNEL_VERSION }}" ] || [ "null" = "${{ env.KERNEL_VERSION }}" ]; then + echo "env.KERNEL_VERSION must not be empty or null" + exit 1 + fi + podman inspect ${{ env.IMAGE_REGISTRY }}/${{ env.KERNEL_FLAVOR }}-kernel:${{ env.FEDORA_VERSION }} > inspect.json + kernel=$(jq -r '.[]["Config"]["Labels"]["ostree.linux"]' inspect.json) + if [[ "${{ env.KERNEL_VERSION }}" != "$kernel"* ]]; then + echo "pulled kernel-cache image kernel ($kernel) does not match expected kernel (${{ env.KERNEL_VERSION }})" + 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 }})" + exit 1 + fi + + - name: Verify versions (nvidia) + if: matrix.nvidia_tag == '-nvidia' + shell: bash + run: | + set -x + podman inspect ${{ env.IMAGE_REGISTRY }}/akmods-nvidia:${{ 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-nvidia image kernel ($kernel) does not match expected kernel (${{ env.KERNEL_VERSION }})" + exit 1 + fi + + - name: Verify versions (ZFS) + if: matrix.zfs_tag == '-zfs' + shell: bash + run: | + set -x + 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 + echo "pulled akmods-zfs image kernel ($kernel) does not match expected kernel (${{ env.KERNEL_VERSION }})" exit 1 fi @@ -330,23 +492,13 @@ jobs: id: meta with: images: | - ${{ matrix.image_base }}${{ matrix.image_suffix }} + ${{ env.IMAGE_NAME }} labels: | io.artifacthub.package.logo-url=https://avatars.githubusercontent.com/u/120078124?s=200&v=4 io.artifacthub.package.readme-url=https://raw.githubusercontent.com/ublue-os/ucore/main/README.md org.opencontainers.image.description=${{ matrix.description }} - org.opencontainers.image.title=${{ matrix.image_base }}${{ matrix.image_suffix }} - org.opencontainers.image.version=${{ matrix.image_version }} - - - name: Pull base image - uses: Wandalen/wretry.action@v3.0.0 - with: - attempt_limit: 3 - attempt_delay: 15000 - command: | - # 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:${{ inputs.coreos_version }} + org.opencontainers.image.title=${{ env.IMAGE_NAME }} + org.opencontainers.image.version=${{ env.IMAGE_VERSION }} # Build image using Buildah action - name: Build Image @@ -356,18 +508,40 @@ jobs: containerfiles: | ./ucore/Containerfile context: ./ucore - image: ${{ matrix.image_base }}${{ matrix.image_suffix }} + image: ${{ env.IMAGE_NAME }} tags: | ${{ steps.generate-tags.outputs.alias_tags }} build-args: | COREOS_VERSION=${{ inputs.coreos_version }} - PR_PREFIX=${{ matrix.pr_prefix }} + FEDORA_VERSION=${{ env.FEDORA_VERSION }} + IMAGE_REGISTRY=${{ env.IMAGE_REGISTRY }} + KERNEL_FLAVOR=${{ env.KERNEL_FLAVOR }} + PR_PREFIX=${{ env.PR_PREFIX }} NVIDIA_TAG=${{ matrix.nvidia_tag }} ZFS_TAG=${{ matrix.zfs_tag }} labels: ${{ steps.meta.outputs.labels }} oci: false extra-args: | - --target=${{ matrix.image_base }}${{ matrix.image_suffix }} + --target=${{ env.IMAGE_NAME }} + + - name: Check Secureboot + shell: bash + run: | + set -x + if [[ ! $(command -v sbverify) || ! $(command -v curl) || ! $(command -v openssl) ]]; then + sudo apt update + sudo apt install sbsigntool curl openssl + fi + podman run -d --rm --name ${{env.IMAGE_NAME }}-$(echo "${{ steps.generate-tags.outputs.alias_tags }}" | cut -d " " -f 1) "${{ env.IMAGE_NAME }}":$(echo "${{ steps.generate-tags.outputs.alias_tags }}" | cut -d " " -f 1) sleep 1000 + podman cp ${{env.IMAGE_NAME }}-$(echo "${{ steps.generate-tags.outputs.alias_tags }}" | cut -d " " -f 1):/usr/lib/modules/${{ env.KERNEL_VERSION }}/vmlinuz . + podman rm -f ${{env.IMAGE_NAME }}-$(echo "${{ steps.generate-tags.outputs.alias_tags }}" | cut -d " " -f 1) + 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 + 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 + sbverify --cert akmods.crt vmlinuz || exit 1 # Workaround bug where capital letters in your GitHub username make it impossible to push to GHCR. # https://github.com/macbre/push-to-ghcr/issues/12 @@ -379,7 +553,7 @@ jobs: # Push the image to GHCR (Image Registry) - name: Push To GHCR - uses: Wandalen/wretry.action@v3.0.0 + uses: Wandalen/wretry.action@v3.7.3 id: push if: github.event_name != 'pull_request' env: @@ -407,7 +581,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} # Sign container - - uses: sigstore/cosign-installer@v3.4.0 + - uses: sigstore/cosign-installer@v3.7.0 if: github.event_name != 'pull_request' - name: Sign container image diff --git a/README.md b/README.md index 41a9e31..f088147 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,64 @@ -# uCore +# uCore [![stable](https://github.com/ublue-os/ucore/actions/workflows/build-stable.yml/badge.svg)](https://github.com/ublue-os/ucore/actions/workflows/build-stable.yml) [![testing](https://github.com/ublue-os/ucore/actions/workflows/build-testing.yml/badge.svg)](https://github.com/ublue-os/ucore/actions/workflows/build-testing.yml) -## What is this? - -You should be familiar with [Fedora CoreOS](https://getfedora.org/coreos/), as this is an OCI image of CoreOS with "batteries included". More specifically, it's an opinionated, custom CoreOS image, built daily with some commonly used tools added in. The idea is to make a lightweight server image including most used services or the building blocks to host them. - -Please take a look at the included modifications and help us test uCore if the project interests you. - -## Images & Features +uCore is an OCI image of [Fedora CoreOS](https://getfedora.org/coreos/) with "batteries included". More specifically, it's an opinionated, custom CoreOS image, built daily with some common tools added in. The idea is to make a lightweight server image including commonly used services or the building blocks to host them. + +Please take a look at the included modifications, and help us improve uCore if the project interests you. + +## Table of Contents + +- [Announcements](#announcements) +- [Features](#features) + - [Images](#images) + - [`fedora-coreos`](#fedora-coreos) + - [`ucore-minimal`](#ucore-minimal) + - [`ucore`](#ucore) + - [`ucore-hci`](#ucore-hci) + - [Tag Matrix](#tag-matrix) +- [Installation](#installation) + - [Image Verification](#image-verification) + - [Auto-Rebase Install](#auto-rebase-install) + - [Manual Install/Rebase](#manual-installrebase) +- [Tips and Tricks](#tips-and-tricks) + - [CoreOS and ostree Docs](#coreos-and-ostree-docs) + - [Podman](#podman) + - [Immutability and Podman](#immutability-and-podman) + - [Docker/Moby and Podman](#dockermoby-and-podman) + - [Podman and FirewallD](#podman-and-firewalld) + - [Automatically start containers on boot](#automatically-start-containers-on-boot) + - [Default Services](#default-services) + - [SELinux Troubleshooting](#selinux-troubleshooting) + - [Distrobox](#distrobox) + - [NAS - Storage](#nas---storage) + - [NFS](#nfs) + - [Samba](#samba) + - [SecureBoot w/ kmods](#secureboot-w-kmods) + - [NVIDIA](#nvidia) + - [Included Drivers](#included-drivers) + - [Other Drivers](#other-drivers) + - [ZFS](#zfs) + - [ZFS and immutable root filesystem](#zfs-and-immutable-root-filesystem) + - [Sanoid/Syncoid](#sanoidsyncoid) +- [DIY](#diy) +- [Metrics](#metrics) + +## Announcements + +### 2024.11.12 - uCore has updated to Fedora 41 + +As of today our upstream Fedora CoreOS stable image updated to Fedora 41 under the hood, so expect a lot of package updates. + +### 2024.11.12 - uCore *stable* has pinned to kernel version *6.11.3* + +Kernel version `6.11.3` was the previous *stable* update's kernel, and despite the update to Fedora 41, we've stuck with `6.11.3` rather than updating to `6.11.5` from upstream. + +This is due to a kernel bug in versions `6.11.4`/`6.11.5` which [breaks tailscale status reporting](https://github.com/tailscale/tailscale/issues/13863). As many users of uCore do use tailscale, we've decided to be extra cautious and hold back the kernel, even though the rest of stable updated as usual. + +We expect the next update of Fedora CoreOS to be on `6.11.6` per the current state of the testing stream. So uCore will follow when that update occurs. + +## Features The uCore project builds four images, each with different tags for different features. @@ -27,23 +76,26 @@ The [tag matrix](#tag-matrix) includes combinations of the following: - `nvidia` - for an image which includes nvidia driver and container runtime - `zfs` - for an image which includes zfs driver and tools +### Images -### `fedora-coreos` +#### `fedora-coreos` -*NOTE: formerly named `fedora-coreos-zfs`, the previous version of the image did not offer the nvidia option. If on the previous image name, please update with `rpm-ostree rebase`.* +> [!IMPORTANT] +> This was previously named `fedora-coreos-zfs`, but that version of the image did not offer the nvidia option. If on the previous image name, please rebase with `rpm-ostree rebase`. A generic [Fedora CoreOS image](https://quay.io/repository/fedora/fedora-coreos?tab=tags) image with choice of add-on kernel modules: - [nvidia versions](#tag-matrix) add: - - [nvidia driver](https://github.com/ublue-os/ucore-kmods) - latest driver (currently version 535) built from negativo17's akmod package + - [nvidia driver](https://github.com/ublue-os/akmods) - latest driver built from negativo17's akmod package - [nvidia-container-toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/sample-workload.html) - latest toolkit which supports both root and rootless podman containers and CDI - [nvidia container selinux policy](https://github.com/NVIDIA/dgx-selinux/tree/master/src/nvidia-container-selinux) - allows using `--security-opt label=type:nvidia_container_t` for some jobs (some will still need `--security-opt label=disable` as suggested by nvidia) - [ZFS versions](#tag-matrix) add: - - [ZFS driver](https://github.com/ublue-os/ucore-kmods) - latest driver (currently pinned to 2.2.x series) + - [ZFS driver](https://github.com/ublue-os/akmods) - latest driver (currently pinned to 2.2.x series) -*NOTE: currently, zincati fails to start on systems with OCI based deployments (like uCore). Upstream efforts are active to correct this.* +> [!NOTE] +> zincati fails to start on all systems with OCI based deployments (like uCore). Upstream efforts are active to develop an alternative. -### `ucore-minimal` +#### `ucore-minimal` Suitable for running containerized workloads on either bare metal or virtual machines, this image tries to stay lightweight but functional. @@ -53,27 +105,27 @@ Suitable for running containerized workloads on either bare metal or virtual mac - [cockpit](https://cockpit-project.org) (podman container and system management) - [firewalld](https://firewalld.org/) - guest VM agents (`qemu-guest-agent` and `open-vm-tools`)) - - [docker-compose](https://github.com/docker/compose) and [podman-compose](https://github.com/containers/podman-compose) *docker(moby-engine) and podman are pre-installed in CoreOS* + - [docker-buildx](https://github.com/docker/buildx) and [docker-compose](https://github.com/docker/compose) (versions matched to moby release) *docker(moby-engine) is pre-installed in CoreOS* + - [podman-compose](https://github.com/containers/podman-compose) *podman is pre-installed in CoreOS* - [tailscale](https://tailscale.com) and [wireguard-tools](https://www.wireguard.com) - [tmux](https://github.com/tmux/tmux/wiki/Getting-Started) - udev rules enabling full functionality on some [Realtek 2.5Gbit USB Ethernet](https://github.com/wget/realtek-r8152-linux/) devices - Optional [nvidia versions](#tag-matrix) add: - - [nvidia driver](https://github.com/ublue-os/ucore-kmods) - latest driver (currently version 535) built from negativo17's akmod package + - [nvidia driver](https://github.com/ublue-os/ucore-kmods) - latest driver built from negativo17's akmod package - [nvidia-container-toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/sample-workload.html) - latest toolkit which supports both root and rootless podman containers and CDI - [nvidia container selinux policy](https://github.com/NVIDIA/dgx-selinux/tree/master/src/nvidia-container-selinux) - allows using `--security-opt label=type:nvidia_container_t` for some jobs (some will still need `--security-opt label=disable` as suggested by nvidia) - Optional [ZFS versions](#tag-matrix) add: - - [ZFS driver](https://github.com/ublue-os/ucore-kmods) - latest driver (currently pinned to 2.2.x series) - - [cockpit-zfs-manager](https://github.com/45Drives/cockpit-zfs-manager) (an interactive ZFS on Linux admin package for Cockpit) - - [sanoid/syncoid dependencies](https://github.com/jimsalterjrs/sanoid) - [see below](#zfs) for details - - note: on `ucore-minimal` images, only `pv` is installed + - [ZFS driver](https://github.com/ublue-os/ucore-kmods) - latest driver (currently pinned to 2.2.x series) - [see below](#zfs) for details + - `pv` is installed with zfs as a complementary tool - Disables Zincati auto upgrade/reboot service - Enables staging of automatic system updates via rpm-ostreed - Enables password based SSH auth (required for locally running cockpit web interface) - Provides public key allowing [SecureBoot](#secureboot) (for ucore signed `nvidia` or `zfs` drivers) -Note: per [cockpit instructions](https://cockpit-project.org/running.html#coreos) the cockpit-ws RPM is **not** installed, rather it is provided as a pre-defined systemd service which runs a podman container. +> [!IMPORTANT] +> Per [cockpit's instructions](https://cockpit-project.org/running.html#coreos) the cockpit-ws RPM is **not** installed, rather it is provided as a pre-defined systemd service which runs a podman container. -### `ucore` +#### `ucore` This image builds on `ucore-minimal` but adds drivers, storage tools and utilities making it more useful on bare metal or as a storage server (NAS). @@ -86,11 +138,15 @@ This image builds on `ucore-minimal` but adds drivers, storage tools and utiliti - [mergerfs](https://github.com/trapexit/mergerfs) - nfs-utils - nfs utils including daemon for kernel NFS server - [pcp](https://pcp.io) Performance Co-pilot monitoring + - [rclone](https://www.rclone.org/) - file synchronization and mounting of cloud storage - [samba](https://www.samba.org/) and samba-usershares to provide SMB sevices - [snapraid](https://www.snapraid.it/) - usbutils(and pciutils) - technically pciutils is pulled in by open-vm-tools in ucore-minimal +- Optional [ZFS versions](#tag-matrix) add: + - [cockpit-zfs-manager](https://github.com/45Drives/cockpit-zfs-manager) (an interactive ZFS on Linux admin package for Cockpit) + - [sanoid/syncoid dependencies](https://github.com/jimsalterjrs/sanoid) - [see below](#zfs) for details -### `ucore-hci` +#### `ucore-hci` Hyper-Coverged Infrastructure(HCI) refers to storage and hypervisor in one place... This image primarily adds libvirt tools for virtualization. @@ -101,15 +157,141 @@ Hyper-Coverged Infrastructure(HCI) refers to storage and hypervisor in one place - [libvirt-daemon-kvm](https://libvirt.org/): libvirt KVM hypervisor management - virt-install: command-line utility for installing virtual machines -Note: Fedora now uses `DefaultTimeoutStop=45s` for systemd services which could cause `libvirtd` to quit before shutting down slow VMs. Consider adding `TimeoutStopSec=120s` as an override for `libvirtd.service` if needed. +> [!NOTE] +> Fedora uses `DefaultTimeoutStop=45s` for systemd services which could cause `libvirtd` to quit before shutting down slow VMs. Consider adding `TimeoutStopSec=120s` as an override for `libvirtd.service` if needed. + +### Tag Matrix + +| IMAGE | TAG | +|-|-| +| [`fedora-coreos`](#fedora-coreos) - *stable* | `stable-nvidia`, `stable-zfs`,`stable-nvidia-zfs` | +| [`fedora-coreos`](#fedora-coreos) - *testing* | `testing-nvidia`, `testing-zfs`, `testing-nvidia-zfs` | +| [`ucore-minimal`](#ucore-minimal) - *stable* | `stable`, `stable-nvidia`, `stable-zfs`,`stable-nvidia-zfs` | +| [`ucore-minimal`](#ucore-minimal) - *testing* | `testing`, `testing-nvidia`, `testing-zfs`, `testing-nvidia-zfs` | +| [`ucore`](#ucore) - *stable* | `stable`, `stable-nvidia`, `stable-zfs`,`stable-nvidia-zfs` | +| [`ucore`](#ucore) - *testing* | `testing`, `testing-nvidia`, `testing-zfs`, `testing-nvidia-zfs` | +| [`ucore-hci`](#ucore-hci) - *stable* | `stable`, `stable-nvidia`, `stable-zfs`,`stable-nvidia-zfs` | +| [`ucore-hci`](#ucore-hci) - *testing* | `testing`, `testing-nvidia`, `testing-zfs`, `testing-nvidia-zfs` | + +## Installation + +> [!IMPORTANT] +> **Read the [CoreOS installation guide](https://docs.fedoraproject.org/en-US/fedora-coreos/bare-metal/)** before attempting installation. uCore extends Fedora CoreOS; it does not provide it's own custom or GUI installer. + +There are varying methods of installation for bare metal, cloud providers, and virtualization platforms. + +**All CoreOS installation methods require the user to [produce an Ignition file](https://docs.fedoraproject.org/en-US/fedora-coreos/producing-ign/).** This Ignition file should, at mimimum, set a password and SSH key for the default user (default username is `core`). + +> [!TIP] +> For bare metal installs, first test your ignition configuration by installing in a VM (or other test hardware) using the bare metal process. + +### Image Verification + +These images are signed with sigstore's [cosign](https://docs.sigstore.dev/cosign/overview/). You can verify the signature by running the following command: + +```bash +cosign verify --key https://github.com/ublue-os/ucore/raw/main/cosign.pub ghcr.io/ublue-os/IMAGE:TAG +``` + +### Auto-Rebase Install + +One of the fastest paths to running uCore is using [examples/ucore-autorebase.butane](examples/ucore-autorebase.butane) as a template for your CoreOS butane file. + +1. As usual, you'll need to [follow the docs to setup a password](https://coreos.github.io/butane/examples/#using-password-authentication). Substitute your password hash for `YOUR_GOOD_PASSWORD_HASH_HERE` in the `ucore-autorebase.butane` file, and add your ssh pub key while you are at it. +1. Generate an ignition file from your new `ucore-autorebase.butane` [using the butane utility](https://coreos.github.io/butane/getting-started/). +1. Now install CoreOS for [hypervisor, cloud provider or bare-metal](https://docs.fedoraproject.org/en-US/fedora-coreos/bare-metal/). Your ignition file should work for any platform, auto-rebasing to the `ucore:stable` (or other `IMAGE:TAG` combo), rebooting and leaving your install ready to use. + +### Manual Install/Rebase + +Once a machine is running any Fedora CoreOS version, you can easily rebase to uCore. Installing CoreOS itself can be done through [a number of provisioning methods](https://docs.fedoraproject.org/en-US/fedora-coreos/bare-metal/). + +> [!WARNING] +> **Rebasing from Fedora IoT or Atomic Desktops is not supported!** +> If ignition doesn't provide a desired feature, then Fedora CoreOS doesn't support that feature. Rebasing from another system to gain a filesystem feature or GUI installation is very likely to cause problems later on. + +To rebase an existing CoreOS machine to the latest uCore: + +1. Execute the `rpm-ostree rebase` command (below) with desired `IMAGE` and `TAG`. +1. Reboot, as instructed. +1. After rebooting, you should [pin the working deployment](https://docs.fedoraproject.org/en-US/fedora-silverblue/faq/#_how_can_i_upgrade_my_system_to_the_next_major_version_for_instance_rawhide_or_an_upcoming_fedora_release_branch_while_keeping_my_current_deployment) which allows you to rollback if required. + +```bash +sudo rpm-ostree rebase ostree-unverified-registry:ghcr.io/ublue-os/IMAGE:TAG +``` + +#### Verified Image Updates + +The `ucore*` images include container policies to support image verification for improved trust of upgrades. Once running one of the `ucore*` images, the following command will rebase to the verified image reference: + +```bash +sudo rpm-ostree rebase ostree-image-signed:docker://ghcr.io/ublue-os/IMAGE:TAG +``` + +> [!NOTE] +> This policy is not included with `fedora-coreos:*` as those images are kept very stock.* ## Tips and Tricks -### Immutability and Podman +### CoreOS and ostree Docs + +It's a good idea to become familar with the [Fedora CoreOS Documentation](https://docs.fedoraproject.org/en-US/fedora-coreos/) as well as the [CoreOS rpm-ostree docs](https://coreos.github.io/rpm-ostree/). Note especially, this image is only possible due to [ostree native containers](https://coreos.github.io/rpm-ostree/container/). + +### Podman + +#### Immutability and Podman + +A CoreOS root filesystem system is immutable at runtime, and it is not recommended to install packages like in a mutable "normal" distribution. -These images are immutable and you probably shouldn't install packages like in a mutable "normal" distribution. +Fedora CoreOS expects the user to run services using [podman](https://podman.io). `moby-engine`, the free Docker implementation, is also installed for those who desire docker instead of podman. -Fedora CoreOS expects the user to run services using [podman](https://podman.io). `moby-engine`, the free Docker implementation, is installed for those who desire docker instead of podman. +#### Docker/Moby and Podman + +> [!IMPORTANT] +> CoreOS [cautions against](https://docs.fedoraproject.org/en-US/fedora-coreos/faq/#_can_i_run_containers_via_docker_and_podman_at_the_same_time) running podman and docker containers at the same time. Thus, `docker.socket` is disabled by default to prevent accidental activation of the docker daemon, given podman is the default. +> +> Only run both simultaneously if you understand the risk. + +#### Podman and FirewallD + +Podman and firewalld [can sometimes conflict](https://github.com/ublue-os/ucore/issues/90) such that a `firewall-cmd --reload` removes firewall rules generated by podman. + +As of [netavark v1.9.0](https://blog.podman.io/2023/11/new-netavark-firewalld-reload-service/) a service is provided to handle re-adding netavark (Podman) firewall rules after a firewalld reload occurs. If needed, enable like so: `systemctl enable netavark-firewalld-reload.service` + +#### Automatically start containers on boot + +By default, UCore does not automatically start `restart: always` containers on system boot, however this can be easily enabled: + +##### For containers running under the `core` user + +```bash +# Copy the system's podman-restart service to the user location +mkdir -p /var/home/core/.config/systemd/user +cp /lib/systemd/system/podman-restart.service /var/home/core/.config/systemd/user + +# Enable the user service +systemctl --user enable podman-restart.service + +# Check that it's running +systemctl --user list-unit-files | grep podman +``` + +When you next reboot the system, your `restart: always` containers will automatically start. + +You may also need to enable “linger” mode on your user session, to prevent containers exiting which you have started interactively. To do that, run: + +```bash +loginctl enable-linger $UID +``` + +You can find more information regarding this on the [Podman troubleshooting page](https://github.com/containers/podman/blob/main/troubleshooting.md#21-a-rootless-container-running-in-detached-mode-is-closed-at-logout). + +##### For containers running under the root user (rootful containers) + +You just need to enable the built-in service: + +```bash +sudo systemctl enable podman-restart.service +``` ### Default Services @@ -121,13 +303,15 @@ To activate pre-installed services (`cockpit`, `docker`, `tailscaled`, etc): sudo systemctl enable --now SERVICENAME.service ``` -Note: `libvirtd` is enabled by default, but only starts when triggerd by it's socket (eg, using `virsh` or other clients). +> [!NOTE] +> The `libvirtd` is enabled by default, but only starts when triggerd by it's socket (eg, using `virsh` or other clients). ### SELinux Troubleshooting SELinux is an integral part of the Fedora Atomic system design. Due to a few interelated issues, if SELinux is disabled, it's difficult to re-enable. -**We STRONGLY recommend: DO NOT DISABLE SELinux!** +> [!WARNING] +> **We STRONGLY recommend: DO NOT DISABLE SELinux!** Should you suspect that SELinux is causing a problem, it is easy to enable permissive mode at runtime, which will keep SELinux functioning, provide reporting of problems, but not enforce restrictions. @@ -147,41 +331,28 @@ Enforcing Fedora provides useful docs on [SELinux troubleshooting](https://docs.fedoraproject.org/en-US/quick-docs/selinux-troubleshooting/). -### Docker/Moby and Podman - -NOTE: CoreOS [cautions against](https://docs.fedoraproject.org/en-US/fedora-coreos/faq/#_can_i_run_containers_via_docker_and_podman_at_the_same_time) running podman and docker containers at the same time. Thus, `docker.socket` is disabled by default to prevent accidental activation of the docker daemon, given podman is the default. - -### Podman and FirewallD - -Podman and firewalld [can sometimes conflict](https://github.com/ublue-os/ucore/issues/90) such that a `firewall-cmd --reload` removes firewall rules generated by podman. - -As of [netavark v1.9.0](https://blog.podman.io/2023/11/new-netavark-firewalld-reload-service/) a service is provided to handle re-adding netavark (Podman) firewall rules after a firewalld reload occurs. If needed, enable like so: `systemctl enable netavark-firewalld-reload.service` - - ### Distrobox Users may use [distrobox](https://github.com/89luca89/distrobox) to run images of mutable distributions where applications can be installed with traditional package managers. This may be useful for installing interactive utilities such has `htop`, `nmap`, etc. As stated above, however, *services* should run as containers. -### CoreOS and ostree Docs - -It's a good idea to become familar with the [Fedora CoreOS Documentation](https://docs.fedoraproject.org/en-US/fedora-coreos/) as well as the [CoreOS rpm-ostree docs](https://coreos.github.io/rpm-ostree/). Note especially, this image is only possible due to [ostree native containers](https://coreos.github.io/rpm-ostree/container/). - ### NAS - Storage `ucore` includes a few packages geared towards a storage server which will require individual research for configuration: - - [duperemove](https://github.com/markfasheh/duperemove) - - [mergerfs](https://github.com/trapexit/mergerfs) - - [snapraid](https://www.snapraid.it/) + +- [duperemove](https://github.com/markfasheh/duperemove) +- [mergerfs](https://github.com/trapexit/mergerfs) +- [snapraid](https://www.snapraid.it/) But two others are included, which though common, warrant some explanation: - - nfs-utils - replaces a "light" version typically in CoreOS to provide kernel NFS server - - samba and samba-usershares - to provide SMB sevices + +- nfs-utils - replaces a "light" version typically in CoreOS to provide kernel NFS server +- samba and samba-usershares - to provide SMB sevices #### NFS It's suggested to read Fedora's [NFS Server docs](https://docs.fedoraproject.org/en-US/fedora-server/services/filesharing-nfs-installation/) plus other documentation to understand how to setup this service. But here's a few quick tips... -##### Firewall +##### Firewall - NFS Unless you've disabled `firewalld`, you'll need to do this: @@ -190,23 +361,26 @@ sudo firewall-cmd --permanent --zone=FedoraServer --add-service=nfs sudo firewall-cmd --reload ``` -##### SELinux +##### SELinux - NFS By default, nfs-server is blocked from sharing directories unless the context is set. So, generically to enable NFS sharing in SELinux run: For read-only NFS shares: + ```bash sudo semanage fcontext --add --type "public_content_t" "/path/to/share/ro(/.*)? sudo restorecon -R /path/to/share/ro ``` For read-write NFS shares: + ```bash sudo semanage fcontext --add --type "public_content_rw_t" "/path/to/share/rw(/.*)? sudo restorecon -R /path/to/share/rw ``` Say you wanted to share all home directories: + ```bash sudo semanage fcontext --add --type "public_content_rw_t" "/var/home(/.*)? sudo restorecon -R /var/home @@ -215,22 +389,24 @@ sudo restorecon -R /var/home The least secure but simplest way to let NFS share anything configured, is... For read-only: + ```bash sudo setsebool -P nfs_export_all_ro 1 ``` For read-write: + ```bash sudo setsebool -P nfs_export_all_rw 1 ``` There is [more to read](https://linux.die.net/man/8/nfs_selinux) on this topic. -##### Shares +##### Shares - NFS NFS shares are configured in `/etc/exports` or `/etc/exports.d/*` (see docs). -##### Run It +##### Run It - NFS Like all services, NFS needs to be enabled and started: @@ -243,7 +419,7 @@ sudo systemctl status nfs-server.service It's suggested to read Fedora's [Samba docs](https://docs.fedoraproject.org/en-US/quick-docs/samba/) plus other documentation to understand how to setup this service. But here's a few quick tips... -##### Firewall +##### Firewall - Samba Unless you've disabled `firewalld`, you'll need to do this: @@ -252,7 +428,7 @@ sudo firewall-cmd --permanent --zone=FedoraServer --add-service=samba sudo firewall-cmd --reload ``` -##### SELinux +##### SELinux - Samba By default, samba is blocked from sharing directories unless the context is set. So, generically to enable samba sharing in SELinux run: @@ -262,28 +438,31 @@ sudo restorecon -R /path/to/share ``` Say you wanted to share all home directories: + ```bash sudo semanage fcontext --add --type "samba_share_t" "/var/home(/.*)? sudo restorecon -R /var/home ``` The least secure but simplest way to let samba share anything configured, is this: + ```bash sudo setsebool -P samba_export_all_rw 1 ``` There is [much to read](https://linux.die.net/man/8/samba_selinux) on this topic. -##### Shares +##### Shares - Samba Samba shares can be manually configured in `/etc/samba/smb.conf` (see docs), but user shares are also a good option. An example follows, but you'll probably want to read some docs on this, too: + ```bash net usershare add sharename /path/to/share [comment] [user:{R|D|F}] [guest_ok={y|n}] ``` -##### Run It +##### Run It - Samba Like all services, Samba needs to be enabled and started: @@ -292,15 +471,29 @@ sudo systemctl enable --now smb.service sudo systemctl status smb.service ``` +### SecureBoot w/ kmods + +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). + +Do so like this: + +```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. + ### NVIDIA +#### Included Drivers + If you installed an image with `-nvidia` in the tag, the nvidia kernel module, basic CUDA libraries, and the nvidia-container-toolkit are all are pre-installed. Note, this does NOT add desktop graphics services to your images, but it DOES enable your compatible nvidia GPU to be used for nvdec, nvenc, CUDA, etc. Since this is CoreOS and it's primarily intended for container workloads the [nvidia container toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/index.html) should be well understood. -Note the included driver is the [latest nvidia driver](https://github.com/negativo17/nvidia-driver/blob/master/nvidia-driver.spec) as bundled by [negativo17](https://negativo17.org/nvidia-driver/). This package was chosen over rpmfusion's due to it's granular packages which allow us to install just the minimal `nvidia-driver-cuda` packages. +The included driver is the [latest nvidia driver](https://github.com/negativo17/nvidia-driver/blob/master/nvidia-driver.spec) as bundled by [negativo17](https://negativo17.org/nvidia-driver/). This package was chosen over rpmfusion's due to it's granular packages which allow us to install just the minimal `nvidia-driver-cuda` packages. -#### Other NVIDIA Drivers +#### Other Drivers If you need an older (or different) driver, consider looking at the [container-toolkit-fcos driver](https://hub.docker.com/r/fifofonix/driver/). It provides pre-bundled container images with nvidia drivers for FCOS, allowing auto-build/loading of the nvidia driver IN podman, at boot, via a systemd service. @@ -341,83 +534,31 @@ If you do forget to specify the mountpoint, or you need to change the mountpoint # zfs set mountpoint=/var/tank tank ``` -### Sanoid/Syncoid - -sanoid/syncoid is a great tool for manual and automated snapshot/transfer of ZFS datasets. However, there is not a current stable RPM, rather they provide [instructions on installing via git](https://github.com/jimsalterjrs/sanoid/blob/master/INSTALL.md#centos). - -`ucore` has pre-install all the (lightweight) required dependencies (perl-Config-IniFiles perl-Data-Dumper perl-Capture-Tiny perl-Getopt-Long lzop mbuffer mhash pv), such that a user wishing to use sanoid/syncoid only need install the "sbin" files and create configuration/systemd units for it. +#### ZFS scrub timers -### SecureBoot +It's good practice to run a `zpool scrub` periodically on ZFS pools to check and repair the integrity of data. This can be easily configured with ucore by enabling the timer. There are two timers available: weekly and monthly. -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). - -Do so like this: ```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. - - -## How to Install - -### Prerequisites - -This image is not currently available for direct install. The user must follow the [CoreOS installation guide](https://docs.fedoraproject.org/en-US/fedora-coreos/bare-metal/). There are varying methods of installation for bare metal, cloud providers, and virtualization platforms. - -All CoreOS installation methods require the user to [produce an Ignition file](https://docs.fedoraproject.org/en-US/fedora-coreos/producing-ign/). This Ignition file should, at mimimum, set a password and SSH key for the default user (default username is `core`). - -### Install and Manually Rebase - -You can rebase any Fedora CoreOS x86_64 installation to uCore. Installing CoreOS itself can be done through [a number of provisioning methods](https://docs.fedoraproject.org/en-US/fedora-coreos/bare-metal/). - -To rebase an Fedora CoreOS machine to the latest uCore (stable): - -1. Execute the `rpm-ostree rebase` command (below) with desired `IMAGE` and `TAG`. -1. Reboot, as instructed. -1. After rebooting, you should [pin the working deployment](https://docs.fedoraproject.org/en-US/fedora-silverblue/faq/#_how_can_i_upgrade_my_system_to_the_next_major_version_for_instance_rawhide_or_an_upcoming_fedora_release_branch_while_keeping_my_current_deployment) which allows you to rollback if required. - -```bash -sudo rpm-ostree rebase ostree-unverified-registry:ghcr.io/ublue-os/IMAGE:TAG -``` - -#### Tag Matrix -| IMAGE | TAG | -|-|-| -| [`fedora-coreos`](#fedora-coreos) - *stable* | `stable-nvidia`, `stable-zfs`,`stable-nvidia-zfs` | -| [`fedora-coreos`](#fedora-coreos) - *testing* | `testing-nvidia`, `testing-zfs`, `testing-nvidia-zfs` | -| [`ucore-minimal`](#ucore-minimal) - *stable* | `stable`, `stable-nvidia`, `stable-zfs`,`stable-nvidia-zfs` | -| [`ucore-mimimal`](#ucore-minimal) - *testing* | `testing`, `testing-nvidia`, `testing-zfs`, `testing-nvidia-zfs` | -| [`ucore`](#ucore) - *stable* | `stable`, `stable-nvidia`, `stable-zfs`,`stable-nvidia-zfs` | -| [`ucore`](#ucore) - *testing* | `testing`, `testing-nvidia`, `testing-zfs`, `testing-nvidia-zfs` | -| [`ucore-hci`](#ucore-hci) - *stable* | `stable`, `stable-nvidia`, `stable-zfs`,`stable-nvidia-zfs` | -| [`ucore-hci`](#ucore-hci) - *testing* | `testing`, `testing-nvidia`, `testing-zfs`, `testing-nvidia-zfs` | - - -#### Verified Image Updates +# Substitute with the name of the zpool +systemctl enable --now zfs-scrub-weekly@.timer -This image now includes container policies to support image verification for improved trust of upgrades. Once running one of the `ucore*` images (not included in `fedora-coreos`), the following command will rebase to the verified image reference: - -```bash -sudo rpm-ostree rebase ostree-image-signed:docker://ghcr.io/ublue-os/IMAGE:TAG +# Or to run it monthly: +systemctl enable --now zfs-scrub-monthly@.timer ``` +This can be enabled for multiple storage pools by enabling and starting a timer for each. -### Install with Auto-Rebase +#### Sanoid/Syncoid -Your path to a running uCore can be shortened by using [examples/ucore-autorebase.butane](examples/ucore-autorebase.butane) as the starting point for your CoreOS ignition file. +sanoid/syncoid is a great tool for manual and automated snapshot/transfer of ZFS datasets. However, there is not a current stable RPM, rather they provide [instructions on installing via git](https://github.com/jimsalterjrs/sanoid/blob/master/INSTALL.md#centos). -1. As usual, you'll need to [follow the docs to setup a password](https://coreos.github.io/butane/examples/#using-password-authentication). Substitute your password hash for `YOUR_GOOD_PASSWORD_HASH_HERE` in the `ucore-autorebase.butane` file, and add your ssh pub key while you are at it. -1. Generate an ignition file from your new `ucore-autorebase.butane` [using the butane utility](https://coreos.github.io/butane/getting-started/). -1. Now install CoreOS for [hypervisor, cloud provider or bare-metal](https://docs.fedoraproject.org/en-US/fedora-coreos/bare-metal/). Your ignition file should work for any platform, auto-rebasing to the `ucore:stable` (or other `IMAGE:TAG` combo), rebooting and leaving your install ready to use. +`ucore` has pre-install all the (lightweight) required dependencies (perl-Config-IniFiles perl-Data-Dumper perl-Capture-Tiny perl-Getopt-Long lzop mbuffer mhash pv), such that a user wishing to use sanoid/syncoid only need install the "sbin" files and create configuration/systemd units for it. -## Verification +## DIY -These images are signed with sigstore's [cosign](https://docs.sigstore.dev/cosign/overview/). You can verify the signature by downloading the `cosign.pub` key from this repo and running the following command: +Is all this too easy, leaving you with the desire to create a custom uCore image? -```bash -cosign verify --key cosign.pub ghcr.io/ublue-os/ucore -``` +Then [create an image `FROM ucore`](https://github.com/ublue-os/image-template) using our [image template](https://github.com/ublue-os/image-template)! ## Metrics diff --git a/cosign.pub b/cosign.pub index f9482c4..bd5b192 100644 --- a/cosign.pub +++ b/cosign.pub @@ -1,4 +1,4 @@ -----BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7lh7fJMV4dBT2jT1XafixUJa7OVA -cT+QFVD8IfIJIS/KBAc8hx1aslzkH3tfeM0cwyCLB7kOStZ4sh6RyFQD9w== +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHLRpBfPRYiMl9wb7s6fx47PzzNWu +3zyJgXhWEvxoOgwv9CpwjbvUwR9qHxNMWkJhuGE6cjDA2hpy1I6NbA+24Q== -----END PUBLIC KEY----- diff --git a/examples/ucore-autorebase.butane b/examples/ucore-autorebase.butane index 6abed95..44f33c2 100644 --- a/examples/ucore-autorebase.butane +++ b/examples/ucore-autorebase.butane @@ -10,33 +10,41 @@ storage: directories: - path: /etc/ucore-autorebase mode: 0754 - files: - - path: /etc/ucore-autorebase/ucore-autorebase.sh - contents: - inline: | - #!/usr/bin/bash - echo "Rebasing to uCore OCI in 5 seconds" - sleep 5 - rpm-ostree rebase ostree-unverified-registry:ghcr.io/ublue-os/ucore:stable \ - && touch /etc/ucore-autorebase/.complete \ - && systemctl disable ucore-autorebase.service \ - && systemctl reboot - mode: 0754 systemd: units: - - name: ucore-autorebase.service + - name: ucore-unsigned-autorebase.service + enabled: true + contents: | + [Unit] + Description=uCore autorebase to unsigned OCI and reboot + ConditionPathExists=!/etc/ucore-autorebase/unverified + ConditionPathExists=!/etc/ucore-autorebase/signed + After=network-online.target + Wants=network-online.target + [Service] + Type=oneshot + StandardOutput=journal+console + ExecStart=/usr/bin/rpm-ostree rebase --bypass-driver ostree-unverified-registry:ghcr.io/ublue-os/ucore:stable + ExecStart=/usr/bin/touch /etc/ucore-autorebase/unverified + ExecStart=/usr/bin/systemctl disable ucore-unsigned-autorebase.service + ExecStart=/usr/bin/systemctl reboot + [Install] + WantedBy=multi-user.target + - name: ucore-signed-autorebase.service enabled: true contents: | [Unit] - Description=uCore autorebase to OCI and reboot - ConditionPathExists=!/etc/ucore-autorebase/.complete - ConditionFileIsExecutable=/etc/ucore-autorebase/ucore-autorebase.sh + Description=uCore autorebase to signed OCI and reboot + ConditionPathExists=/etc/ucore-autorebase/unverified + ConditionPathExists=!/etc/ucore-autorebase/verified After=network-online.target Wants=network-online.target [Service] Type=oneshot StandardOutput=journal+console - RemainAfterExit=yes - ExecStart=/etc/ucore-autorebase/ucore-autorebase.sh + ExecStart=/usr/bin/rpm-ostree rebase --bypass-driver ostree-image-signed:docker://ghcr.io/ublue-os/ucore:stable + ExecStart=/usr/bin/touch /etc/ucore-autorebase/signed + ExecStart=/usr/bin/systemctl disable ucore-signed-autorebase.service + ExecStart=/usr/bin/systemctl reboot [Install] - WantedBy=multi-user.target \ No newline at end of file + WantedBy=multi-user.target diff --git a/fedora-coreos/Containerfile b/fedora-coreos/Containerfile index 36e9fa1..c45ded7 100644 --- a/fedora-coreos/Containerfile +++ b/fedora-coreos/Containerfile @@ -1,4 +1,22 @@ ARG COREOS_VERSION="${COREOS_VERSION:-stable}" +ARG FEDORA_VERSION="${FEDORA_VERSION:-40}" +ARG IMAGE_REGISTRY="${IMAGE_REGISTRY:-ghcr.io/ublue-os}" +ARG KERNEL_FLAVOR="${KERNEL_FLAVOR:-coreos-stable}" + +# 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}" +ARG CONFIG="${IMAGE_REGISTRY}/config:latest" +ARG KERNEL="${IMAGE_REGISTRY}/${KERNEL_FLAVOR}-kernel:${FEDORA_VERSION}" +FROM ${AKMODS_COMMON} AS akmods-common +FROM ${AKMODS_NVIDIA} AS akmods-nvidia +FROM ${AKMODS_ZFS} AS akmods-zfs +FROM ${CONFIG} AS config +FROM ${KERNEL} AS kernel + +FROM scratch AS ctx +COPY / / FROM quay.io/fedora/fedora-coreos:${COREOS_VERSION} @@ -7,20 +25,21 @@ ARG COREOS_VERSION="${COREOS_VERSION:-stable}" ARG NVIDIA_TAG="${NVIDIA_TAG}" # build with --build-arg ZFS_TAG="-zfs" to install zfs ARG ZFS_TAG="${ZFS_TAG}" -ARG KMOD_SRC="${KMOD_SRC:-ghcr.io/ublue-os/ucore-kmods:${COREOS_VERSION}}" - -COPY --from=${KMOD_SRC} /rpms/kmods/*.rpm /tmp/rpms/ -COPY --from=${KMOD_SRC} /rpms/kmods/nvidia/*.rpm /tmp/rpms/nvidia/ -COPY --from=${KMOD_SRC} /rpms/kmods/zfs/*.rpm /tmp/rpms/zfs/ -COPY *.sh /tmp/ -RUN mkdir -p /var/lib/alternatives \ - && /tmp/install.sh \ - && /tmp/post-install.sh \ +RUN --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=config,src=/rpms,dst=/tmp/rpms/config \ + --mount=type=bind,from=kernel,src=/tmp/rpms,dst=/tmp/rpms/kernel \ + mkdir -p /var/lib/alternatives \ + && /ctx/install.sh \ + && /ctx/post-install.sh \ && mv /var/lib/alternatives /staged-alternatives \ - && rm -fr /tmp/* /var/* \ + && /ctx/cleanup.sh \ && ostree container commit \ && mkdir -p /var/lib && mv /staged-alternatives /var/lib/alternatives \ - && mkdir -p /tmp /var/tmp \ - && chmod -R 1777 /tmp /var/tmp \ No newline at end of file + && mkdir -p /var/tmp \ + && chmod -R 1777 /var/tmp \ No newline at end of file diff --git a/fedora-coreos/cleanup.sh b/fedora-coreos/cleanup.sh new file mode 100755 index 0000000..e9549a3 --- /dev/null +++ b/fedora-coreos/cleanup.sh @@ -0,0 +1,8 @@ +#!/usr/bin/bash + +set -eoux pipefail +shopt -s extglob + +rm -rf /tmp/* || true +rm -rf /var/!(cache) +rm -rf /var/cache/!(rpm-ostree) \ No newline at end of file diff --git a/fedora-coreos/install.sh b/fedora-coreos/install.sh index f0559f4..78b8dbc 100755 --- a/fedora-coreos/install.sh +++ b/fedora-coreos/install.sh @@ -2,8 +2,12 @@ set -ouex pipefail +ARCH="$(rpm -E %{_arch})" RELEASE="$(rpm -E %fedora)" -KERNEL="$(rpm -q kernel --queryformat '%{VERSION}-%{RELEASE}.%{ARCH}')" +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//') +popd +QUALIFIED_KERNEL="$(rpm -qa | grep -P 'kernel-(\d+\.\d+\.\d+)' | sed -E 's/kernel-//')" #### PREPARE # enable testing repos if not enabled on testing stream @@ -23,13 +27,33 @@ 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/ -rpm-ostree install /tmp/rpms/ublue-os-ucore-addons-*.rpm +rpm-ostree install \ + /tmp/rpms/akmods-common/ublue-os-ucore-addons*.rpm \ + /tmp/rpms/config/ublue-os-signing*.rpm + +# Handle Kernel Skew with override replace +rpm-ostree cliwrap install-to-root / +if [[ "${KERNEL_VERSION}" == "${QUALIFIED_KERNEL}" ]]; then + echo "Installing signed kernel from kernel-cache." + cd /tmp + rpm2cpio /tmp/rpms/kernel/kernel-core-*.rpm | cpio -idmv + cp ./lib/modules/*/vmlinuz /usr/lib/modules/*/vmlinuz + cd / +else + echo "Install kernel version ${KERNEL_VERSION} from kernel-cache." + rpm-ostree override replace \ + --experimental \ + --install=zstd \ + /tmp/rpms/kernel/kernel-[0-9]*.rpm \ + /tmp/rpms/kernel/kernel-core-*.rpm \ + /tmp/rpms/kernel/kernel-modules-*.rpm +fi ## CONDITIONAL: install ZFS if [[ "-zfs" == "${ZFS_TAG}" ]]; then - rpm-ostree install pv /tmp/rpms/zfs/*.rpm + rpm-ostree install pv /tmp/rpms/akmods-zfs/kmods/zfs/*.rpm /tmp/rpms/akmods-zfs/kmods/zfs/other/zfs-dracut-*.rpm # for some reason depmod ran automatically with zfs 2.1 but not with 2.2 - depmod -A ${KERNEL} + depmod -a -v ${KERNEL_VERSION} fi ## CONDITIONAL: install NVIDIA @@ -37,11 +61,11 @@ if [[ "-nvidia" == "${NVIDIA_TAG}" ]]; then # repo for nvidia rpms curl -L https://negativo17.org/repos/fedora-nvidia.repo -o /etc/yum.repos.d/fedora-nvidia.repo - rpm-ostree install /tmp/rpms/nvidia/ublue-os-ucore-nvidia-*.rpm + rpm-ostree install /tmp/rpms/akmods-nvidia/ucore/ublue-os-ucore-nvidia*.rpm sed -i '0,/enabled=0/{s/enabled=0/enabled=1/}' /etc/yum.repos.d/nvidia-container-toolkit.repo rpm-ostree install \ - /tmp/rpms/nvidia/kmod-nvidia-*.rpm \ + /tmp/rpms/akmods-nvidia/kmods/kmod-nvidia*.rpm \ nvidia-driver-cuda \ nvidia-container-toolkit fi diff --git a/ucore/Containerfile b/ucore/Containerfile index e781370..8d50c8a 100644 --- a/ucore/Containerfile +++ b/ucore/Containerfile @@ -1,5 +1,22 @@ ARG COREOS_VERSION="${COREOS_VERSION:-stable}" - +ARG FEDORA_VERSION="${FEDORA_VERSION:-40}" +ARG IMAGE_REGISTRY="${IMAGE_REGISTRY:-ghcr.io/ublue-os}" +ARG KERNEL_FLAVOR="${KERNEL_FLAVOR:-coreos-stable}" + +# 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}" +ARG CONFIG="${IMAGE_REGISTRY}/config:latest" +ARG KERNEL="${IMAGE_REGISTRY}/${KERNEL_FLAVOR}-kernel:${FEDORA_VERSION}" +FROM ${AKMODS_COMMON} AS akmods-common +FROM ${AKMODS_NVIDIA} AS akmods-nvidia +FROM ${AKMODS_ZFS} AS akmods-zfs +FROM ${CONFIG} AS config +FROM ${KERNEL} AS kernel + +FROM scratch AS ctx +COPY / / # ucore-minimal image section FROM quay.io/fedora/fedora-coreos:${COREOS_VERSION} AS ucore-minimal @@ -9,49 +26,50 @@ ARG COREOS_VERSION="${COREOS_VERSION:-stable}" ARG NVIDIA_TAG="${NVIDIA_TAG}" # build with --build-arg ZFS_TAG="-zfs" to install zfs ARG ZFS_TAG="${ZFS_TAG}" -ARG KMOD_SRC="${KMOD_SRC:-ghcr.io/ublue-os/ucore-kmods:${COREOS_VERSION}}" - -COPY --from=${KMOD_SRC} /rpms/kmods/*.rpm /tmp/rpms/ -COPY --from=${KMOD_SRC} /rpms/kmods/nvidia/*.rpm /tmp/rpms/nvidia/ -COPY --from=${KMOD_SRC} /rpms/kmods/zfs/*.rpm /tmp/rpms/zfs/ - -COPY *.sh /tmp/ -COPY packages.json /tmp/packages.json -COPY usr /usr - -RUN mkdir -p /var/lib/alternatives \ - && /tmp/install-ucore-minimal.sh \ - && /tmp/post-install-ucore-minimal.sh \ +# 0.12.1 matches docker/moby 24.0.5 which FCOS ships as of 40.20240421 +ARG DOCKER_BUILDX_VERSION=0.12.1 +# 2.24.7 matches docker/moby 24.0.5 which FCOS ships as of 40.20240421 +ARG DOCKER_COMPOSE_VERSION=v2.24.7 + +COPY system_files / +COPY --from=docker.io/docker/buildx-bin:${DOCKER_BUILDX_VERSION} /buildx /usr/libexec/docker/cli-plugins/docker-buildx +COPY --from=docker.io/docker/compose-bin:${DOCKER_COMPOSE_VERSION} /docker-compose /usr/libexec/docker/cli-plugins/docker-compose + +RUN --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=config,src=/rpms,dst=/tmp/rpms/config \ + --mount=type=bind,from=kernel,src=/tmp/rpms,dst=/tmp/rpms/kernel \ + mkdir -p /var/lib/alternatives \ + && /ctx/install-ucore-minimal.sh \ + && /ctx/post-install-ucore-minimal.sh \ && mv /var/lib/alternatives /staged-alternatives \ - && rm -fr /tmp/* /var/* \ + && /ctx/cleanup.sh \ && ostree container commit \ && mkdir -p /var/lib && mv /staged-alternatives /var/lib/alternatives \ - && mkdir -p /tmp /var/tmp \ - && chmod -R 1777 /tmp /var/tmp - -COPY --from=docker.io/docker/compose-bin:latest /docker-compose /usr/bin/docker-compose - + && mkdir -p /var/tmp \ + && chmod -R 1777 /var/tmp # ucore image section FROM ucore-minimal AS ucore ARG COREOS_VERSION="${COREOS_VERSION:-stable}" +ARG NVIDIA_TAG="${NVIDIA_TAG}" ARG ZFS_TAG="${ZFS_TAG}" -COPY *.sh /tmp/ -COPY packages.json /tmp/packages.json - -COPY usr /usr - -RUN mkdir -p /var/lib/alternatives \ - && /tmp/install-ucore.sh \ +RUN --mount=type=cache,dst=/var/cache/rpm-ostree \ + --mount=type=bind,from=ctx,src=/,dst=/ctx \ + mkdir -p /var/lib/alternatives \ + && /ctx/install-ucore.sh \ && mv /var/lib/alternatives /staged-alternatives \ - && rm -fr /tmp/* /var/* \ + && /ctx/cleanup.sh \ && ostree container commit \ && mkdir -p /var/lib && mv /staged-alternatives /var/lib/alternatives \ - && mkdir -p /tmp /var/tmp \ - && chmod -R 1777 /tmp /var/tmp + && mkdir -p /var/tmp \ + && chmod -R 1777 /var/tmp # ucore-hci image section @@ -61,14 +79,13 @@ ARG COREOS_VERSION="${COREOS_VERSION:-stable}" ARG NVIDIA_TAG="${NVIDIA_TAG}" ARG ZFS_TAG="${ZFS_TAG}" -COPY *.sh /tmp/ -COPY packages.json /tmp/packages.json - -RUN mkdir -p /var/lib/alternatives \ - && /tmp/install-ucore-hci.sh \ +RUN --mount=type=cache,dst=/var/cache/rpm-ostree \ + --mount=type=bind,from=ctx,src=/,dst=/ctx \ + mkdir -p /var/lib/alternatives \ + && /ctx/install-ucore-hci.sh \ && mv /var/lib/alternatives /staged-alternatives \ - && rm -fr /tmp/* /var/* \ + && /ctx/cleanup.sh \ && ostree container commit \ && mkdir -p /var/lib && mv /staged-alternatives /var/lib/alternatives \ - && mkdir -p /tmp /var/tmp \ - && chmod -R 1777 /tmp /var/tmp \ No newline at end of file + && mkdir -p /var/tmp \ + && chmod -R 1777 /var/tmp \ No newline at end of file diff --git a/ucore/cleanup.sh b/ucore/cleanup.sh new file mode 100755 index 0000000..e9549a3 --- /dev/null +++ b/ucore/cleanup.sh @@ -0,0 +1,8 @@ +#!/usr/bin/bash + +set -eoux pipefail +shopt -s extglob + +rm -rf /tmp/* || true +rm -rf /var/!(cache) +rm -rf /var/cache/!(rpm-ostree) \ No newline at end of file diff --git a/ucore/github-release-install.sh b/ucore/github-release-install.sh index aa9243e..3d72665 100755 --- a/ucore/github-release-install.sh +++ b/ucore/github-release-install.sh @@ -47,14 +47,11 @@ API="https://api.github.com/repos/${ORG_PROJ}/releases/${RELTAG}" # retry up to 5 times with 5 second delays for any error included HTTP 404 etc curl --fail --retry 5 --retry-delay 5 --retry-all-errors -sL ${API} -o ${API_JSON} -RPM_URLS=$(cat ${API_JSON} \ +RPM_URLS=($(cat ${API_JSON} \ | jq \ -r \ --arg arch_filter "${ARCH_FILTER}" \ - '.assets | sort_by(.created_at) | reverse | .[] | select(.name|test($arch_filter)) | select (.name|test("rpm$")) | .browser_download_url') -for URL in ${RPM_URLS}; do - # WARNING: in case of multiple matches, this only installs the first matched release - echo "execute: rpm-ostree install \"${URL}\"" - rpm-ostree install "${URL}" - break -done + '.assets | sort_by(.created_at) | reverse | .[] | select(.name|test($arch_filter)) | select(.name|test("rpm$")) | .browser_download_url')) +# WARNING: in case of multiple matches, this only installs the first matched release +echo "execute: rpm-ostree install \"${RPM_URLS[0]}\"" +rpm-ostree install "${RPM_URLS[0]}" diff --git a/ucore/install-ucore-hci.sh b/ucore/install-ucore-hci.sh index 9559a9d..0ff3280 100755 --- a/ucore/install-ucore-hci.sh +++ b/ucore/install-ucore-hci.sh @@ -4,7 +4,7 @@ set -ouex pipefail # install packages.json stuffs export IMAGE_NAME=ucore-hci -/tmp/packages.sh +/ctx/packages.sh # tweak os-release sed -i '/^PRETTY_NAME/s/(uCore.*$/(uCore HCI)"/' /usr/lib/os-release diff --git a/ucore/install-ucore-minimal.sh b/ucore/install-ucore-minimal.sh index d2f6b87..adb686a 100755 --- a/ucore/install-ucore-minimal.sh +++ b/ucore/install-ucore-minimal.sh @@ -2,8 +2,12 @@ set -ouex pipefail -KERNEL="$(rpm -q kernel --queryformat '%{VERSION}-%{RELEASE}.%{ARCH}')" +ARCH="$(rpm -E %{_arch})" RELEASE="$(rpm -E %fedora)" +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//') +popd +QUALIFIED_KERNEL="$(rpm -qa | grep -P 'kernel-(\d+\.\d+\.\d+)' | sed -E 's/kernel-//')" #### PREPARE # enable testing repos if not enabled on testing stream @@ -26,14 +30,33 @@ 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/ -rpm-ostree install /tmp/rpms/ublue-os-ucore-addons-*.rpm +rpm-ostree install \ + /tmp/rpms/akmods-common/ublue-os-ucore-addons*.rpm \ + /tmp/rpms/config/ublue-os-signing*.rpm + +# Handle Kernel Skew with override replace +rpm-ostree cliwrap install-to-root / +if [[ "${KERNEL_VERSION}" == "${QUALIFIED_KERNEL}" ]]; then + echo "Installing signed kernel from kernel-cache." + cd /tmp + rpm2cpio /tmp/rpms/kernel/kernel-core-*.rpm | cpio -idmv + cp ./lib/modules/*/vmlinuz /usr/lib/modules/*/vmlinuz + cd / +else + echo "Install kernel version ${KERNEL_VERSION} from kernel-cache." + rpm-ostree override replace \ + --experimental \ + --install=zstd \ + /tmp/rpms/kernel/kernel-[0-9]*.rpm \ + /tmp/rpms/kernel/kernel-core-*.rpm \ + /tmp/rpms/kernel/kernel-modules-*.rpm +fi ## CONDITIONAL: install ZFS (and sanoid deps) if [[ "-zfs" == "${ZFS_TAG}" ]]; then - rpm-ostree install /tmp/rpms/zfs/*.rpm \ - pv + rpm-ostree install pv /tmp/rpms/akmods-zfs/kmods/zfs/*.rpm /tmp/rpms/akmods-zfs/kmods/zfs/other/zfs-dracut-*.rpm # for some reason depmod ran automatically with zfs 2.1 but not with 2.2 - depmod -A ${KERNEL} + depmod -a -v ${KERNEL_VERSION} curl -L https://github.com/45Drives/cockpit-zfs-manager/archive/refs/tags/v1.3.1.tar.gz | tar xz -C /tmp mv /tmp/cockpit-zfs-manager-1.3.1/zfs /usr/share/cockpit @@ -44,11 +67,11 @@ if [[ "-nvidia" == "${NVIDIA_TAG}" ]]; then # repo for nvidia rpms curl -L https://negativo17.org/repos/fedora-nvidia.repo -o /etc/yum.repos.d/fedora-nvidia.repo - rpm-ostree install /tmp/rpms/nvidia/ublue-os-ucore-nvidia-*.rpm + rpm-ostree install /tmp/rpms/akmods-nvidia/ucore/ublue-os-ucore-nvidia*.rpm sed -i '0,/enabled=0/{s/enabled=0/enabled=1/}' /etc/yum.repos.d/nvidia-container-toolkit.repo rpm-ostree install \ - /tmp/rpms/nvidia/kmod-nvidia-*.rpm \ + /tmp/rpms/akmods-nvidia/kmods/kmod-nvidia*.rpm \ nvidia-driver-cuda \ nvidia-container-toolkit fi @@ -60,7 +83,7 @@ curl -L https://pkgs.tailscale.com/stable/fedora/tailscale.repo -o /etc/yum.repo # install packages.json stuffs export IMAGE_NAME=ucore-minimal -/tmp/packages.sh +/ctx/packages.sh # tweak os-release sed -i '/^PRETTY_NAME/s/"$/ (uCore minimal)"/' /usr/lib/os-release diff --git a/ucore/install-ucore.sh b/ucore/install-ucore.sh index ba6834e..c210bb6 100755 --- a/ucore/install-ucore.sh +++ b/ucore/install-ucore.sh @@ -2,6 +2,8 @@ set -ouex pipefail +RELEASE="$(rpm -E %fedora)" + ## CONDITIONAL: install sanoid if ZFS if [[ "-zfs" == "${ZFS_TAG}" ]]; then rpm-ostree install sanoid @@ -9,10 +11,10 @@ fi # install packages.json stuffs export IMAGE_NAME=ucore -/tmp/packages.sh +/ctx/packages.sh # install packages direct from github -/tmp/github-release-install.sh trapexit/mergerfs fc.x86_64 +/ctx/github-release-install.sh trapexit/mergerfs "fc${RELEASE}.x86_64" # tweak os-release sed -i '/^PRETTY_NAME/s/(uCore.*$/(uCore)"/' /usr/lib/os-release diff --git a/ucore/packages.json b/ucore/packages.json index 6e85ed6..7ba7671 100644 --- a/ucore/packages.json +++ b/ucore/packages.json @@ -9,20 +9,20 @@ "cockpit-selinux", "cockpit-system", "firewalld", + "fwupd-efi", + "intel-compute-runtime", "open-vm-tools", "podman", "podman-compose", "qemu-guest-agent", "tailscale", "tmux", - "wget", "wireguard-tools" ], "ucore": [ "NetworkManager-wifi", "atheros-firmware", "brcmfmac-firmware", - "cockpit-pcp", "cockpit-storaged", "distrobox", "duperemove", @@ -35,6 +35,7 @@ "nxpwireless-firmware", "pciutils", "pcp-zeroconf", + "rclone", "realtek-firmware", "samba", "samba-usershares", diff --git a/ucore/packages.sh b/ucore/packages.sh index 2c9ecc3..70a847d 100755 --- a/ucore/packages.sh +++ b/ucore/packages.sh @@ -7,12 +7,12 @@ RELEASE="$(rpm -E %fedora)" # build list of all packages requested for inclusion INCLUDED_PACKAGES=($(jq -r "[(.all.include | (.all, select(.\"$IMAGE_NAME\" != null).\"$IMAGE_NAME\")[]), \ (select(.\"$COREOS_VERSION\" != null).\"$COREOS_VERSION\".include | (.all, select(.\"$IMAGE_NAME\" != null).\"$IMAGE_NAME\")[])] \ - | sort | unique[]" /tmp/packages.json)) + | sort | unique[]" /ctx/packages.json)) # build list of all packages requested for exclusion EXCLUDED_PACKAGES=($(jq -r "[(.all.exclude | (.all, select(.\"$IMAGE_NAME\" != null).\"$IMAGE_NAME\")[]), \ (select(.\"$COREOS_VERSION\" != null).\"$COREOS_VERSION\".exclude | (.all, select(.\"$IMAGE_NAME\" != null).\"$IMAGE_NAME\")[])] \ - | sort | unique[]" /tmp/packages.json)) + | sort | unique[]" /ctx/packages.json)) # ensure exclusion list only contains packages already present on image @@ -45,7 +45,7 @@ fi # (this can happen if an included package pulls in a dependency) EXCLUDED_PACKAGES=($(jq -r "[(.all.exclude | (.all, select(.\"$IMAGE_NAME\" != null).\"$IMAGE_NAME\")[]), \ (select(.\"$COREOS_VERSION\" != null).\"$COREOS_VERSION\".exclude | (.all, select(.\"$IMAGE_NAME\" != null).\"$IMAGE_NAME\")[])] \ - | sort | unique[]" /tmp/packages.json)) + | sort | unique[]" /ctx/packages.json)) if [[ "${#EXCLUDED_PACKAGES[@]}" -gt 0 ]]; then EXCLUDED_PACKAGES=($(rpm -qa --queryformat='%{NAME} ' ${EXCLUDED_PACKAGES[@]})) diff --git a/ucore/post-install-ucore-minimal.sh b/ucore/post-install-ucore-minimal.sh index 8813327..7d4aa89 100755 --- a/ucore/post-install-ucore-minimal.sh +++ b/ucore/post-install-ucore-minimal.sh @@ -18,9 +18,16 @@ fi ## ALWAYS: regular post-install +ln -s /usr/libexec/docker/cli-plugins/docker-compose /usr/bin/docker-compose + systemctl disable docker.socket systemctl disable zincati.service +systemctl enable gssproxy-workaround.service +systemctl enable libvirt-workaround.service +systemctl enable swtpm-workaround.service + + systemctl enable ucore-paths-provision.service systemctl enable rpm-ostreed-automatic.timer diff --git a/ucore/usr/etc/default/duperemove b/ucore/system_files/etc/default/duperemove similarity index 100% rename from ucore/usr/etc/default/duperemove rename to ucore/system_files/etc/default/duperemove diff --git a/ucore/usr/etc/sysctl.conf b/ucore/system_files/etc/sysctl.conf similarity index 100% rename from ucore/usr/etc/sysctl.conf rename to ucore/system_files/etc/sysctl.conf diff --git a/ucore/usr/etc/systemd/ucore-paths-provision.conf b/ucore/system_files/etc/systemd/ucore-paths-provision.conf similarity index 100% rename from ucore/usr/etc/systemd/ucore-paths-provision.conf rename to ucore/system_files/etc/systemd/ucore-paths-provision.conf diff --git a/ucore/usr/etc/systemd/zram-generator.conf b/ucore/system_files/etc/systemd/zram-generator.conf similarity index 100% rename from ucore/usr/etc/systemd/zram-generator.conf rename to ucore/system_files/etc/systemd/zram-generator.conf diff --git a/ucore/usr/etc/udev/rules.d/50-usb-realtek-net.rules b/ucore/system_files/etc/udev/rules.d/50-usb-realtek-net.rules similarity index 100% rename from ucore/usr/etc/udev/rules.d/50-usb-realtek-net.rules rename to ucore/system_files/etc/udev/rules.d/50-usb-realtek-net.rules diff --git a/ucore/usr/lib/systemd/system/cockpit.service b/ucore/system_files/usr/lib/systemd/system/cockpit.service similarity index 100% rename from ucore/usr/lib/systemd/system/cockpit.service rename to ucore/system_files/usr/lib/systemd/system/cockpit.service diff --git a/ucore/usr/lib/systemd/system/duperemove-weekly@.timer b/ucore/system_files/usr/lib/systemd/system/duperemove-weekly@.timer similarity index 100% rename from ucore/usr/lib/systemd/system/duperemove-weekly@.timer rename to ucore/system_files/usr/lib/systemd/system/duperemove-weekly@.timer diff --git a/ucore/usr/lib/systemd/system/duperemove@.service b/ucore/system_files/usr/lib/systemd/system/duperemove@.service similarity index 100% rename from ucore/usr/lib/systemd/system/duperemove@.service rename to ucore/system_files/usr/lib/systemd/system/duperemove@.service diff --git a/ucore/system_files/usr/lib/systemd/system/gssproxy-workaround.service b/ucore/system_files/usr/lib/systemd/system/gssproxy-workaround.service new file mode 100644 index 0000000..f7cdccb --- /dev/null +++ b/ucore/system_files/usr/lib/systemd/system/gssproxy-workaround.service @@ -0,0 +1,12 @@ +[Unit] +Description=Workaround to relabel gssproxy files and directories +ConditionPathIsDirectory=/var/lib/gssproxy/ +After=local-fs.target + +[Service] +Type=oneshot +ExecStart=-/usr/sbin/restorecon -Rv /var/lib/gssproxy/ +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/ucore/system_files/usr/lib/systemd/system/libvirt-workaround.service b/ucore/system_files/usr/lib/systemd/system/libvirt-workaround.service new file mode 100644 index 0000000..440e056 --- /dev/null +++ b/ucore/system_files/usr/lib/systemd/system/libvirt-workaround.service @@ -0,0 +1,13 @@ +[Unit] +Description=Workaround to relabel libvirt files and directories +ConditionPathIsDirectory=/var/lib/libvirt/ +After=local-fs.target + +[Service] +Type=oneshot +ExecStart=-/usr/sbin/restorecon -Rv /var/lib/libvirt/ +ExecStart=-/usr/sbin/restorecon -Rv /var/log/libvirt/ +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/ucore/system_files/usr/lib/systemd/system/swtpm-workaround.service b/ucore/system_files/usr/lib/systemd/system/swtpm-workaround.service new file mode 100644 index 0000000..b4cd40d --- /dev/null +++ b/ucore/system_files/usr/lib/systemd/system/swtpm-workaround.service @@ -0,0 +1,20 @@ +[Unit] +Description=Workaround swtpm not having the correct label +ConditionFileIsExecutable=/usr/bin/swtpm +After=local-fs.target + +[Service] +Type=oneshot +# Copy if it doesn't exist +ExecStartPre=/usr/bin/bash -c "[ -x /usr/local/bin/overrides/swtpm ] || /usr/bin/cp /usr/bin/swtpm /usr/local/bin/overrides/swtpm" +# This is faster than using .mount unit. Also allows for the previous line/cleanup +ExecStartPre=/usr/bin/mount --bind /usr/local/bin/overrides/swtpm /usr/bin/swtpm +# Fix SELinux label +ExecStart=/usr/sbin/restorecon /usr/bin/swtpm +# Clean-up after ourselves +ExecStop=/usr/bin/umount /usr/bin/swtpm +ExecStop=/usr/bin/rm /usr/local/bin/overrides/swtpm +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/ucore/usr/lib/systemd/system/ucore-paths-provision.service b/ucore/system_files/usr/lib/systemd/system/ucore-paths-provision.service similarity index 100% rename from ucore/usr/lib/systemd/system/ucore-paths-provision.service rename to ucore/system_files/usr/lib/systemd/system/ucore-paths-provision.service diff --git a/ucore/usr/lib/systemd/user/distrobox-upgrade-automatic.service b/ucore/system_files/usr/lib/systemd/user/distrobox-upgrade-automatic.service similarity index 100% rename from ucore/usr/lib/systemd/user/distrobox-upgrade-automatic.service rename to ucore/system_files/usr/lib/systemd/user/distrobox-upgrade-automatic.service diff --git a/ucore/usr/lib/systemd/user/distrobox-upgrade-automatic.timer b/ucore/system_files/usr/lib/systemd/user/distrobox-upgrade-automatic.timer similarity index 100% rename from ucore/usr/lib/systemd/user/distrobox-upgrade-automatic.timer rename to ucore/system_files/usr/lib/systemd/user/distrobox-upgrade-automatic.timer diff --git a/ucore/system_files/usr/lib/tmpfiles.d/gssproxy-workaround.conf b/ucore/system_files/usr/lib/tmpfiles.d/gssproxy-workaround.conf new file mode 100644 index 0000000..4fdd48b --- /dev/null +++ b/ucore/system_files/usr/lib/tmpfiles.d/gssproxy-workaround.conf @@ -0,0 +1,3 @@ +d /var/lib/gssproxy 0755 root root - +d /var/lib/gssproxy/clients 0755 root root - +d /var/lib/gssproxy/rcache 0755 root root - \ No newline at end of file diff --git a/ucore/system_files/usr/lib/tmpfiles.d/libvirt-workaround.conf b/ucore/system_files/usr/lib/tmpfiles.d/libvirt-workaround.conf new file mode 100644 index 0000000..4af298b --- /dev/null +++ b/ucore/system_files/usr/lib/tmpfiles.d/libvirt-workaround.conf @@ -0,0 +1 @@ +d /var/log/libvirt 0750 - - - - diff --git a/ucore/usr/lib/tmpfiles.d/pcp-ucore.conf b/ucore/system_files/usr/lib/tmpfiles.d/pcp-ucore.conf similarity index 100% rename from ucore/usr/lib/tmpfiles.d/pcp-ucore.conf rename to ucore/system_files/usr/lib/tmpfiles.d/pcp-ucore.conf diff --git a/ucore/system_files/usr/lib/tmpfiles.d/swtpm-workaround.conf b/ucore/system_files/usr/lib/tmpfiles.d/swtpm-workaround.conf new file mode 100644 index 0000000..62147f4 --- /dev/null +++ b/ucore/system_files/usr/lib/tmpfiles.d/swtpm-workaround.conf @@ -0,0 +1,2 @@ +C /usr/local/bin/overrides/swtpm - - - - /usr/bin/swtpm +d /var/lib/swtpm-localca 0750 tss tss - - diff --git a/ucore/usr/sbin/ucore-paths-provision.sh b/ucore/system_files/usr/sbin/ucore-paths-provision.sh similarity index 100% rename from ucore/usr/sbin/ucore-paths-provision.sh rename to ucore/system_files/usr/sbin/ucore-paths-provision.sh diff --git a/ucore/usr/etc/containers/policy.json b/ucore/usr/etc/containers/policy.json deleted file mode 100644 index 0f0e363..0000000 --- a/ucore/usr/etc/containers/policy.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "default": [ - { - "type": "reject" - } - ], - "transports": { - "docker": { - "registry.access.redhat.com": [ - { - "type": "signedBy", - "keyType": "GPGKeys", - "keyPath": "/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release" - } - ], - "registry.redhat.io": [ - { - "type": "signedBy", - "keyType": "GPGKeys", - "keyPath": "/etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release" - } - ], - "ghcr.io/ublue-os": [ - { - "type": "sigstoreSigned", - "keyPath": "/usr/etc/pki/containers/ublue-os.pub", - "signedIdentity": { - "type": "matchRepository" - } - } - ], - "": [ - { - "type": "insecureAcceptAnything" - } - ] - }, - "docker-daemon": { - "": [ - { - "type": "insecureAcceptAnything" - } - ] - }, - "atomic": { - "": [ - { - "type": "insecureAcceptAnything" - } - ] - }, - "containers-storage": { - "": [ - { - "type": "insecureAcceptAnything" - } - ] - }, - "dir": { - "": [ - { - "type": "insecureAcceptAnything" - } - ] - }, - "oci": { - "": [ - { - "type": "insecureAcceptAnything" - } - ] - }, - "oci-archive": { - "": [ - { - "type": "insecureAcceptAnything" - } - ] - }, - "docker-archive": { - "": [ - { - "type": "insecureAcceptAnything" - } - ] - }, - "tarball": { - "": [ - { - "type": "insecureAcceptAnything" - } - ] - } - } -} diff --git a/ucore/usr/etc/containers/registries.d/ublue-os.yaml b/ucore/usr/etc/containers/registries.d/ublue-os.yaml deleted file mode 100644 index f314b0a..0000000 --- a/ucore/usr/etc/containers/registries.d/ublue-os.yaml +++ /dev/null @@ -1,3 +0,0 @@ -docker: - ghcr.io/ublue-os: - use-sigstore-attachments: true \ No newline at end of file diff --git a/ucore/usr/etc/pki/containers/ublue-os.pub b/ucore/usr/etc/pki/containers/ublue-os.pub deleted file mode 100644 index f9482c4..0000000 --- a/ucore/usr/etc/pki/containers/ublue-os.pub +++ /dev/null @@ -1,4 +0,0 @@ ------BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7lh7fJMV4dBT2jT1XafixUJa7OVA -cT+QFVD8IfIJIS/KBAc8hx1aslzkH3tfeM0cwyCLB7kOStZ4sh6RyFQD9w== ------END PUBLIC KEY----- diff --git a/ucore/usr/lib/systemd/system/zfs-scrub-monthly@.timer b/ucore/usr/lib/systemd/system/zfs-scrub-monthly@.timer new file mode 100644 index 0000000..961dc7f --- /dev/null +++ b/ucore/usr/lib/systemd/system/zfs-scrub-monthly@.timer @@ -0,0 +1,12 @@ +[Unit] +Description=Monthly zpool scrub timer for %i +Documentation=man:zpool-scrub(8) + +[Timer] +OnCalendar=monthly +Persistent=true +RandomizedDelaySec=1h +Unit=zfs-scrub@%i.service + +[Install] +WantedBy=timers.target \ No newline at end of file diff --git a/ucore/usr/lib/systemd/system/zfs-scrub-weekly@.timer b/ucore/usr/lib/systemd/system/zfs-scrub-weekly@.timer new file mode 100644 index 0000000..d4cd754 --- /dev/null +++ b/ucore/usr/lib/systemd/system/zfs-scrub-weekly@.timer @@ -0,0 +1,12 @@ +[Unit] +Description=Weekly zpool scrub timer for %i +Documentation=man:zpool-scrub(8) + +[Timer] +OnCalendar=weekly +Persistent=true +RandomizedDelaySec=1h +Unit=zfs-scrub@%i.service + +[Install] +WantedBy=timers.target \ No newline at end of file diff --git a/ucore/usr/lib/systemd/system/zfs-scrub@.service b/ucore/usr/lib/systemd/system/zfs-scrub@.service new file mode 100644 index 0000000..0eecc61 --- /dev/null +++ b/ucore/usr/lib/systemd/system/zfs-scrub@.service @@ -0,0 +1,15 @@ +[Unit] +Description=zpool scrub on %i +Documentation=man:zpool-scrub(8) +Requires=zfs.target +After=zfs.target +ConditionACPower=true +ConditionPathIsDirectory=/sys/module/zfs + +[Service] +EnvironmentFile=-@initconfdir@/zfs +ExecStart=/bin/sh -c '\ +if /usr/sbin/zpool status %i | grep -q "scrub in progress"; then\ +exec /usr/sbin/zpool wait -t scrub %i;\ +else exec /usr/sbin/zpool scrub -w %i; fi' +ExecStop=-/bin/sh -c '/usr/sbin/zpool scrub -p %i 2>/dev/null || true'