Files
NexusOS/install-windows.ps1

165 lines
7.1 KiB
PowerShell
Executable File

#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"