#Requires -Version 5.1 <# .SYNOPSIS NexusOS installer for Windows. .DESCRIPTION Installs WSL2 + Ubuntu if needed, copies NexusOS into WSL, and runs the bootstrap to set up Python, Node.js, Ollama, and a Windows Terminal profile. Run from the nexus-core directory: Right-click install-windows.ps1 -> "Run with PowerShell" Requires Windows 10 Build 19041+ or Windows 11. #> param( [string]$Distro = "Ubuntu" ) Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" $RepoRoot = $PSScriptRoot # ── Helpers ─────────────────────────────────────────────────────────────────── function Write-Step { param([string]$Msg) Write-Host "`n==> $Msg" -ForegroundColor Cyan } function Write-OK { param([string]$Msg) Write-Host " ok: $Msg" -ForegroundColor Green } function Write-Warn { param([string]$Msg) Write-Host " warn: $Msg" -ForegroundColor Yellow } function Write-Fail { param([string]$Msg) Write-Host "`n ERROR: $Msg`n" -ForegroundColor Red; Read-Host "Press Enter to exit"; exit 1 } function Pause-And-Exit { param([string]$Msg) Write-Host "" Write-Host $Msg -ForegroundColor Yellow Read-Host "Press Enter to exit" exit 0 } # ── Self-elevate to Administrator ───────────────────────────────────────────── $IsAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole( [Security.Principal.WindowsBuiltInRole]::Administrator) if (-not $IsAdmin) { Write-Host "Requesting administrator privileges..." -ForegroundColor Yellow $PsArgs = "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`" -Distro `"$Distro`"" Start-Process powershell -ArgumentList $PsArgs -Verb RunAs exit } Write-Host "" Write-Host " NexusOS Installer for Windows" -ForegroundColor White Write-Host " ════════════════════════════" -ForegroundColor DarkGray # ── Windows version check ───────────────────────────────────────────────────── Write-Step "Checking Windows version" $Build = [System.Environment]::OSVersion.Version.Build if ($Build -lt 19041) { Write-Fail "WSL2 requires Windows 10 Build 19041 or later (you have $Build). Please update Windows first." } Write-OK "Windows Build $Build — OK" # ── WSL2 check / install ────────────────────────────────────────────────────── Write-Step "Checking WSL2" $WslExe = Get-Command wsl -ErrorAction SilentlyContinue if (-not $WslExe) { Write-Warn "WSL not found — installing WSL2 + $Distro" wsl --install -d $Distro | Out-Host Pause-And-Exit "WSL has been installed. Please RESTART your computer, then run this installer again." } # Upgrade any WSL1 distros to WSL2 silently wsl --set-default-version 2 2>&1 | Out-Null if ($LASTEXITCODE -ne 0) { Write-Fail "Could not set WSL2 as the default version. Enable the WSL2 feature and reboot, then retry." } # Check if our target distro is registered $InstalledDistros = (wsl --list --quiet 2>&1) -split "`n" | ForEach-Object { $_.Trim() -replace '\x00', '' } | Where-Object { $_ -ne "" } if ($InstalledDistros -notcontains $Distro) { Write-Warn "$Distro not found — installing" wsl --install -d $Distro | Out-Host Pause-And-Exit "$Distro is being set up. Create a Unix username/password when prompted, then run this installer again." } # Ensure the distro runs as WSL2 wsl --set-version $Distro 2 2>&1 | Out-Null if ($LASTEXITCODE -ne 0) { Write-Fail "Could not convert $Distro to WSL2. Check that virtualization is enabled and retry." } wsl --set-default $Distro 2>&1 | Out-Null if ($LASTEXITCODE -ne 0) { Write-Fail "Could not set $Distro as the default WSL distro." } Write-OK "$Distro is ready (WSL2)" # ── Copy repo into WSL ──────────────────────────────────────────────────────── Write-Step "Copying repo into WSL" # Resolve the Windows path to a WSL path $WslSrcRaw = $RepoRoot -replace '\\', '/' $WslSrcPath = (wsl -- wslpath -u "$WslSrcRaw" 2>&1 | Out-String).Trim() if (-not $WslSrcPath) { Write-Fail "Could not convert repo path to WSL path. Is the repo on a Windows drive?" } $WslUser = (wsl -- bash -c "echo \$USER" 2>&1 | Out-String).Trim() if (-not $WslUser) { Write-Fail "Could not determine WSL username." } $WslDest = "/home/$WslUser/nexus-core" Write-Host " Source: $WslSrcPath" Write-Host " Dest: $WslDest" # rsync if available, otherwise cp $HasRsync = (wsl -- bash -c "command -v rsync && echo yes || echo no" 2>&1 | Out-String).Trim() if ($HasRsync -eq "yes") { wsl -- bash -c @" rsync -a --delete \ --exclude='.git' \ --exclude='Promethean/' \ --exclude='assets/themes/NexusOS-icons/' \ --exclude='node_modules/' \ --exclude='runtime/' \ --exclude='__pycache__/' \ --exclude='*.pyc' \ '$WslSrcPath/' '$WslDest/' "@ } else { wsl -- bash -c "mkdir -p '$WslDest' && cp -r '$WslSrcPath/.' '$WslDest/'" } Write-OK "Repo at $WslDest" # ── Run WSL bootstrap ───────────────────────────────────────────────────────── Write-Step "Running bootstrap inside WSL (this takes a few minutes)" Write-Host " You may be prompted for your WSL sudo password." -ForegroundColor DarkGray Write-Host "" wsl -- bash -c "chmod +x '$WslDest/bin/wsl-bootstrap.sh' && '$WslDest/bin/wsl-bootstrap.sh'" if ($LASTEXITCODE -ne 0) { Write-Fail "NexusOS bootstrap failed inside WSL. Review the error above and retry the installer." } # ── Done ────────────────────────────────────────────────────────────────────── Write-Host "" Write-Host " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -ForegroundColor Green Write-Host " NexusOS is installed!" -ForegroundColor Green Write-Host "" Write-Host " To launch: open the NexusOS shortcut on your desktop" -ForegroundColor White Write-Host " or open Windows Terminal -> NexusOS profile" -ForegroundColor White Write-Host "" Write-Host " Frontend: http://localhost:5173" -ForegroundColor White Write-Host " Backend: http://localhost:8000" -ForegroundColor White Write-Host " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -ForegroundColor Green Write-Host "" Read-Host "Press Enter to close"