From 5d9cec4fe8c6da99308ef3d6698a2b4640ac1522 Mon Sep 17 00:00:00 2001 From: Jino Jose Date: Tue, 23 Jun 2026 16:11:12 +0530 Subject: [PATCH] Add autoinstall ISO builder for Cezen AI Suite --- autoinstall/build-iso.sh | 144 +++++++++++++++++++++++++++++++++++++++ autoinstall/meta-data | 2 + autoinstall/user-data | 91 +++++++++++++++++++++++++ 3 files changed, 237 insertions(+) create mode 100644 autoinstall/build-iso.sh create mode 100644 autoinstall/meta-data create mode 100644 autoinstall/user-data diff --git a/autoinstall/build-iso.sh b/autoinstall/build-iso.sh new file mode 100644 index 0000000..f79ee56 --- /dev/null +++ b/autoinstall/build-iso.sh @@ -0,0 +1,144 @@ +#!/usr/bin/env bash +# ───────────────────────────────────────────────────────────── +# Cezen AI Suite — Custom ISO Builder +# Runs on macOS using Docker. Produces a bootable USB image. +# +# Usage: bash autoinstall/build-iso.sh +# Output: autoinstall/cezen-ai-ubuntu2204.iso +# +# Requirements: +# - Docker Desktop running on your MacBook +# - ~6 GB free disk space (ISO download + work) +# ───────────────────────────────────────────────────────────── +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +OUTPUT_ISO="$SCRIPT_DIR/cezen-ai-ubuntu2204.iso" +UBUNTU_ISO_URL="https://releases.ubuntu.com/22.04.5/ubuntu-22.04.5-live-server-amd64.iso" + +echo "╔══════════════════════════════════════════╗" +echo "║ Cezen AI — ISO Builder ║" +echo "╚══════════════════════════════════════════╝" +echo "" + +# Check Docker is running +if ! docker info &>/dev/null; then + echo "ERROR: Docker is not running. Start Docker Desktop and try again." + exit 1 +fi +echo "✓ Docker is running" + +# Check autoinstall files exist +if [ ! -f "$SCRIPT_DIR/user-data" ] || [ ! -f "$SCRIPT_DIR/meta-data" ]; then + echo "ERROR: user-data or meta-data not found in $SCRIPT_DIR" + exit 1 +fi +echo "✓ Autoinstall files found" + +echo "" +echo "→ Building ISO inside Docker container (Ubuntu 22.04)..." +echo " This will take 5–15 minutes depending on internet speed." +echo "" + +docker run --rm \ + -v "$SCRIPT_DIR:/autoinstall" \ + -v "$REPO_ROOT:/repo" \ + ubuntu:22.04 \ + bash -c ' +set -e + +# Install tools +export DEBIAN_FRONTEND=noninteractive +apt-get update -qq +apt-get install -y -qq xorriso wget isolinux rsync + +WORK_DIR="/tmp/iso-work" +ORIGINAL_ISO="/tmp/ubuntu-22.04.5-live-server-amd64.iso" +UBUNTU_URL="https://releases.ubuntu.com/22.04.5/ubuntu-22.04.5-live-server-amd64.iso" + +# Download Ubuntu ISO if not already cached +if [ ! -f "$ORIGINAL_ISO" ]; then + echo "→ Downloading Ubuntu 22.04.5 Server ISO (~1.8 GB)..." + wget -q --show-progress -O "$ORIGINAL_ISO" "$UBUNTU_URL" +fi +echo "✓ Ubuntu ISO ready" + +# Extract ISO contents +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 "✓ ISO extracted" + +# Inject autoinstall files +echo "→ Injecting autoinstall config..." +mkdir -p "$WORK_DIR/nocloud" +cp /autoinstall/user-data "$WORK_DIR/nocloud/user-data" +cp /autoinstall/meta-data "$WORK_DIR/nocloud/meta-data" + +# Modify GRUB to auto-select install with autoinstall +GRUB_CFG="$WORK_DIR/boot/grub/grub.cfg" + +# Backup original +cp "$GRUB_CFG" "$GRUB_CFG.orig" + +# Set default to first entry and zero timeout +sed -i "s/set timeout=.*/set timeout=5/" "$GRUB_CFG" +sed -i "s/set timeout_style=.*/set timeout_style=countdown/" "$GRUB_CFG" + +# Add autoinstall + nocloud parameters to the first linux line +# This patches the "Install Ubuntu Server" entry +sed -i "/^\s*linux.*vmlinuz/s/$/ autoinstall quiet ds=nocloud;s=\/cdrom\/nocloud\//" "$GRUB_CFG" + +echo "✓ GRUB config patched" + +# Get original ISO metadata for repacking +MBR_TEMPLATE=$(mktemp) +dd if="$ORIGINAL_ISO" bs=1 count=432 of="$MBR_TEMPLATE" 2>/dev/null + +# Get EFI partition info +EFI_START=$(fdisk -l "$ORIGINAL_ISO" 2>/dev/null | grep "EFI" | awk "{print \$2}") +EFI_SIZE=$(fdisk -l "$ORIGINAL_ISO" 2>/dev/null | grep "EFI" | awk "{print \$4}") + +echo "→ Repacking ISO..." +xorriso -as mkisofs \ + -r \ + -V "Cezen_AI_Ubuntu2204" \ + -o /autoinstall/cezen-ai-ubuntu2204.iso \ + --grub2-mbr "$MBR_TEMPLATE" \ + -partition_offset 16 \ + --mbr-force-bootable \ + -append_partition 2 28732ac11ff8d211ba4b00a0c93ec93b "$WORK_DIR/boot/grub/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_start_${EFI_START}s_size_${EFI_SIZE}s:all::" \ + -no-emul-boot \ + -boot-load-size 4 \ + "$WORK_DIR" 2>/dev/null + +echo "✓ ISO built successfully" +ls -lh /autoinstall/cezen-ai-ubuntu2204.iso +' + +echo "" +echo "╔══════════════════════════════════════════════════════╗" +echo "║ ISO built: autoinstall/cezen-ai-ubuntu2204.iso ║" +echo "║ ║" +echo "║ Flash to USB: ║" +echo "║ sudo dd if=autoinstall/cezen-ai-ubuntu2204.iso \ ║" +echo "║ of=/dev/diskX bs=4m status=progress ║" +echo "║ (replace /dev/diskX with your USB drive) ║" +echo "╚══════════════════════════════════════════════════════╝" +echo "" +echo "→ To find your USB drive: diskutil list" diff --git a/autoinstall/meta-data b/autoinstall/meta-data new file mode 100644 index 0000000..ec4d5f8 --- /dev/null +++ b/autoinstall/meta-data @@ -0,0 +1,2 @@ +instance-id: cezen-aiserver +local-hostname: aiserver diff --git a/autoinstall/user-data b/autoinstall/user-data new file mode 100644 index 0000000..c56cb69 --- /dev/null +++ b/autoinstall/user-data @@ -0,0 +1,91 @@ +#cloud-config +autoinstall: + version: 1 + + # ── Locale & keyboard ────────────────────────── + locale: en_IN.UTF-8 + keyboard: + layout: us + + # ── Network: DHCP on first ethernet ─────────── + network: + network: + version: 2 + ethernets: + any-en: + dhcp4: true + match: + name: "en*" + any-eth: + dhcp4: true + match: + name: "eth*" + + # ── Storage: LVM on largest disk ────────────── + storage: + layout: + name: lvm + match: + size: largest + + # ── Identity: cezen user ────────────────────── + identity: + hostname: aiserver + username: cezen + # Password: Cezen@2024! (SHA-512 hash below) + password: "$6$rounds=4096$cezentech$9pHVUFCvB7mHrblqn0qXJaFWxMkmepNM4T8Q5Fx8piVXuGDq.MLk/RH4nRMWtluLMpPXaZQAGFOD4xtjW1wC1" + + # ── SSH ─────────────────────────────────────── + ssh: + install-server: true + allow-pw: true + + # ── Packages installed during setup ─────────── + packages: + - git + - curl + - wget + + # ── Late commands: run after OS install ─────── + # These run with target mounted at /target + late-commands: + # Clone the Cezen AI installer + - git clone https://cgit.cezentech.com/jinojose/aipackage.git /target/opt/aipackage + + # Set ownership + - curtin in-target -- chown -R cezen:cezen /opt/aipackage + + # Create a firstboot systemd service that runs install.sh on first boot + - | + cat > /target/etc/systemd/system/cezen-firstboot.service << 'SVCEOF' + [Unit] + Description=Cezen AI Suite First Boot Installer + After=network-online.target + Wants=network-online.target + ConditionPathExists=!/opt/cezen/.installed + + [Service] + Type=oneshot + ExecStart=/bin/bash /opt/aipackage/install.sh + ExecStartPost=/bin/touch /opt/cezen/.installed + RemainAfterExit=yes + StandardOutput=journal+console + StandardError=journal+console + + [Install] + WantedBy=multi-user.target + SVCEOF + + # Enable the firstboot service + - curtin in-target -- systemctl enable cezen-firstboot.service + + # Allow cezen user to run sudo without password (needed for install.sh) + - echo "cezen ALL=(ALL) NOPASSWD:ALL" > /target/etc/sudoers.d/cezen + - chmod 440 /target/etc/sudoers.d/cezen + + # ── Skip confirmations ──────────────────────── + user-data: + disable_root: false + + # Confirm destructive action without prompting + confirm-bugs: false