From b1e79313be8d4781bf5336eae668f7bdc0b57246 Mon Sep 17 00:00:00 2001 From: Michael Heller <21163552+mdheller@users.noreply.github.com> Date: Tue, 16 Jun 2026 11:55:06 -0400 Subject: [PATCH] feat(asahi): wire Asahi/Apple Silicon support for builder-aarch64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - flake.nix: add nixos-apple-silicon input (tpwrules/nixos-apple-silicon, follows nixpkgs); wire the apple-silicon-support module into nixosConfigurations.builder-aarch64 - hosts/builder-aarch64: add hardware.asahi options (enable, sound, AGX GPU), systemd-boot config for m1n1/U-Boot Asahi chain, canTouchEfiVariables=false (mandatory on Apple Silicon), Nix flake settings, local Katello substituter stub (127.0.0.1:8101), sourceos user with wheel/video/audio groups, stateVersion 25.05 hardware-configuration.nix is intentionally omitted — generate on device with `nixos-generate-config` after Asahi install. - scripts/katello-sourceos-setup.sh: hammer CLI setup for SourceOS content structure in Foreman+Katello: lifecycle envs (dev/candidate/stable), SourceOS product, nix-cache-aarch64-linux and sourceos-closures-aarch64 repos, sourceos-builder-aarch64 content view, initial publish + dev promote --- flake.nix | 11 +++- hosts/builder-aarch64/default.nix | 44 ++++++++++++- scripts/katello-sourceos-setup.sh | 104 ++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+), 3 deletions(-) create mode 100755 scripts/katello-sourceos-setup.sh diff --git a/flake.nix b/flake.nix index b9e7ac6..1b12432 100644 --- a/flake.nix +++ b/flake.nix @@ -3,13 +3,17 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + nixos-apple-silicon = { + url = "github:tpwrules/nixos-apple-silicon"; + inputs.nixpkgs.follows = "nixpkgs"; + }; lampstand-src = { url = "github:SocioProphet/lampstand"; flake = false; }; }; - outputs = { self, nixpkgs, lampstand-src }: + outputs = { self, nixpkgs, nixos-apple-silicon, lampstand-src }: let lib = nixpkgs.lib; systems = [ "x86_64-linux" "aarch64-linux" ]; @@ -75,7 +79,10 @@ builder-aarch64 = lib.nixosSystem { system = "aarch64-linux"; specialArgs = { inherit self; }; - modules = [ ./hosts/builder-aarch64/default.nix ]; + modules = [ + nixos-apple-silicon.nixosModules.apple-silicon-support + ./hosts/builder-aarch64/default.nix + ]; }; canary-x86_64 = lib.nixosSystem { diff --git a/hosts/builder-aarch64/default.nix b/hosts/builder-aarch64/default.nix index 4c336ee..6d1645d 100644 --- a/hosts/builder-aarch64/default.nix +++ b/hosts/builder-aarch64/default.nix @@ -1,7 +1,11 @@ -{ ... }: +{ config, lib, pkgs, ... }: { imports = [ ../../profiles/linux-dev/default.nix + # hardware-configuration.nix is device-specific. + # After Asahi install, run `nixos-generate-config` on the device and + # place the result at /etc/nixos/hardware-configuration.nix, or pass + # it via `--impure` with a local path override. ]; networking.hostName = "builder-aarch64"; @@ -10,4 +14,42 @@ role = "builder-aarch64"; channel = "dev"; }; + + # Apple Silicon hardware support (module wired in via flake.nix + # nixosConfigurations.builder-aarch64 modules list). + hardware.asahi = { + enable = true; + setupAsahiSound = true; + experimentalGpuAcceleration = true; + }; + + # Boot via systemd-boot: Asahi installer places m1n1 + U-Boot which + # expose an EFI stub. NixOS picks it up via systemd-boot. + # canTouchEfiVariables = false is mandatory — modifying EFI vars on + # Apple Silicon can prevent booting macOS. + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = false; + + # Flakes required for sourceos-syncd and prophet CLI + nix.settings.experimental-features = [ "nix-command" "flakes" ]; + + # Trusted substituters for the SourceOS binary cache (populated by Katello + # after the content view is published) + nix.settings.trusted-substituters = [ + "https://cache.nixos.org" + "http://127.0.0.1:8101" + ]; + nix.settings.trusted-public-keys = [ + "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" + ]; + + users.users.sourceos = { + isNormalUser = true; + extraGroups = [ "wheel" "video" "audio" "networkmanager" ]; + # Set password post-install via `passwd sourceos` — never commit credentials + }; + + security.sudo.wheelNeedsPassword = false; + + system.stateVersion = "25.05"; } diff --git a/scripts/katello-sourceos-setup.sh b/scripts/katello-sourceos-setup.sh new file mode 100755 index 0000000..947a983 --- /dev/null +++ b/scripts/katello-sourceos-setup.sh @@ -0,0 +1,104 @@ +#!/usr/bin/env bash +# Sets up SourceOS content structure in a running Foreman+Katello instance. +# Run after the foreman-installer bootstrap completes. +# +# Usage: +# FOREMAN_URL=https://127.0.0.1:8443 \ +# FOREMAN_USER=admin \ +# FOREMAN_PASSWORD= \ +# ORG=SocioProphet \ +# ./scripts/katello-sourceos-setup.sh +# +# Idempotent: re-running skips objects that already exist. + +set -euo pipefail + +FOREMAN_URL="${FOREMAN_URL:-https://127.0.0.1:8443}" +FOREMAN_USER="${FOREMAN_USER:-admin}" +FOREMAN_PASSWORD="${FOREMAN_PASSWORD:?FOREMAN_PASSWORD required}" +ORG="${ORG:-SocioProphet}" + +HAMMER="hammer --server ${FOREMAN_URL} --username ${FOREMAN_USER} --password ${FOREMAN_PASSWORD}" + +echo "=== SourceOS Katello content setup ===" +echo "Foreman: ${FOREMAN_URL} Org: ${ORG}" + +# ── 1. Lifecycle environments ───────────────────────────────────────────── +# Mirrors source-os/channels: dev → candidate → stable +echo "--- lifecycle environments" +$HAMMER lifecycle-environment create --organization "${ORG}" \ + --name dev --prior Library 2>/dev/null || echo " dev: exists" +$HAMMER lifecycle-environment create --organization "${ORG}" \ + --name candidate --prior dev 2>/dev/null || echo " candidate: exists" +$HAMMER lifecycle-environment create --organization "${ORG}" \ + --name stable --prior candidate 2>/dev/null || echo " stable: exists" + +# ── 2. Product ──────────────────────────────────────────────────────────── +echo "--- product" +$HAMMER product create --organization "${ORG}" \ + --name "SourceOS" \ + --description "SourceOS Linux image artifacts and Nix binary cache" \ + 2>/dev/null || echo " SourceOS product: exists" + +# ── 3. Repositories ─────────────────────────────────────────────────────── +echo "--- repositories" + +# Nix binary cache (file-type repo; populated by nix copy --to http://katello) +$HAMMER repository create --organization "${ORG}" \ + --product "SourceOS" \ + --name "nix-cache-aarch64-linux" \ + --content-type file \ + --url "https://cache.nixos.org" \ + --download-policy immediate \ + 2>/dev/null || echo " nix-cache-aarch64-linux: exists" + +# SourceOS system closure artifacts (file-type; Nix store paths exported as NAR) +$HAMMER repository create --organization "${ORG}" \ + --product "SourceOS" \ + --name "sourceos-closures-aarch64" \ + --content-type file \ + 2>/dev/null || echo " sourceos-closures-aarch64: exists" + +# ── 4. Content view ─────────────────────────────────────────────────────── +echo "--- content view" +$HAMMER content-view create --organization "${ORG}" \ + --name "sourceos-builder-aarch64" \ + --description "SourceOS builder image content view for aarch64 (Asahi/M2)" \ + 2>/dev/null || echo " sourceos-builder-aarch64: exists" + +$HAMMER content-view add-repository --organization "${ORG}" \ + --name "sourceos-builder-aarch64" \ + --product "SourceOS" \ + --repository "nix-cache-aarch64-linux" \ + 2>/dev/null || echo " nix-cache-aarch64-linux already in view" + +$HAMMER content-view add-repository --organization "${ORG}" \ + --name "sourceos-builder-aarch64" \ + --product "SourceOS" \ + --repository "sourceos-closures-aarch64" \ + 2>/dev/null || echo " sourceos-closures-aarch64 already in view" + +# Publish version 1.0 to Library +echo "--- publishing content view (this may take a minute)" +$HAMMER content-view publish --organization "${ORG}" \ + --name "sourceos-builder-aarch64" \ + --description "Initial publish — dev channel bootstrap" + +# Promote to dev lifecycle environment +echo "--- promoting to dev" +CV_VERSION=$($HAMMER --output json content-view version list \ + --organization "${ORG}" \ + --content-view "sourceos-builder-aarch64" | python3 -c \ + "import json,sys; vs=json.load(sys.stdin); print(sorted(vs,key=lambda v:v['ID'])[-1]['Version'])") + +$HAMMER content-view version promote \ + --organization "${ORG}" \ + --content-view "sourceos-builder-aarch64" \ + --version "${CV_VERSION}" \ + --to-lifecycle-environment dev + +echo "=== Setup complete ===" +echo "Content view 'sourceos-builder-aarch64' published and promoted to dev." +echo "Next: nix build and push the builder-aarch64 closure:" +echo " nix build .#nixosConfigurations.builder-aarch64.config.system.build.toplevel" +echo " nix copy --to 'http://127.0.0.1:8101?compression=zstd' ./result"