Skip to content

Commit 1f23a46

Browse files
committed
end to end install works
1 parent 52cc594 commit 1f23a46

12 files changed

Lines changed: 108 additions & 178 deletions

File tree

Containerfile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ RUN --mount=type=bind,from=ctx,source=/,target=/ctx \
5151
--mount=type=cache,dst=/var/cache/libdnf5 \
5252
--mount=type=cache,dst=/var/cache/rpm-ostree \
5353
--mount=type=tmpfs,dst=/tmp \
54-
/ctx/build_files/shared/build.sh && \
55-
ostree container commit
54+
/ctx/build_files/shared/build.sh
5655

5756
# Final validation
5857
RUN bootc container lint

Justfile

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
export repo_organization := env("REPO_ORGANIZATION", "binarypie-dev")
66
export image_name := env("IMAGE_NAME", "hypercube")
77
export fedora_version := env("FEDORA_VERSION", "43")
8-
export akmods_flavor := env("AKMODS_FLAVOR", "coreos-stable")
8+
export akmods_flavor := env("AKMODS_FLAVOR", "main")
99

1010
# Runtime detection
1111
export SUDO := if `id -u` == "0" { "" } else { "sudo" }
@@ -137,6 +137,23 @@ run-iso-local iso_file:
137137
--boot uefi \
138138
--autoconsole graphical
139139

140+
# Restart the test VM and connect to console
141+
[group('VM')]
142+
restart-vm:
143+
#!/usr/bin/bash
144+
set -euo pipefail
145+
VM_NAME="hypercube-test"
146+
147+
echo "Stopping VM..."
148+
virsh destroy "${VM_NAME}" 2>/dev/null || true
149+
sleep 1
150+
151+
echo "Starting VM..."
152+
virsh start "${VM_NAME}"
153+
154+
echo "Connecting to console..."
155+
virt-viewer "${VM_NAME}"
156+
140157
# Delete the test VM and its disk
141158
[group('VM')]
142159
delete-test-vm:

build_files/base/00-kernel-akmods.sh

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,13 @@ set -eoux pipefail
88
echo "Installing kernel, akmods, and NVIDIA drivers..."
99

1010
FEDORA_VERSION="$(rpm -E %fedora)"
11-
AKMODS_FLAVOR="${AKMODS_FLAVOR:-coreos-stable}"
11+
AKMODS_FLAVOR="${AKMODS_FLAVOR:-main}"
1212

13-
# Remove existing kernel packages
14-
for pkg in kernel kernel-core kernel-modules kernel-modules-core kernel-modules-extra; do
15-
rpm --erase "$pkg" --nodeps || true
16-
done
13+
# Get current kernel version from base image (don't replace it)
14+
KERNEL_VERSION=$(rpm -q kernel-core --queryformat "%{VERSION}-%{RELEASE}.%{ARCH}" | tail -n 1)
15+
echo "Using base image kernel: ${KERNEL_VERSION}"
1716

18-
# Fetch akmods container (contains kernel RPMs and kmods)
17+
# Fetch akmods container (contains kmods for this kernel)
1918
skopeo copy --retry-times 3 \
2019
docker://ghcr.io/ublue-os/akmods:"${AKMODS_FLAVOR}"-"${FEDORA_VERSION}" \
2120
dir:/tmp/akmods
@@ -24,24 +23,6 @@ AKMODS_TARGZ=$(jq -r '.layers[].digest' </tmp/akmods/manifest.json | cut -d : -f
2423
tar -xvzf /tmp/akmods/"$AKMODS_TARGZ" -C /tmp/
2524
mv /tmp/rpms/* /tmp/akmods/
2625

27-
# Install kernel from akmods cache
28-
# Use rpm directly to skip scriptlets that try to run dracut (fails in container builds)
29-
rpm -ivh --nodeps --noscripts \
30-
/tmp/kernel-rpms/kernel-[0-9]*.rpm \
31-
/tmp/kernel-rpms/kernel-core-*.rpm \
32-
/tmp/kernel-rpms/kernel-modules-*.rpm \
33-
/tmp/kernel-rpms/kernel-modules-core-*.rpm \
34-
/tmp/kernel-rpms/kernel-modules-extra-*.rpm
35-
36-
rpm -ivh --nodeps --noscripts /tmp/kernel-rpms/kernel-devel-*.rpm
37-
38-
# Lock kernel version to prevent mismatches
39-
dnf5 versionlock add kernel kernel-devel kernel-devel-matched kernel-core kernel-modules kernel-modules-core kernel-modules-extra
40-
41-
# Get installed kernel version for nvidia akmods
42-
KERNEL_VERSION=$(rpm -q kernel-core --queryformat "%{VERSION}-%{RELEASE}.%{ARCH}" | tail -n 1)
43-
echo "Installed kernel: ${KERNEL_VERSION}"
44-
4526
# Enable ublue-os akmods COPR
4627
sed -i 's@enabled=0@enabled=1@g' /etc/yum.repos.d/_copr_ublue-os-akmods.repo
4728

@@ -94,6 +75,6 @@ kargs = ["rd.driver.blacklist=nouveau", "modprobe.blacklist=nouveau", "nvidia-dr
9475
EOF
9576

9677
# Cleanup
97-
rm -rf /tmp/akmods /tmp/akmods-nvidia /tmp/akmods-rpms /tmp/kernel-rpms /tmp/rpms /tmp/nvidia-install.sh
78+
rm -rf /tmp/akmods /tmp/akmods-nvidia /tmp/akmods-rpms /tmp/rpms /tmp/nvidia-install.sh
9879

99-
echo "Kernel and NVIDIA drivers installed successfully"
80+
echo "NVIDIA drivers installed successfully for kernel ${KERNEL_VERSION}"

build_files/base/01-base-system.sh

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@ echo "Installing Hypercube base system..."
99
# Clean DNF cache first
1010
dnf5 -y clean all
1111

12+
### Enable Hypercube COPR for custom packages
13+
dnf5 -y copr enable binarypie/hypercube
14+
1215
### Display Manager: greetd + regreet
13-
# greetd is in official Fedora repos, regreet from binarypie/hypercube COPR
14-
# cage is a minimal Wayland compositor to host regreet
16+
# regreet from binarypie/hypercube COPR
17+
# cage is a minimal Wayland compositor to host regreet and the first-boot wizard
1518
dnf5 -y install \
1619
greetd \
1720
greetd-selinux \
@@ -91,7 +94,8 @@ systemctl enable greetd.service
9194
systemctl enable NetworkManager.service
9295
systemctl enable bluetooth.service
9396
systemctl enable power-profiles-daemon.service
94-
systemctl enable hypercube-first-boot.service
97+
# TODO: Re-enable once first-boot wizard is properly tested
98+
# systemctl enable hypercube-first-boot.service
9599

96100
### Disable services we don't need
97101
systemctl disable gdm.service 2>/dev/null || true
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/bash
2+
# Regenerate initramfs after all kernel modules are installed
3+
# This is critical for bootc containers that change the kernel
4+
5+
set -ouex pipefail
6+
7+
echo "Regenerating initramfs..."
8+
9+
QUALIFIED_KERNEL="$(rpm -qa | grep -P 'kernel-(\d+\.\d+\.\d+)' | sed -E 's/kernel-//')"
10+
echo "Kernel version: ${QUALIFIED_KERNEL}"
11+
12+
export DRACUT_NO_XATTR=1
13+
/usr/bin/dracut \
14+
--no-hostonly \
15+
--kver "${QUALIFIED_KERNEL}" \
16+
--reproducible \
17+
--add ostree \
18+
-f "/lib/modules/${QUALIFIED_KERNEL}/initramfs.img"
19+
20+
chmod 0600 "/lib/modules/${QUALIFIED_KERNEL}/initramfs.img"
21+
22+
echo "Initramfs regenerated successfully"

build_files/hypercube/99-tests.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ echo "Running Hypercube validation tests..."
1010
REQUIRED_PACKAGES=(
1111
# Display manager
1212
"greetd"
13-
"tuigreet"
13+
"regreet"
14+
"cage"
1415
# Hyprland stack
1516
"hyprland"
1617
"hyprlock"

build_files/hyprland/01-hyprland-desktop.sh

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@ set -ouex pipefail
66

77
echo "Installing Hyprland desktop stack..."
88

9-
### Enable Hypercube COPR (our self-maintained packages)
10-
dnf5 -y copr enable binarypie/hypercube
11-
12-
### Compositor / Hyprland Stack (from Hypercube COPR)
9+
### Compositor / Hyprland Stack
1310
dnf5 -y install \
1411
hyprland \
1512
hyprland-guiutils \

dot_files/quickshell/welcome-mode.qml

Lines changed: 43 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,52 +4,24 @@
44
import QtQuick
55
import QtQuick.Layouts
66
import QtQuick.Controls
7+
import QtQuick.Window
78
import Quickshell
8-
import Quickshell.Wayland
99
import Quickshell.Io
1010

1111
ShellRoot {
1212
id: root
1313

14-
// Welcome wizard runs on all screens, full screen
15-
Variants {
16-
model: Quickshell.screens
17-
18-
delegate: Component {
19-
PanelWindow {
20-
id: welcomeWindow
21-
required property var modelData
22-
property var screen: modelData
23-
24-
anchors.fill: true
25-
color: "#1a1b26" // Tokyonight background
26-
27-
// Only show wizard on primary screen
28-
property bool isPrimary: screen === Quickshell.screens[0]
29-
30-
// Background for non-primary screens
31-
Rectangle {
32-
anchors.fill: parent
33-
visible: !isPrimary
34-
color: "#1a1b26"
35-
36-
Text {
37-
anchors.centerIn: parent
38-
text: "Hypercube"
39-
font.pixelSize: 48
40-
font.weight: Font.Medium
41-
color: "#7aa2f7"
42-
opacity: 0.3
43-
}
44-
}
45-
46-
// Wizard on primary screen
47-
Loader {
48-
anchors.fill: parent
49-
active: isPrimary
50-
sourceComponent: WelcomeWizard {}
51-
}
52-
}
14+
// Simple fullscreen window for cage compositor
15+
Window {
16+
id: welcomeWindow
17+
visible: true
18+
visibility: Window.FullScreen
19+
color: "#1a1b26" // Tokyonight background
20+
title: "Hypercube Setup"
21+
22+
// Wizard content
23+
WelcomeWizard {
24+
anchors.fill: parent
5325
}
5426
}
5527

@@ -662,29 +634,51 @@ ShellRoot {
662634
}
663635
}
664636

637+
property bool isCreating: false
638+
665639
function createUser() {
640+
if (isCreating) return
641+
isCreating = true
666642
errorMessage = ""
667643
userCreateProcess.running = true
668644
}
669645

646+
// Escape single quotes in strings for shell safety
647+
function shellEscape(str: string): string {
648+
return str.replace(/'/g, "'\\''")
649+
}
650+
670651
Process {
671652
id: userCreateProcess
653+
// Runs as root via greetd initial_session
672654
command: ["sh", "-c",
673-
"useradd -m -G wheel -c '" + (fullName || username) + "' '" + username + "' && " +
674-
"echo '" + username + ":" + password + "' | chpasswd && " +
655+
"useradd -m -G wheel -c '" + shellEscape(fullName || username) + "' '" + shellEscape(username) + "' && " +
656+
"echo '" + shellEscape(username) + ":" + shellEscape(password) + "' | chpasswd && " +
675657
// Save theme config for the new user
676-
"mkdir -p /home/" + username + "/.config/hypercube && " +
677-
"echo '{\"appearance\":{\"darkMode\":" + (selectedDarkMode ? "true" : "false") + ",\"accentColor\":\"" + selectedAccent + "\"}}' > /home/" + username + "/.config/hypercube/shell.json && " +
678-
"chown -R " + username + ":" + username + " /home/" + username + "/.config"
658+
"mkdir -p '/home/" + shellEscape(username) + "/.config/hypercube' && " +
659+
"echo '{\"appearance\":{\"darkMode\":" + (selectedDarkMode ? "true" : "false") + ",\"accentColor\":\"" + selectedAccent + "\"}}' > '/home/" + shellEscape(username) + "/.config/hypercube/shell.json' && " +
660+
"chown -R '" + shellEscape(username) + "':'" + shellEscape(username) + "' '/home/" + shellEscape(username) + "/.config'"
679661
]
680662

681663
running: false
682-
onExited: {
683-
if (exitCode === 0) {
684-
// Exit quickshell, which will cause Hyprland to exit
664+
onExited: (code, status) => {
665+
isCreating = false
666+
if (code === 0) {
667+
// Success - exit quickshell to return to greetd
685668
Qt.quit()
686669
} else {
687-
errorMessage = "Failed to create user. Exit code: " + exitCode
670+
errorMessage = "Failed to create user (error " + code + "). Please try again."
671+
}
672+
}
673+
}
674+
675+
// Allow exiting with Escape key
676+
Shortcut {
677+
sequence: "Escape"
678+
onActivated: {
679+
if (!isCreating) {
680+
// Exit without creating user - greetd will show regreet
681+
Qt.quit()
688682
}
689683
}
690684
}

system_files/shared/etc/greetd/config.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,11 @@ vt = 1
44

55
[default_session]
66
# Run regreet in cage (minimal Wayland compositor)
7-
command = "cage -s -- regreet"
7+
command = "/usr/sbin/cage -s -- /usr/sbin/regreet"
88
user = "greeter"
9+
10+
[initial_session]
11+
# First boot wizard - runs once as root, then exits to show regreet
12+
# Set XDG_RUNTIME_DIR for quickshell/Qt to work properly as root
13+
command = "sh -c 'mkdir -p /run/user/0 && export XDG_RUNTIME_DIR=/run/user/0; /usr/sbin/cage -s -- /usr/sbin/quickshell -p /usr/share/hypercube/config/quickshell/welcome-mode.qml'"
14+
user = "root"

system_files/shared/usr/lib/bootc/kargs.d/hypercube-kargs.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
"quiet",
55
"splash",
66
"rd.plymouth=1",
7-
"plymouth.use-simpledrm=1",
87
"bgrt_disable"
98
]
109
}

0 commit comments

Comments
 (0)