Update ISO installer tiers and backend deployment

This commit is contained in:
Jino Jose committed 2026-06-30 08:54:01 +05:30
1 parent 79784a6743
commit 56668f7bdc
38 files changed
+7206 -175

No files matched your search

+199
View File
@@ -0,0 +1,199 @@
#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────
# Nexus One AI — Starter Tier ISO Builder
# Hardware target: compact workstation (1× RTX 5090, 64 GB RAM, 2 TB NVMe)
#
# Usage:
# cd ~/aipackage
# bash autoinstall/build-iso-starter.sh
#
# Output: autoinstall/cezen-ai-starter-ubuntu2204.iso
# Flash to USB:
# diskutil unmountDisk /dev/diskN
# sudo dd if=cezen-ai-starter-ubuntu2204.iso of=/dev/diskN bs=4m status=progress
# ─────────────────────────────────────────────────────────────
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PACKAGE_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
WORK_DIR="/tmp/cezen-iso-starter-work"
ORIGINAL_ISO="/tmp/ubuntu-22.04.5-live-server-amd64.iso"
OUTPUT_ISO="$SCRIPT_DIR/cezen-ai-starter-ubuntu2204.iso"
UBUNTU_URL="https://releases.ubuntu.com/22.04.5/ubuntu-22.04.5-live-server-amd64.iso"
TIER="starter"
echo "╔══════════════════════════════════════════════════════╗"
echo "║ Nexus One AI — ISO Builder [STARTER TIER] ║"
echo "║ RTX 5090 · 64 GB RAM · 2 TB NVMe · 1–5 users ║"
echo "╚══════════════════════════════════════════════════════╝"
echo ""
# ── Install build tools ────────────────────────
echo "→ Installing build tools..."
apt-get update -qq
apt-get install -y -qq xorriso wget isolinux rsync
echo "✓ Tools ready"
# ── Download Ubuntu ISO ────────────────────────
if [ -f "$ORIGINAL_ISO" ]; then
echo "✓ Ubuntu ISO already downloaded"
else
echo "→ Downloading Ubuntu 22.04.5 Server ISO (~1.8 GB)..."
wget --show-progress -O "$ORIGINAL_ISO" "$UBUNTU_URL"
echo "✓ Downloaded"
fi
# ── Extract ISO ────────────────────────────────
echo "→ Extracting ISO..."
rm -rf "$WORK_DIR"
mkdir -p "$WORK_DIR"
xorriso -osirrox on \
-indev "$ORIGINAL_ISO" \
-extract / "$WORK_DIR" 2>/dev/null
chmod -R u+w "$WORK_DIR"
echo "✓ Extracted"
# ── Inject Starter autoinstall files ──────────
echo "→ Injecting Starter autoinstall config..."
mkdir -p "$WORK_DIR/nocloud"
cp "$SCRIPT_DIR/user-data-starter" "$WORK_DIR/nocloud/user-data"
cp "$SCRIPT_DIR/meta-data" "$WORK_DIR/nocloud/meta-data"
echo "✓ user-data-starter and meta-data injected"
# ── Online installer mode ──────────────────────
# The installed system pulls the current package from cgit on first boot. This
# keeps the ISO small and avoids shipping stale backend/portal code.
echo "✓ Online installer mode: package will be pulled from cgit on first boot"
# ── Patch GRUB ────────────────────────────────
echo "→ Patching GRUB config..."
GRUB_CFG="$WORK_DIR/boot/grub/grub.cfg"
cp "$GRUB_CFG" "$GRUB_CFG.orig"
sed -i "s/set timeout=.*/set timeout=5/" "$GRUB_CFG"
sed -i "s/set timeout_style=.*/set timeout_style=countdown/" "$GRUB_CFG"
sed -i '/^\s*linux.*vmlinuz/s|---|autoinstall ds=nocloud\\;s=/cdrom/nocloud/ ---|' "$GRUB_CFG"
# Update GRUB title to reflect Starter tier
sed -i 's/Install Ubuntu Server/Install Nexus One AI — Starter Tier/' "$GRUB_CFG" || true
echo "✓ GRUB patched"
# ── Extract MBR and EFI boot data ─────────────
echo "→ Extracting boot data from original ISO..."
MBR_TEMPLATE=$(mktemp)
EFI_IMG=$(mktemp)
dd if="$ORIGINAL_ISO" bs=1 count=432 of="$MBR_TEMPLATE" 2>/dev/null
EFI_LINE=$(fdisk -l "$ORIGINAL_ISO" 2>/dev/null | grep "EFI")
echo " EFI partition info: $EFI_LINE"
EFI_START=$(echo "$EFI_LINE" | awk '{print $2}')
EFI_SIZE=$(echo "$EFI_LINE" | awk '{print $4}')
if [ -z "$EFI_START" ] || [ -z "$EFI_SIZE" ]; then
echo "ERROR: Could not detect EFI partition in ISO."
echo "Run: fdisk -l $ORIGINAL_ISO"
exit 1
fi
dd if="$ORIGINAL_ISO" bs=512 skip="$EFI_START" count="$EFI_SIZE" \
of="$EFI_IMG" 2>/dev/null
echo "✓ EFI partition extracted (start=$EFI_START, size=$EFI_SIZE)"
# ── Repack ISO (pass 1) ────────────────────────
echo "→ Repacking ISO (pass 1)..."
xorriso -as mkisofs \
-r \
-V "CezenAI_Starter_2204" \
-o "$OUTPUT_ISO" \
--grub2-mbr "$MBR_TEMPLATE" \
-partition_offset 16 \
--mbr-force-bootable \
-append_partition 2 28732ac11ff8d211ba4b00a0c93ec93b "$EFI_IMG" \
-appended_part_as_gpt \
-iso_mbr_part_type a2a0d0ebe5b9334487c068b6b72699c7 \
-c "/boot.catalog" \
-b "/boot/grub/i386-pc/eltorito.img" \
-no-emul-boot \
-boot-load-size 4 \
-boot-info-table \
--grub2-boot-info \
-eltorito-alt-boot \
-e "--interval:appended_partition_2:::" \
-no-emul-boot \
"$WORK_DIR"
# ── Refresh md5sum.txt and repack (pass 2) ────
echo "→ Refreshing md5sum.txt..."
FINAL_DIR=$(mktemp -d)
VERIFY_DIR=$(mktemp -d)
trap 'rm -rf "$WORK_DIR" "$MBR_TEMPLATE" "$EFI_IMG" "$FINAL_DIR" "$VERIFY_DIR"' EXIT
xorriso -osirrox on -indev "$OUTPUT_ISO" -extract / "$FINAL_DIR" >/dev/null 2>&1
chmod -R u+w "$FINAL_DIR"
(
cd "$FINAL_DIR"
rm -f md5sum.txt
find . -type f \
! -path './md5sum.txt' \
! -path './boot.catalog' \
-print0 \
| sort -z \
| xargs -0 md5sum > md5sum.txt
)
echo "✓ md5sum.txt refreshed"
echo "→ Repacking ISO (pass 2)..."
xorriso -as mkisofs \
-r \
-V "CezenAI_Starter_2204" \
-o "$OUTPUT_ISO" \
--grub2-mbr "$MBR_TEMPLATE" \
-partition_offset 16 \
--mbr-force-bootable \
-append_partition 2 28732ac11ff8d211ba4b00a0c93ec93b "$EFI_IMG" \
-appended_part_as_gpt \
-iso_mbr_part_type a2a0d0ebe5b9334487c068b6b72699c7 \
-c "/boot.catalog" \
-b "/boot/grub/i386-pc/eltorito.img" \
-no-emul-boot \
-boot-load-size 4 \
-boot-info-table \
--grub2-boot-info \
-eltorito-alt-boot \
-e "--interval:appended_partition_2:::" \
-no-emul-boot \
"$FINAL_DIR"
# ── Verify output ISO ──────────────────────────
echo "→ Verifying rebuilt ISO manifest..."
xorriso -osirrox on -indev "$OUTPUT_ISO" -extract / "$VERIFY_DIR" >/dev/null 2>&1
chmod -R u+w "$VERIFY_DIR"
(
cd "$VERIFY_DIR"
md5sum -c md5sum.txt >/tmp/cezen-iso-md5check-starter.log 2>&1 || {
echo "ERROR: Rebuilt ISO failed its own md5sum.txt verification."
sed -n '1,40p' /tmp/cezen-iso-md5check-starter.log
exit 1
}
)
echo "✓ Output ISO manifest verified"
echo ""
echo "╔══════════════════════════════════════════════════════╗"
echo "║ Done! Starter Tier ISO ready. ║"
echo "╚══════════════════════════════════════════════════════╝"
echo ""
ls -lh "$OUTPUT_ISO"
echo ""
echo "→ Transfer to MacBook:"
echo " scp user@server:~/aipackage/autoinstall/cezen-ai-starter-ubuntu2204.iso ."
echo ""
echo "→ Flash to USB (macOS):"
echo " diskutil list # find USB e.g. /dev/disk4"
echo " diskutil unmountDisk /dev/disk4"
echo " sudo dd if=cezen-ai-starter-ubuntu2204.iso of=/dev/disk4 bs=4m status=progress"
echo ""
echo "→ Post-flash: boot the workstation from USB."
echo " Unattended install completes in ~10 min."
echo " First-boot wizard runs on tty1 — set IP, org name, admin password."
echo " Then run: sudo bash /opt/aipackage/install.sh --tier starter"
+65 -26
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────
# Cezen AI Suite — Custom ISO Builder
# Nexus One AI — Custom ISO Builder
# Runs directly on Ubuntu 22.04 (run on the server)
#
# Usage:
@@ -20,7 +20,7 @@ OUTPUT_ISO="$SCRIPT_DIR/cezen-ai-ubuntu2204.iso"
UBUNTU_URL="https://releases.ubuntu.com/22.04.5/ubuntu-22.04.5-live-server-amd64.iso"
echo "╔══════════════════════════════════════════╗"
echo "║ Cezen AI — ISO Builder ║"
echo "║ Nexus One AI — ISO Builder ║"
echo "╚══════════════════════════════════════════╝"
echo ""
@@ -56,15 +56,10 @@ cp "$SCRIPT_DIR/user-data" "$WORK_DIR/nocloud/user-data"
cp "$SCRIPT_DIR/meta-data" "$WORK_DIR/nocloud/meta-data"
echo "✓ user-data and meta-data injected"
# Keep the installer payload on the ISO so first boot does not depend on a
# private Git server being reachable before the setup UI can start.
echo "→ Bundling Cezen AI installer payload..."
mkdir -p "$WORK_DIR/cezen-aipackage"
rsync -a --delete \
--exclude 'autoinstall/cezen-ai-ubuntu2204.iso' \
--exclude '*.iso' \
"$PACKAGE_DIR/" "$WORK_DIR/cezen-aipackage/"
echo "✓ Installer payload bundled"
# Keep this as an online installer ISO. The installed system pulls the current
# Nexus One AI package from cgit during first boot, which keeps the ISO small and
# avoids shipping stale backend/portal code inside the image.
echo "✓ Online installer mode: package will be pulled from cgit on first boot"
# ── Patch GRUB ────────────────────────────────
echo "→ Patching GRUB config..."
@@ -82,20 +77,6 @@ sed -i "s/set timeout_style=.*/set timeout_style=countdown/" "$GRUB_CFG"
sed -i '/^\s*linux.*vmlinuz/s|---|autoinstall ds=nocloud\\;s=/cdrom/nocloud/ ---|' "$GRUB_CFG"
echo "✓ GRUB patched"
# ── Refresh installer checksum manifest ─────────────────
echo "→ Refreshing md5sum.txt..."
(
cd "$WORK_DIR"
rm -f md5sum.txt
find . -type f \
! -path './md5sum.txt' \
! -path './boot.catalog' \
-print0 \
| sort -z \
| xargs -0 md5sum > md5sum.txt
)
echo "✓ md5sum.txt refreshed"
# ── Extract MBR and EFI partition from original ISO ────
echo "→ Extracting boot data from original ISO..."
MBR_TEMPLATE=$(mktemp)
@@ -119,7 +100,7 @@ dd if="$ORIGINAL_ISO" bs=512 skip="$EFI_START" count="$EFI_SIZE" \
echo "✓ EFI partition extracted (start=$EFI_START, size=$EFI_SIZE)"
# ── Repack ISO ─────────────────────────────────
echo "→ Repacking ISO (this takes ~2 minutes)..."
echo "→ Repacking ISO (pass 1)..."
xorriso -as mkisofs \
-r \
-V "Cezen_AI_Ubuntu2204" \
@@ -141,6 +122,64 @@ xorriso -as mkisofs \
-no-emul-boot \
"$WORK_DIR"
echo "→ Refreshing md5sum.txt from pass-1 ISO contents..."
FINAL_DIR=$(mktemp -d)
VERIFY_DIR=$(mktemp -d)
trap 'rm -rf "$WORK_DIR" "$MBR_TEMPLATE" "$EFI_IMG" "$FINAL_DIR" "$VERIFY_DIR"' EXIT
xorriso -osirrox on \
-indev "$OUTPUT_ISO" \
-extract / "$FINAL_DIR" >/dev/null 2>&1
chmod -R u+w "$FINAL_DIR"
(
cd "$FINAL_DIR"
rm -f md5sum.txt
find . -type f \
! -path './md5sum.txt' \
! -path './boot.catalog' \
-print0 \
| sort -z \
| xargs -0 md5sum > md5sum.txt
)
echo "✓ md5sum.txt refreshed"
echo "→ Repacking ISO (pass 2 with final manifest)..."
xorriso -as mkisofs \
-r \
-V "Cezen_AI_Ubuntu2204" \
-o "$OUTPUT_ISO" \
--grub2-mbr "$MBR_TEMPLATE" \
-partition_offset 16 \
--mbr-force-bootable \
-append_partition 2 28732ac11ff8d211ba4b00a0c93ec93b "$EFI_IMG" \
-appended_part_as_gpt \
-iso_mbr_part_type a2a0d0ebe5b9334487c068b6b72699c7 \
-c "/boot.catalog" \
-b "/boot/grub/i386-pc/eltorito.img" \
-no-emul-boot \
-boot-load-size 4 \
-boot-info-table \
--grub2-boot-info \
-eltorito-alt-boot \
-e "--interval:appended_partition_2:::" \
-no-emul-boot \
"$FINAL_DIR"
# ── Verify output ISO integrity manifest ─────────────────
echo "→ Verifying rebuilt ISO manifest..."
xorriso -osirrox on \
-indev "$OUTPUT_ISO" \
-extract / "$VERIFY_DIR" >/dev/null 2>&1
chmod -R u+w "$VERIFY_DIR"
(
cd "$VERIFY_DIR"
md5sum -c md5sum.txt >/tmp/cezen-iso-md5check.log 2>&1 || {
echo "ERROR: Rebuilt ISO failed its own md5sum.txt verification."
sed -n '1,40p' /tmp/cezen-iso-md5check.log
exit 1
}
)
echo "✓ Output ISO manifest verified"
echo ""
echo "╔══════════════════════════════════════════════════════╗"
echo "║ Done! ║"
+23 -21
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────
# Cezen AI Suite — First Boot Setup Wizard
# Nexus One AI — First Boot Setup Wizard
# Runs on first boot after OS install via systemd service.
# Uses whiptail for the TUI.
# ─────────────────────────────────────────────────────────────
@@ -8,6 +8,7 @@ set -e
AIPACKAGE_DIR="/opt/aipackage"
LOG_FILE="/var/log/cezen-setup.log"
export TERM="${TERM:-linux}"
exec > >(tee -a "$LOG_FILE") 2>&1
detect_iface() {
@@ -20,28 +21,28 @@ IFACE="${IFACE:-$(ip -o link show | awk -F': ' '$2 !~ /lo|docker|br-|veth/ {prin
# ── Colors / terminal setup ────────────────────────────────
export NEWT_COLORS='
root=,black
window=white,navy
border=white,navy
title=white,navy
button=black,cyan
actbutton=white,red
checkbox=white,navy
actcheckbox=black,cyan
entry=white,navy
label=white,navy
listbox=white,navy
actlistbox=black,cyan
textbox=white,navy
acttextbox=black,cyan
window=black,white
border=white,black
title=black,white
button=black,white
actbutton=white,blue
checkbox=black,white
actcheckbox=white,blue
entry=black,white
label=black,white
listbox=black,white
actlistbox=white,blue
textbox=black,white
acttextbox=white,blue
'
TITLE=" Cezen AI Suite — Server Setup "
TITLE=" Nexus One AI — Server Setup "
H=20
W=70
# ── Welcome ────────────────────────────────────────────────
whiptail --title "$TITLE" \
--msgbox "\nWelcome to the Cezen AI Suite installer.\n\nThis wizard will configure your network and install the AI stack.\n\nMake sure this server is connected to the internet before continuing." \
--msgbox "\nWelcome to the Nexus One AI installer.\n\nThis wizard will configure your network and install the AI stack.\n\nMake sure this server is connected to the internet before continuing." \
$H $W
# ════════════════════════════════════════════════════════════
@@ -135,10 +136,11 @@ fi
TIER=$(whiptail --title "$TITLE" \
--menu "\nStep 2 of 3: Select AI Package Tier\n\nChoose the tier that matches your hardware:" \
$H $W 3 \
"entry" "Entry — 3× NVIDIA L40S (48GB each) · Up to 20 users" \
"mid" "Mid — RTX Pro 6000 BW (96GB each) · Up to 50 users" \
"advanced" "Advanced — HGX H200 (141GB each) · 200+ users" \
$H $W 4 \
"starter" "Starter — 1× RTX 5090 / 32GB VRAM · Small team" \
"basic" "Entry — 1× NVIDIA RTX Pro 6000 (96GB) · Up to 20 users" \
"pro" "Pro — 2× RTX 5090 / RTX Pro class · Up to 100 users" \
"max" "Max — 4–8× H100/H200/A100 class · 100+ users" \
3>&1 1>&2 2>&3)
# ════════════════════════════════════════════════════════════
@@ -177,7 +179,7 @@ whiptail --title "$TITLE" \
clear
echo ""
echo "╔══════════════════════════════════════════╗"
echo "║ Cezen AI Suite — Installing... ║"
echo "║ Nexus One AI — Installing... ║"
echo "║ Check progress: journalctl -f ║"
echo "╚══════════════════════════════════════════╝"
echo ""
+11 -15
View File
@@ -85,10 +85,11 @@ autoinstall:
# mirrors instead of the custom ISO content.
- sed -i 's/^deb cdrom:/# deb cdrom:/' /target/etc/apt/sources.list || true
# Install the Cezen AI payload from the ISO first. Fall back to Git only
# when building from older media that does not contain /cdrom/cezen-aipackage.
# Pull the Nexus One AI installer from cgit. The ISO intentionally does not
# bundle the full package, keeping the image small and the installed code
# current at deployment time.
- mkdir -p /target/opt/aipackage
- cp -a /cdrom/cezen-aipackage/. /target/opt/aipackage/ || git clone https://cgit.cezentech.com/jinojose/aipackage.git /target/opt/aipackage
- git clone https://cgit.cezentech.com/jinojose/aipackage.git /target/opt/aipackage
# Deploy the console setup wizard
- mkdir -p /target/opt/cezen
@@ -104,23 +105,18 @@ autoinstall:
- |
cat > /target/etc/systemd/system/cezen-setup.service << 'EOF'
[Unit]
Description=Cezen AI Suite — Console Setup Wizard
Description=Nexus One AI — Console Setup Wizard
After=cloud-final.service cloud-init.target network-online.target
Wants=cloud-init.target network-online.target
Conflicts=getty@tty1.service
ConditionPathExists=!/opt/cezen/.setup-done
OnFailure=getty@tty1.service
[Service]
Type=idle
ExecStartPre=-/usr/bin/systemctl stop getty@tty1.service
ExecStart=/bin/bash -lc 'clear >/dev/tty1 2>/dev/null || true; exec /opt/cezen/firstboot-setup.sh'
StandardInput=tty-force
StandardOutput=tty
StandardError=tty
TTYPath=/dev/tty1
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
Type=oneshot
WorkingDirectory=/opt/cezen
ExecStart=/bin/bash -lc 'clear >/dev/tty1 2>/dev/null || true; /usr/bin/openvt -c 1 -f -w -- env TERM=linux /opt/cezen/firstboot-setup.sh'
StandardOutput=journal+console
StandardError=journal+console
Restart=no
[Install]
+137
View File
@@ -0,0 +1,137 @@
#cloud-config
# ─────────────────────────────────────────────────────────────
# Nexus One AI — Starter Tier Autoinstall
# Hardware target: compact workstation (Mini-ITX / SFF)
# GPU: 1× NVIDIA RTX 5090 (32 GB GDDR7)
# RAM: 64 GB DDR5
# Storage: 1× 2 TB NVMe SSD (single drive — simple LVM)
# Network: 2.5 GbE (single interface)
# ─────────────────────────────────────────────────────────────
autoinstall:
version: 1
# ── Locale & keyboard ──────────────────────────
locale: en_IN.UTF-8
keyboard:
layout: us
# ── Network: DHCP during install; static config applied post-install ──
network:
network:
version: 2
ethernets:
any-en:
dhcp4: true
match:
name: "en*"
any-eth:
dhcp4: true
match:
name: "eth*"
# ── Storage: single 2 TB NVMe, simple LVM ─────
# Starter workstations have one drive — no RAID needed.
storage:
layout:
name: lvm
match:
size: largest
# ── Identity ──────────────────────────────────
identity:
hostname: cezenai-starter
username: cezen
# Default password: cezen@123 (change via first-boot wizard)
password: "$6$I5VA.42G1xTeVhCv$KCLzqIKg/kbNHZyiTEMAY4FZsJMDDwoS90k6Ffb9VEwmcK.wuzlJNe3ceiEfLrzYzXEvqjYsLc7klAbeGPGab."
# ── SSH ───────────────────────────────────────
ssh:
install-server: true
allow-pw: true
# ── Base packages ─────────────────────────────
packages:
- git
- curl
- wget
- python3
- whiptail
- openssh-server
- nvme-cli # NVMe health / SMART monitoring
# ── Late commands ─────────────────────────────
late-commands:
# Expand LVM to fill the full 2 TB NVMe
- lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv || true
- resize2fs /dev/ubuntu-vg/ubuntu-lv || true
# Passwordless sudo for cezen (needed by install.sh + first-boot wizard)
- echo "cezen ALL=(ALL) NOPASSWD:ALL" > /target/etc/sudoers.d/cezen
- chmod 440 /target/etc/sudoers.d/cezen
# Replace installer netplan with simple DHCP target config.
# The first-boot wizard will switch to static if desired.
- rm -f /target/etc/netplan/50-cloud-init.yaml /target/etc/netplan/00-installer-config.yaml || true
- |
cat > /target/etc/netplan/99-cezen-dhcp.yaml << 'EOF'
network:
version: 2
ethernets:
any-en:
dhcp4: true
match:
name: "en*"
any-eth:
dhcp4: true
match:
name: "eth*"
EOF
# Disable cdrom APT source
- sed -i 's/^deb cdrom:/# deb cdrom:/' /target/etc/apt/sources.list || true
# Pull the Nexus One AI installer from cgit. The ISO intentionally does not
# bundle the full package, keeping the image small and the installed code
# current at deployment time.
- mkdir -p /target/opt/aipackage
- git clone https://cgit.cezentech.com/jinojose/aipackage.git /target/opt/aipackage
# Write tier marker — used by install.sh and the portal branding system
- mkdir -p /target/opt/cezen
- echo "starter" > /target/opt/cezen/tier
# Deploy first-boot TUI wizard
- cp /target/opt/aipackage/autoinstall/firstboot-setup.sh /target/opt/cezen/firstboot-setup.sh
- chmod +x /target/opt/cezen/firstboot-setup.sh
# Set hostname
- echo "cezenai-starter" > /target/etc/hostname
- sed -i 's/aiserver/cezenai-starter/g' /target/etc/hosts || true
# Systemd service: run first-boot wizard on tty1 once
- |
cat > /target/etc/systemd/system/cezen-setup.service << 'EOF'
[Unit]
Description=Nexus One AI — Console Setup Wizard (Starter)
After=cloud-final.service cloud-init.target network-online.target
Wants=cloud-init.target network-online.target
ConditionPathExists=!/opt/cezen/.setup-done
OnFailure=getty@tty1.service
[Service]
Type=oneshot
WorkingDirectory=/opt/cezen
ExecStart=/bin/bash -lc 'clear >/dev/tty1 2>/dev/null || true; /usr/bin/openvt -c 1 -f -w -- env TERM=linux CEZEN_TIER=starter /opt/cezen/firstboot-setup.sh'
StandardOutput=journal+console
StandardError=journal+console
Restart=no
[Install]
WantedBy=cloud-init.target
EOF
- curtin in-target -- systemctl enable ssh
- curtin in-target -- systemctl enable cezen-setup.service
user-data:
disable_root: false
+23 -18
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
"""
Cezen AI Suite — First Boot Web Setup Server
Nexus One AI — First Boot Web Setup Server
Serves on port 80. Access from any browser on the same network.
"""
import os, json, subprocess, threading, time, socket, ipaddress
@@ -123,7 +123,7 @@ HTML = r"""<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cezen AI Suite — Server Setup</title>
<title>Nexus One AI — Server Setup</title>
<style>
:root {
--navy: #1B2A4A;
@@ -317,19 +317,24 @@ HTML = r"""<!DOCTYPE html>
<h2>Select AI Package Tier</h2>
<p class="desc">Choose the tier that matches your GPU hardware.</p>
<div class="tier-grid">
<div class="tier-card" id="tier-entry" onclick="selectTier('entry')">
<div class="tier-card" id="tier-starter" onclick="selectTier('starter')">
<div class="tier-name">Starter</div>
<div class="tier-gpu">1× RTX 5090 / 32GB VRAM</div>
<div class="tier-users">Small team deployment</div>
</div>
<div class="tier-card" id="tier-basic" onclick="selectTier('basic')">
<div class="tier-name">Entry</div>
<div class="tier-gpu">3× NVIDIA L40S</div>
<div class="tier-gpu">1× NVIDIA RTX Pro 6000 (96GB)</div>
<div class="tier-users">Up to 20 concurrent users</div>
</div>
<div class="tier-card" id="tier-mid" onclick="selectTier('mid')">
<div class="tier-name">Mid</div>
<div class="tier-gpu">3× RTX Pro 6000</div>
<div class="tier-users">Up to 50 concurrent users</div>
<div class="tier-card" id="tier-pro" onclick="selectTier('pro')">
<div class="tier-name">Pro</div>
<div class="tier-gpu">2× RTX 5090 / RTX Pro class</div>
<div class="tier-users">Up to 100 concurrent users</div>
</div>
<div class="tier-card" id="tier-advanced" onclick="selectTier('advanced')">
<div class="tier-name">Advanced</div>
<div class="tier-gpu">8× HGX H200</div>
<div class="tier-card" id="tier-max" onclick="selectTier('max')">
<div class="tier-name">Max</div>
<div class="tier-gpu">4–8× H100/H200/A100 class</div>
<div class="tier-users">200+ concurrent users</div>
</div>
</div>
@@ -369,7 +374,7 @@ HTML = r"""<!DOCTYPE html>
<div class="progress-wrap" id="progress-wrap">
<div class="card">
<h2>Installing Cezen AI Suite...</h2>
<h2>Installing Nexus One AI...</h2>
<div class="progress-bar-bg"><div class="progress-bar" id="progress-bar"></div></div>
<p id="progress-label" style="font-size:13px;color:var(--muted);margin-bottom:12px">Starting...</p>
<div class="log-box" id="log-box"></div>
@@ -379,7 +384,7 @@ HTML = r"""<!DOCTYPE html>
<div id="done-screen" class="hidden">
<div class="done-icon">✅</div>
<h2>Installation Complete!</h2>
<p>Your Cezen AI Suite is ready.</p>
<p>Your Nexus One AI is ready.</p>
<div class="services card" style="margin-top:24px;text-align:left">
<div class="summary-row"><span class="key">Open WebUI</span><span class="val badge">:3001</span></div>
<div class="summary-row"><span class="key">JupyterLab</span><span class="val badge">:8888</span></div>
@@ -400,7 +405,7 @@ HTML = r"""<!DOCTYPE html>
<script>
// ── State ──────────────────────────────────────────────────
let netMode = 'dhcp';
let selectedTier = 'entry';
let selectedTier = 'basic';
let tools = {
ollama: { name: 'Ollama + Open WebUI', desc: 'LLM inference & chat', icon: '🤖', on: true },
jupyterlab: { name: 'JupyterLab', desc: 'Notebook environment', icon: '📓', on: true },
@@ -418,7 +423,7 @@ window.onload = () => {
document.getElementById('current-ip').textContent = d.ip || 'unknown';
});
renderTools();
selectTier('entry');
selectTier('basic');
};
// ── Navigation ─────────────────────────────────────────────
@@ -467,7 +472,7 @@ function applyStaticIP() {
// ── Tier ───────────────────────────────────────────────────
function selectTier(t) {
selectedTier = t;
['entry','mid','advanced'].forEach(x =>
['starter','basic','pro','max'].forEach(x =>
document.getElementById('tier-'+x).classList.toggle('selected', x===t));
}
@@ -707,7 +712,7 @@ class Handler(BaseHTTPRequestHandler):
elif path == "/api/install":
global install_proc
tier = body.get("tier", "entry")
tier = body.get("tier", "basic")
skip = body.get("skip_tools", [])
if not install_status["running"]:
t = threading.Thread(target=run_install, args=(tier, skip), daemon=True)
@@ -752,7 +757,7 @@ def show_console_banner(ip):
try:
with open("/etc/issue", "w") as f:
f.write(f"Ubuntu 22.04.5 LTS \\n \\l\n\n")
f.write(f" \033[1;36mCezen AI Suite Setup:\033[0m http://{ip} | http://cezenai.local\n\n")
f.write(f" \033[1;36mNexus One AI Setup:\033[0m http://{ip} | http://cezenai.local\n\n")
except Exception:
pass