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.iso → en-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
installCommandJSON, replace placeholders ({installerPath},{username},{password}), execute silently, log toC:\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])