Unattended Installation System

Complete guide to automated OS installation - Windows unattend.xml, Ubuntu cloud-init, RedHat kickstart

Unattended Installation System

Introduction

Infinibay automates OS installation by generating custom ISOs with embedded autoinstall configurations. The system extracts installation media, injects config files (Windows unattend.xml, Ubuntu cloud-init, RedHat kickstart), and creates bootable ISOs.

Base class UnattendedManagerBase provides common ISO manipulation logic. OS-specific implementations handle Windows 10/11, Ubuntu, Fedora, and RedHat.

Unattended Installation Architecture

Base Class

File: backend/app/services/unattendedManagerBase.ts

Abstract base class with template method generateNewImage() that orchestrates ISO extraction, config injection, ISO creation, and cleanup. Subclasses implement generateConfig() for OS-specific configuration.

OS-Specific Implementations

  • UnattendedWindowsManager: Windows 10/11 with unattend.xml
  • UnattendedUbuntuManager: Ubuntu with cloud-init YAML
  • UnattendedRedHatManager: Fedora/RedHat with kickstart

Manager Selection

File: backend/app/utils/VirtManager/createMachineService.ts

const osManagers: Record<string, () => UnattendedManagerBase> = {
  'windows10': () => new UnattendedWindowsManager(10, username, password, productKey, applications, machine.id),
  'windows11': () => new UnattendedWindowsManager(11, username, password, productKey, applications, machine.id),
  'ubuntu': () => new UnattendedUbuntuManager(username, password, applications, machine.id),
  'fedora': () => new UnattendedRedHatManager(username, password, applications, machine.id),
  'redhat': () => new UnattendedRedHatManager(username, password, applications, machine.id)
};

Factory pattern maps machine.os to manager constructor. Throws for unsupported OS types.

ISO Generation Process

generateNewImage Method

File: backend/app/services/unattendedManagerBase.ts

Flow: validate ISO path → generate OS-specific config → create temp directory with random filename → extract original ISO with 7z → inject config file to root → create new bootable ISO (xorriso/genisoimage) → cleanup extracted files.

On error, cleans up extracted directory and re-throws.

ISO Extraction

extractISO Method

Extracts ISO to short-lived workspace /tmp/extracted_iso_<timestamp> using 7z x <isoPath> -o<extractDir>. This temporary extraction directory is deleted after ISO creation; the resulting ISO is written to ${INFINIBAY_ISO_TEMP_DIR}.

Requirements: p7zip-full installed, sufficient /tmp space (5-10GB for Windows ISOs), write access to /tmp.

Config File Injection

addAutoinstallConfigFile Method

Note: Code currently has typo addAutonistallConfigFile, should be addAutoinstallConfigFile.

Writes config string to ${extractDir}/${fileName}.

File placement (root of extracted ISO):

  • Windows: autounattend.xml (XML with windowsPE, specialize, oobeSystem passes)
  • Ubuntu: user-data, meta-data (YAML with autoinstall, identity, ssh, packages)
  • RedHat: ks.cfg (plain text with install, lang, network, user commands)

ISO Creation

createISO Method

createISO() is abstract in backend/app/services/unattendedManagerBase.ts and implemented by OS-specific subclasses.

Windows (createISO() in backend/app/services/unattendedWindowsManager.ts): Uses xorriso with ISO level 3, BIOS boot (boot/etfsboot.com), UEFI boot (efi/microsoft/boot/efisys.bin).

Linux (Ubuntu/RedHat): Uses genisoimage with isolinux boot loader, Rock Ridge, and Joliet extensions.

Windows Unattended Installation

UnattendedWindowsManager Overview

File: backend/app/services/unattendedWindowsManager.ts

Generates unattend.xml for Windows 10/11 Setup. Configures language, user account, product key, drivers, applications, system settings.

Constructor

Takes version (10/11), username, password, product key, applications, vmId. Detects language from ISO filename or host locale (fallback: en-US). Sets ISO path from WINDOWS_10_ISO_PATH or WINDOWS_11_ISO_PATH env var.

Language Detection

Parses ISO filename for language codes (e.g., Win11_English_x64.isoen-US). Falls back to host LANG/LC_ALL env vars.

Unattend.xml Structure

Organized into Windows Setup passes:

  • windowsPE: Locale settings, GPT disk partitioning (EFI 100MB, MSR 128MB, Windows partition), product key, image selection (Windows 10/11 Pro)
  • offlineServicing: Empty (no offline operations)
  • generalize: Empty (not used)
  • specialize: Computer name, product key, timezone, skip OOBE screens
  • oobeSystem: Create user account (Administrators group), auto-logon (first boot), hide OOBE screens, first logon commands

First Logon Commands

Commands execute after first login to complete setup. First-logon actions (security settings, system tweaks) are configurable per deployment policy; the list below reflects current defaults.

Command Categories

generateFirstLogonCommands method:

  • System tweaks: Disable Defender, Windows Update, UAC; set High Performance power plan
  • Password settings: Set password to never expire, disable complexity requirements
  • VirtIO drivers: Mount virtio-win ISO, install NetKVM/viostor/Balloon/vioserial drivers, install SPICE guest tools
  • Setup: Create C:\infinibay\logs, wait for network (ping gateway, 5min timeout)
  • InfiniService: Download from backend with retry logic (5 attempts), verify download, install silently (/S), configure as auto-start service
  • Applications: For each app: download from URL, parse installCommand JSON, replace placeholders ({installerPath}, {username}, {password}), execute silently, log to C:\infinibay\logs\app-install.log

Command Encoding

Base64 encoding for complex PowerShell (prevents XML escaping), simple encoding for basic commands, logging wrapper redirects output.

Ubuntu Unattended Installation

UnattendedUbuntuManager Overview

Uses cloud-init for automated configuration. Generates user-data (autoinstall config) and meta-data (instance ID) YAML files.

Configuration

user-data sections: autoinstall (version, identity, storage, network), identity (username, password hash, hostname), ssh (install server, allow password), packages (qemu-guest-agent, spice-vdagent), runcmd (post-install commands)

meta-data: instance-id, local-hostname

Post-install: Download/install InfiniService deb from backend, install applications from list

RedHat/Fedora Unattended Installation

UnattendedRedHatManager Overview

Uses kickstart (Anaconda installer scripting). Generates ks.cfg plain text file.

Configuration

Sections: install (text, cdrom), lang (en_US.UTF-8, keyboard), network (DHCP), rootpw, user (with wheel group), timezone, bootloader (GRUB), clearpart, autopart (LVM), %packages (minimal-environment, qemu-guest-agent, spice-vdagent), %post (post-install script)

Post-install: Download/install InfiniService rpm from backend, install applications from list

InfiniService Deployment

Downloaded from backend with retry logic (5 attempts, 10s delay), verified (file exists, size > 0). Installed silently (/S for NSIS), configured as auto-start Windows service, started immediately.

Service provides bidirectional communication for metrics, commands, configuration.

Application Installation

For each app: download installer from downloadUrl, parse installCommand JSON (command, parameters), replace placeholders ({installerPath}, {username}, {password}), execute silently, log results.

On error, logs to C:\infinibay\logs\app-install.log and continues with next app.

Temporary ISO Management

Location: Generated ISOs stored in ${INFINIBAY_BASE_DIR}/iso/temp (configurable via INFINIBAY_ISO_TEMP_DIR). Distinct from the short-lived extraction workspace in /tmp/.

Lifecycle: Created during VM creation, attached as CDROM, deleted on rollback. Currently remains after successful install.

Cleanup: Manual (find ... -mtime +7 -delete) or automated cron job recommended.

Error Handling and Debugging

Logging

All operations logged via Debugger class. Windows first logon commands log to C:\infinibay\logs.

Common Issues

  • ISO extraction fails: 7z not installed, corrupted ISO, no /tmp space
  • ISO creation fails: xorriso/genisoimage missing, invalid boot files
  • Installation hangs: Invalid unattend.xml, missing drivers, network timeout

Debugging

Check Windows Setup logs: C:\Windows\Panther\unattend.xml, setupact.log, setuperr.log. Check first logon logs: C:\infinibay\logs\setup.log.

Environment Variables

Variable Description Default
INFINIBAY_BASE_DIR Base directory for all data '/opt/infinibay'
INFINIBAY_ISO_TEMP_DIR Temporary ISO directory ${INFINIBAY_BASE_DIR}/iso/temp
INFINIBAY_ISO_DIR Permanent ISO directory ${INFINIBAY_BASE_DIR}/iso
WINDOWS_10_ISO_PATH Windows 10 ISO path undefined (must be set)
WINDOWS_11_ISO_PATH Windows 11 ISO path undefined (must be set)

Mermaid Diagrams

Unattended Installation Flow

sequenceDiagram
    participant CreateMachineService
    participant UnattendedManager
    participant FileSystem
    participant VM

    CreateMachineService->>UnattendedManager: Create manager for OS
    CreateMachineService->>UnattendedManager: generateNewImage()
    UnattendedManager->>UnattendedManager: Validate ISO path
    UnattendedManager->>UnattendedManager: Generate OS-specific config<br/>(XML/YAML/kickstart)
    UnattendedManager->>FileSystem: Extract ISO with 7z
    FileSystem-->>UnattendedManager: Extract directory path
    UnattendedManager->>FileSystem: Write config file to<br/>extract directory root
    UnattendedManager->>FileSystem: Create new ISO with<br/>xorriso/genisoimage
    FileSystem-->>UnattendedManager: New ISO path
    UnattendedManager->>FileSystem: Cleanup extracted directory
    UnattendedManager-->>CreateMachineService: Return new ISO path
    CreateMachineService->>XMLGenerator: Add CDROM with new ISO
    CreateMachineService->>Libvirt: Define and start VM
    VM->>VM: Boot from ISO
    VM->>VM: Windows Setup reads<br/>autounattend.xml
    VM->>VM: Automated installation<br/>(partition, install, configure)
    VM->>VM: First logon commands execute
    VM->>VM: Install VirtIO drivers
    VM->>Backend: Download InfiniService
    VM->>VM: Install InfiniService as service
    VM->>VM: Install applications
    VM->>VM: Installation complete,<br/>ready for use

ISO Generation Process

flowchart TD
    Start([Start: generateNewImage]) --> ValidateISO{ISO path valid?}
    ValidateISO -->|No| ThrowError[Throw error:<br/>ISO path not set]
    ValidateISO -->|Yes| GenConfig[Generate autoinstall config<br/>OS-specific method]
    GenConfig --> SetupPaths[Setup temp directory<br/>and random filename]
    SetupPaths --> ExtractISO[Extract original ISO<br/>with 7z]
    ExtractISO --> WriteConfig[Write config file to<br/>extracted directory root]
    WriteConfig --> CreateISO[Create new ISO<br/>xorriso/genisoimage]
    CreateISO --> VerifyISO{ISO created<br/>successfully?}
    VerifyISO -->|No| CleanupFail[Cleanup extracted directory]
    CleanupFail --> ThrowError
    VerifyISO -->|Yes| CleanupSuccess[Cleanup extracted directory]
    CleanupSuccess --> ReturnPath[Return new ISO path]
    ReturnPath --> End([End: Success])
    ThrowError --> End2([End: Error])

Windows First Logon Commands

flowchart TD
    FirstLogon([First Logon]) --> DisableDefender[Disable Windows Defender]
    DisableDefender --> DisableUpdate[Disable Windows Update]
    DisableUpdate --> DisableUAC[Disable UAC]
    DisableUAC --> SetPowerPlan[Set High Performance<br/>power plan]
    SetPowerPlan --> SetPassword[Set password to<br/>never expire]
    SetPassword --> MountVirtIO[Mount VirtIO driver ISO]
    MountVirtIO --> InstallNetwork[Install VirtIO<br/>network driver]
    InstallNetwork --> InstallStorage[Install VirtIO<br/>storage driver]
    InstallStorage --> InstallBalloon[Install VirtIO<br/>balloon driver]
    InstallBalloon --> InstallSerial[Install VirtIO<br/>serial driver]
    InstallSerial --> InstallSPICE[Install SPICE<br/>guest tools]
    InstallSPICE --> UnmountVirtIO[Unmount VirtIO ISO]
    UnmountVirtIO --> CreateLogDir[Create log directory<br/>C:\infinibay\logs]
    CreateLogDir --> WaitNetwork[Wait for network<br/>connectivity]
    WaitNetwork --> DownloadInfini[Download InfiniService<br/>installer]
    DownloadInfini --> VerifyDownload{Download<br/>successful?}
    VerifyDownload -->|No| RetryDownload[Retry download<br/>5 attempts]
    RetryDownload --> DownloadInfini
    VerifyDownload -->|Yes| InstallInfini[Install InfiniService]
    InstallInfini --> StartInfini[Start InfiniService]
    StartInfini --> InstallApps[For each application:<br/>Download and install]
    InstallApps --> LogResults[Log results to<br/>app-install.log]
    LogResults --> Complete([Installation complete])