max / alloy
3 files changed,
+234 insertions,
-42 deletions
| @@ -2643,21 +2643,57 @@ | |||
| 2643 | 2643 | "winnow", | |
| 2644 | 2644 | ] | |
| 2645 | 2645 | ||
| 2646 | + | [[patch.unused]] | |
| 2647 | + | name = "docengine" | |
| 2648 | + | version = "0.7.0" | |
| 2649 | + | ||
| 2650 | + | [[patch.unused]] | |
| 2651 | + | name = "quasi-axum" | |
| 2652 | + | version = "0.79.0" | |
| 2653 | + | ||
| 2654 | + | [[patch.unused]] | |
| 2655 | + | name = "quasi-basics" | |
| 2656 | + | version = "0.79.0" | |
| 2657 | + | ||
| 2658 | + | [[patch.unused]] | |
| 2659 | + | name = "quasi-http" | |
| 2660 | + | version = "0.79.0" | |
| 2661 | + | ||
| 2662 | + | [[patch.unused]] | |
| 2663 | + | name = "quasi-immediate" | |
| 2664 | + | version = "0.79.0" | |
| 2665 | + | ||
| 2666 | + | [[patch.unused]] | |
| 2667 | + | name = "quasi-notifs" | |
| 2668 | + | version = "0.79.0" | |
| 2669 | + | ||
| 2670 | + | [[patch.unused]] | |
| 2671 | + | name = "quasi-router" | |
| 2672 | + | version = "0.79.0" | |
| 2673 | + | ||
| 2674 | + | [[patch.unused]] | |
| 2675 | + | name = "quasi-store" | |
| 2676 | + | version = "0.1.0" | |
| 2677 | + | ||
| 2678 | + | [[patch.unused]] | |
| 2679 | + | name = "quasi-tauri" | |
| 2680 | + | version = "0.79.0" | |
| 2681 | + | ||
| 2682 | + | [[patch.unused]] | |
| 2683 | + | name = "quasi-webview" | |
| 2684 | + | version = "0.79.0" | |
| 2685 | + | ||
| 2646 | 2686 | [[patch.unused]] | |
| 2647 | 2687 | name = "synckit-client" | |
| 2648 | - | version = "0.9.1" | |
| 2688 | + | version = "0.10.0" | |
| 2649 | 2689 | ||
| 2650 | 2690 | [[patch.unused]] | |
| 2651 | 2691 | name = "synckit-config" | |
| 2652 | 2692 | version = "0.2.0" | |
| 2653 | 2693 | ||
| 2654 | - | [[patch.unused]] | |
| 2655 | - | name = "docengine" | |
| 2656 | - | version = "0.7.0" | |
| 2657 | - | ||
| 2658 | 2694 | [[patch.unused]] | |
| 2659 | 2695 | name = "quasi-type" | |
| 2660 | - | version = "0.1.0" | |
| 2696 | + | version = "0.1.3" | |
| 2661 | 2697 | ||
| 2662 | 2698 | [[patch.unused]] | |
| 2663 | 2699 | name = "kberg" | |
| @@ -2674,39 +2710,3 @@ | |||
| 2674 | 2710 | [[patch.unused]] | |
| 2675 | 2711 | name = "tagtree" | |
| 2676 | 2712 | version = "0.4.1" | |
| 2677 | - | ||
| 2678 | - | [[patch.unused]] | |
| 2679 | - | name = "quasi-axum" | |
| 2680 | - | version = "0.61.1" | |
| 2681 | - | ||
| 2682 | - | [[patch.unused]] | |
| 2683 | - | name = "quasi-basics" | |
| 2684 | - | version = "0.61.1" | |
| 2685 | - | ||
| 2686 | - | [[patch.unused]] | |
| 2687 | - | name = "quasi-http" | |
| 2688 | - | version = "0.61.1" | |
| 2689 | - | ||
| 2690 | - | [[patch.unused]] | |
| 2691 | - | name = "quasi-immediate" | |
| 2692 | - | version = "0.61.1" | |
| 2693 | - | ||
| 2694 | - | [[patch.unused]] | |
| 2695 | - | name = "quasi-notifs" | |
| 2696 | - | version = "0.61.1" | |
| 2697 | - | ||
| 2698 | - | [[patch.unused]] | |
| 2699 | - | name = "quasi-router" | |
| 2700 | - | version = "0.61.1" | |
| 2701 | - | ||
| 2702 | - | [[patch.unused]] | |
| 2703 | - | name = "quasi-store" | |
| 2704 | - | version = "0.1.0" | |
| 2705 | - | ||
| 2706 | - | [[patch.unused]] | |
| 2707 | - | name = "quasi-tauri" | |
| 2708 | - | version = "0.61.1" | |
| 2709 | - | ||
| 2710 | - | [[patch.unused]] | |
| 2711 | - | name = "quasi-webview" | |
| 2712 | - | version = "0.61.1" |
| @@ -1,0 +1,101 @@ | |||
| 1 | + | # alloy-nvidia — Alloy plus the open NVIDIA kernel module, aarch64. | |
| 2 | + | # | |
| 3 | + | # Derived, not a build ARG on the shipped Containerfile. Max chose option (c) | |
| 4 | + | # on alloy `2a382a75` (2026-08-30) and the reason is structural rather than | |
| 5 | + | # stylistic: the kernel and the module come from the same digest by | |
| 6 | + | # construction, so the kernel-lock failure the ARG option had is impossible | |
| 7 | + | # here. There is no build-time assertion to write and no way for | |
| 8 | + | # build/refresh-base-digests.sh to ship a machine that boots with no GPU and no | |
| 9 | + | # signal, because moving the base digest cannot reach an image built from the | |
| 10 | + | # old one. | |
| 11 | + | # | |
| 12 | + | # It also keeps the shipped image out of it. An aarch64 NVIDIA card is not a | |
| 13 | + | # role almost all Alloy users have, and wiki `alloy-selection-discipline` says | |
| 14 | + | # the shipped image should not serve one by default. | |
| 15 | + | # | |
| 16 | + | # WHAT ASTRA NEEDS THIS FOR: an RTX 5070 Ti, Blackwell GB203, which the | |
| 17 | + | # proprietary module does not drive. `akmod-nvidia` on aarch64 IS the open | |
| 18 | + | # build -- `modinfo` reports `license: Dual MIT/GPL`, where the proprietary one | |
| 19 | + | # reports `NVIDIA`. There is no separate `akmod-nvidia-open` for this arch, so | |
| 20 | + | # do not go looking for one. | |
| 21 | + | # | |
| 22 | + | # Usage: build/build-nvidia.sh. It resolves the digest, so this file names none. | |
| 23 | + | ||
| 24 | + | ARG ALLOY_DIGEST | |
| 25 | + | FROM localhost/alloy@${ALLOY_DIGEST} | |
| 26 | + | ||
| 27 | + | # RPM Fusion nonfree, which is where the akmod lives. `--nogpgcheck` on the | |
| 28 | + | # release package alone and nothing else: it is the package that installs the | |
| 29 | + | # key every later transaction is then checked against, which is the one | |
| 30 | + | # bootstrap that cannot itself be checked. | |
| 31 | + | # | |
| 32 | + | # `$releasever` resolves to 43 without help, because the base image already | |
| 33 | + | # pins it in /etc/dnf/vars/releasever -- Alloy re-brands os-release, so dnf | |
| 34 | + | # would otherwise expand it to Alloy's own VERSION_ID and ask for a nonexistent | |
| 35 | + | # Fedora. | |
| 36 | + | RUN dnf install -y --nogpgcheck \ | |
| 37 | + | "https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm" \ | |
| 38 | + | "https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm" \ | |
| 39 | + | && dnf clean all | |
| 40 | + | ||
| 41 | + | # The akmod source and the userspace it pairs with. | |
| 42 | + | # | |
| 43 | + | # NOT `kmod-nvidia`, which exists prebuilt in the repo and is built against RPM | |
| 44 | + | # Fusion's own kernel rather than this image's. Installing it would put a | |
| 45 | + | # module in the image whose vermagic does not match the kernel beside it, which | |
| 46 | + | # is the failure this whole derived shape exists to make impossible -- and it | |
| 47 | + | # would look installed. | |
| 48 | + | # | |
| 49 | + | # Weak deps off, as everywhere else in this project. | |
| 50 | + | RUN dnf install -y --setopt=install_weak_deps=False \ | |
| 51 | + | akmod-nvidia \ | |
| 52 | + | xorg-x11-drv-nvidia-cuda \ | |
| 53 | + | && dnf clean all | |
| 54 | + | ||
| 55 | + | # Build the module against THIS image's kernel, now, at build time. | |
| 56 | + | # | |
| 57 | + | # akmods normally runs on the machine after a kernel update, which a bootc | |
| 58 | + | # image does not do: the filesystem is immutable and the kernel only changes by | |
| 59 | + | # taking a new image. So the build happens here, against the one kernel this | |
| 60 | + | # image has, and the result ships inside it. | |
| 61 | + | # | |
| 62 | + | # The kernel is read out of /usr/lib/modules rather than passed in. There is | |
| 63 | + | # exactly one, it came with the digest above, and a number written here by hand | |
| 64 | + | # is the drift this file exists to avoid. | |
| 65 | + | RUN set -eux; \ | |
| 66 | + | kernel="$(ls /usr/lib/modules | head -1)"; \ | |
| 67 | + | akmods --force --kernels "$kernel"; \ | |
| 68 | + | # The check, and it is the done condition. A build that produced nothing, | |
| 69 | + | # or produced a module for a different kernel, fails here rather than at | |
| 70 | + | # boot on a machine with no display. | |
| 71 | + | module="/usr/lib/modules/$kernel/extra/nvidia/nvidia.ko.xz"; \ | |
| 72 | + | [ -f "$module" ] || module="/usr/lib/modules/$kernel/extra/nvidia/nvidia.ko"; \ | |
| 73 | + | test -f "$module"; \ | |
| 74 | + | vermagic="$(modinfo -F vermagic "$module" | awk '{print $1}')"; \ | |
| 75 | + | test "$vermagic" = "$kernel" \ | |
| 76 | + | || { echo "vermagic $vermagic is not this image's kernel $kernel" >&2; exit 1; }; \ | |
| 77 | + | # Open, not proprietary. Blackwell GB203 needs the open module, and the two | |
| 78 | + | # are told apart by their licence: the open one is Dual MIT/GPL. | |
| 79 | + | licence="$(modinfo -F license "$module")"; \ | |
| 80 | + | case "$licence" in \ | |
| 81 | + | *MIT*) : ;; \ | |
| 82 | + | *) echo "nvidia.ko reports licence '$licence'; expected the open Dual MIT/GPL build" >&2; exit 1 ;; \ | |
| 83 | + | esac; \ | |
| 84 | + | echo "built $module: vermagic $vermagic, licence $licence" | |
| 85 | + | ||
| 86 | + | # The initramfs has to carry it, or the module is present and not loaded early | |
| 87 | + | # enough to drive the console. | |
| 88 | + | RUN set -eux; \ | |
| 89 | + | kernel="$(ls /usr/lib/modules | head -1)"; \ | |
| 90 | + | depmod -a "$kernel"; \ | |
| 91 | + | dracut --force --no-hostonly \ | |
| 92 | + | --kver "$kernel" \ | |
| 93 | + | "/usr/lib/modules/$kernel/initramfs.img" | |
| 94 | + | ||
| 95 | + | # `nouveau` and the nvidia module cannot both drive the card, and nouveau wins | |
| 96 | + | # by loading first. Blacklisted here rather than as a kernel argument so the | |
| 97 | + | # fact travels with the image that needs it. | |
| 98 | + | RUN printf 'blacklist nouveau\noptions nouveau modeset=0\n' \ | |
| 99 | + | > /etc/modprobe.d/alloy-nvidia-blacklist.conf | |
| 100 | + | ||
| 101 | + | RUN bootc container lint |
| @@ -1,0 +1,91 @@ | |||
| 1 | + | #!/usr/bin/env bash | |
| 2 | + | # | |
| 3 | + | # build-nvidia.sh — build alloy-nvidia, Alloy plus the open NVIDIA module. | |
| 4 | + | # | |
| 5 | + | # A thin derived image over an Alloy that already exists. It does not build | |
| 6 | + | # Alloy: the whole point of the derived shape (alloy `2a382a75`, option c) is | |
| 7 | + | # that the module is compiled against the kernel of one specific Alloy image, | |
| 8 | + | # so the input is a digest and this script's job is to resolve one and hold it. | |
| 9 | + | # | |
| 10 | + | # aarch64 only, and that is not a limitation to lift. The card this exists for | |
| 11 | + | # is in astra; CLAUDE.md forbids cross-compiling, and an x86_64 machine with an | |
| 12 | + | # NVIDIA card would want the proprietary module rather than the open one | |
| 13 | + | # Blackwell requires. | |
| 14 | + | # | |
| 15 | + | # Rootful, for build-image.sh's reason: it shares one container store with the | |
| 16 | + | # Alloy build, so the digest below resolves without a rootless->rootful copy. | |
| 17 | + | # | |
| 18 | + | # Usage: | |
| 19 | + | # build/build-nvidia.sh # derive from localhost/alloy:local | |
| 20 | + | # build/build-nvidia.sh --digest sha256:... # derive from a named digest | |
| 21 | + | # build/build-nvidia.sh --tag alloy-nvidia:aarch64 | |
| 22 | + | ||
| 23 | + | set -euo pipefail | |
| 24 | + | ||
| 25 | + | REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" | |
| 26 | + | ||
| 27 | + | # priv / privc. See build/privilege.sh. | |
| 28 | + | # shellcheck source=build/privilege.sh | |
| 29 | + | . "$REPO_ROOT/build/privilege.sh" | |
| 30 | + | ||
| 31 | + | BASE="localhost/alloy:local" | |
| 32 | + | DIGEST="" | |
| 33 | + | TAG="localhost/alloy-nvidia:aarch64" | |
| 34 | + | ||
| 35 | + | while [ $# -gt 0 ]; do | |
| 36 | + | case "$1" in | |
| 37 | + | --digest) DIGEST="${2:?--digest needs a sha256:... value}"; shift 2 ;; | |
| 38 | + | --base) BASE="${2:?--base needs an image}"; shift 2 ;; | |
| 39 | + | --tag) TAG="${2:?--tag needs a name}"; shift 2 ;; | |
| 40 | + | -h|--help) sed -n '2,25p' "$0"; exit 0 ;; | |
| 41 | + | *) echo "error: unknown argument $1" >&2; exit 2 ;; | |
| 42 | + | esac | |
| 43 | + | done | |
| 44 | + | ||
| 45 | + | arch="$(uname -m)" | |
| 46 | + | if [ "$arch" != "aarch64" ]; then | |
| 47 | + | echo "error: alloy-nvidia is aarch64 only; this is $arch." >&2 | |
| 48 | + | echo " The card it exists for is astra's. Builds are native per" >&2 | |
| 49 | + | echo " architecture (CLAUDE.md), so build it there." >&2 | |
| 50 | + | exit 1 | |
| 51 | + | fi | |
| 52 | + | ||
| 53 | + | # The digest is the input, so it is resolved and printed rather than assumed. | |
| 54 | + | # Deriving from a tag would mean two runs a week apart produced modules for | |
| 55 | + | # different kernels while claiming the same provenance, which is the drift the | |
| 56 | + | # base pins in the Containerfile exist to stop. | |
| 57 | + | if [ -z "$DIGEST" ]; then | |
| 58 | + | DIGEST="$(priv podman image inspect "$BASE" --format '{{.Digest}}' 2>/dev/null || true)" | |
| 59 | + | [ -n "$DIGEST" ] || { | |
| 60 | + | echo "error: no image $BASE to derive from." >&2 | |
| 61 | + | echo " Build Alloy first: build/build-image.sh --skip-bib" >&2 | |
| 62 | + | exit 1 | |
| 63 | + | } | |
| 64 | + | fi | |
| 65 | + | ||
| 66 | + | kernel="$(priv podman run --rm "$BASE" ls /usr/lib/modules | head -1)" | |
| 67 | + | echo "deriving from $BASE" | |
| 68 | + | echo " digest: $DIGEST" | |
| 69 | + | echo " kernel: $kernel" | |
| 70 | + | echo | |
| 71 | + | ||
| 72 | + | priv podman build \ | |
| 73 | + | --build-arg "ALLOY_DIGEST=$DIGEST" \ | |
| 74 | + | -f "$REPO_ROOT/build/Containerfile.nvidia" \ | |
| 75 | + | -t "$TAG" \ | |
| 76 | + | "$REPO_ROOT" | |
| 77 | + | ||
| 78 | + | echo | |
| 79 | + | echo "built $TAG" | |
| 80 | + | # Read back out of the finished image rather than trusting the build log: the | |
| 81 | + | # Containerfile asserts this too, and a second reading from the outside is what | |
| 82 | + | # a person checking the machine would do. | |
| 83 | + | priv podman run --rm "$TAG" sh -c ' | |
| 84 | + | kernel="$(ls /usr/lib/modules | head -1)" | |
| 85 | + | module="/usr/lib/modules/$kernel/extra/nvidia/nvidia.ko.xz" | |
| 86 | + | [ -f "$module" ] || module="/usr/lib/modules/$kernel/extra/nvidia/nvidia.ko" | |
| 87 | + | echo " kernel: $kernel" | |
| 88 | + | echo " vermagic: $(modinfo -F vermagic "$module")" | |
| 89 | + | echo " licence: $(modinfo -F license "$module")" | |
| 90 | + | echo " version: $(modinfo -F version "$module")" | |
| 91 | + | ' |