Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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" ];
Expand Down Expand Up @@ -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 {
Expand Down
44 changes: 43 additions & 1 deletion hosts/builder-aarch64/default.nix
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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";
}
104 changes: 104 additions & 0 deletions scripts/katello-sourceos-setup.sh
Original file line number Diff line number Diff line change
@@ -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=<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"