diff --git a/README.md b/README.md index 841121c..b1714c3 100644 --- a/README.md +++ b/README.md @@ -168,13 +168,17 @@ from the shared Windows 11 QCOW2 base image: It creates a persistent 64G disk at `.vm/windows11/disk.qcow2`, automatically partitions it, completes OOBE, creates the local administrator `guofang` with the initial password `wang`, and enables Remote Desktop on -`localhost:3389`. During the first login it also installs and enables the -Windows OpenSSH Server on `localhost:2222` and silently installs the VirtIO -Windows guest tools. It also installs the host's configured SSH public key for -passwordless administrator login. The installer includes the VirtIO drivers, SPICE vdagent, -and QEMU Guest Agent. Connect with `ssh guofang@localhost -p 2222`. The launcher -exposes the vdagent channel for host/guest clipboard integration and the QEMU Guest Agent at -`.vm/windows11/qemu-guest-agent.sock`. Change the password after first login. +`localhost:3389`. During the first login it also silently installs the VirtIO +drivers (the guest tools installer on amd64, the Arm64 driver packages from the +VirtIO ISO with `pnputil` on arm64), without which the guest has no network on +arm64. The installer includes the VirtIO drivers, SPICE vdagent, and QEMU Guest +Agent. The launcher exposes the vdagent channel for host/guest clipboard +integration and the QEMU Guest Agent at `.vm/windows11/qemu-guest-agent.sock`. +Change the password after first login. The OpenSSH Server is downloaded through +Windows Update, which can be slow, so it is not installed automatically: run +`05-Install-OpenSSH-Admin.bat` from the `Installers` folder on the desktop as +administrator, then connect with `ssh guofang@localhost -p 2222`; it also installs +the host's configured SSH public key for passwordless administrator login. The Windows VM hardware (8G memory, 8 CPUs, system disk, devices) is defined in `qemu/windows11.ini`, with the accelerators and machine type in `qemu/windows11--.ini`; the launcher renders the former to diff --git a/seediso/windows11/05-Install-OpenSSH-Admin.bat b/seediso/windows11/05-Install-OpenSSH-Admin.bat new file mode 100644 index 0000000..c4c99ca --- /dev/null +++ b/seediso/windows11/05-Install-OpenSSH-Admin.bat @@ -0,0 +1,50 @@ +@echo off +setlocal +title Install OpenSSH Server + +fltmc >nul 2>&1 +if errorlevel 1 ( + echo Please right-click this file and choose "Run as administrator". + pause + exit /b 1 +) + +rem The capability is downloaded through Windows Update, which can be slow. +echo Installing the OpenSSH Server Windows capability... +dism.exe /Online /Add-Capability /CapabilityName:OpenSSH.Server~~~~0.0.1.0 +set "RC=%ERRORLEVEL%" +if not "%RC%"=="0" if not "%RC%"=="3010" ( + echo dism exited with code %RC%. + pause + exit /b %RC% +) + +echo Starting the sshd service... +sc.exe config sshd start= auto +net.exe start sshd >nul 2>&1 +sc.exe query sshd | find "RUNNING" >nul +if errorlevel 1 ( + echo The sshd service is not running. + pause + exit /b 1 +) + +netsh.exe advfirewall firewall show rule name="OpenSSH-Server-In-TCP" >nul 2>&1 +if errorlevel 1 ( + netsh.exe advfirewall firewall add rule name="OpenSSH-Server-In-TCP" ^ + dir=in action=allow protocol=TCP localport=22 profile=private,public +) + +echo Installing the administrator authorized key... +set "KEYFILE=%ProgramData%\ssh\administrators_authorized_keys" +> "%KEYFILE%" echo ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCwsF2ZDSHDaXM9BdDq3Vxkp6T+DJEakKaVZQJUEHexS34mbrxYAxmGBUPCrddfE01dS31kGS4XHVBa+wGUYodY+nPwnrfD1Q4phKVSzXr65K1Y/sCcjSiANBPWpv2Xd7IMOfLlrdLtmf5QcKWroIqO2LaIDGECwzUUHrfprgeaF9N0FGcmrgbmm23JUk+f6guRQ4br88L4rWIWEBvL9bTdwErNkdfsYE2F/U8aIFpMcVy2eJIOgy8ZjZvkGdm4r730YkTDL1VmAjiHH3/m2R1EOvwLzFhyWKoa4ULk/IQW+8iNnG42QEcaWRM+hMwlVdnNhPJP6WzS+fAEbibD3zM0q2X/4ex+cXRNOCd2/0KhnD2+3p1BM5QeFTzDappkk8W2meQkDE3hvTjtIQCzygFO6LNWtEEa7BTvvlMqF3CZWh88J9XiP750SjESe3Ge5o9A0T2hcJa+KZ1LxVEmNt4nD6E/OD4EymoaLIJZ1fH5ksSFjHzJ+mJouSVjc/H/VSE= guofang@GUOFANG-OFFICE +icacls.exe "%KEYFILE%" /inheritance:r /grant "*S-1-5-32-544:F" /grant "*S-1-5-18:F" >nul +if errorlevel 1 ( + echo icacls exited with code %ERRORLEVEL%. + pause + exit /b 1 +) + +echo Done. SSH is available on port 22 of this machine. +pause +exit /b 0 diff --git a/seediso/windows11/Configure-Windows.ps1 b/seediso/windows11/Configure-Windows.ps1 index 72ac0fc..bc37055 100644 --- a/seediso/windows11/Configure-Windows.ps1 +++ b/seediso/windows11/Configure-Windows.ps1 @@ -34,7 +34,49 @@ if (-not (Test-Administrator)) { exit $elevated.ExitCode } +# The guest tools installer is an x86 program and the VirtIO ISO has no Arm64 +# package for it, so on Arm64 Windows the Arm64 drivers are installed from their +# folders on the ISO instead. NetKVM is the network driver; without it the guest +# has no network. +function Install-VirtIOArm64Drivers { + $roots = (Get-PSDrive -PSProvider FileSystem).Root + $drivers = @( + @{ Folder = 'NetKVM'; Inf = 'netkvm.inf' }, + @{ Folder = 'vioserial'; Inf = 'vioser.inf' }, + @{ Folder = 'Balloon'; Inf = 'balloon.inf' }, + @{ Folder = 'viorng'; Inf = 'viorng.inf' }, + @{ Folder = 'vioinput'; Inf = 'vioinput.inf' } + ) + + $installed = 0 + foreach ($driver in $drivers) { + $inf = $roots | + ForEach-Object { Join-Path $_ "$($driver.Folder)\w11\ARM64\$($driver.Inf)" } | + Where-Object { Test-Path -LiteralPath $_ } | + Select-Object -First 1 + if (-not $inf) { + if ($driver.Folder -eq 'NetKVM') { + throw 'The Arm64 NetKVM driver was not found on the attached media.' + } + continue + } + + & pnputil.exe /add-driver $inf /install | Out-Host + # 3010 asks for a restart; 259 means that no device uses the driver. + if ($LASTEXITCODE -notin 0, 259, 3010) { + throw "pnputil failed to install $inf (exit code $LASTEXITCODE)." + } + $installed++ + } + Write-Host "Installed $installed VirtIO Arm64 driver packages." +} + function Install-VirtIOGuestTools { + if ([Runtime.InteropServices.RuntimeInformation]::OSArchitecture -eq 'Arm64') { + Install-VirtIOArm64Drivers + return + } + $installer = Get-ChildItem ` -Path (Get-PSDrive -PSProvider FileSystem).Root ` -Filter 'virtio-win-guest-tools.exe' ` @@ -57,63 +99,6 @@ function Install-VirtIOGuestTools { } } -function Install-OpenSSHServer { - $capability = Get-WindowsCapability -Online -Name 'OpenSSH.Server*' | - Select-Object -First 1 - - if (-not $capability) { - throw 'The OpenSSH Server Windows capability was not found.' - } - - if ($capability.State -ne 'Installed') { - Add-WindowsCapability -Online -Name $capability.Name | Out-Null - } - - Set-Service -Name 'sshd' -StartupType Automatic - Start-Service -Name 'sshd' - - $rule = Get-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -ErrorAction SilentlyContinue - if ($rule) { - Set-NetFirewallRule ` - -Name 'OpenSSH-Server-In-TCP' ` - -Enabled True ` - -Profile Private, Public - } - else { - New-NetFirewallRule ` - -Name 'OpenSSH-Server-In-TCP' ` - -DisplayName 'OpenSSH SSH Server (sshd)' ` - -Enabled True ` - -Direction Inbound ` - -Protocol TCP ` - -Action Allow ` - -LocalPort 22 ` - -Profile Private, Public | Out-Null - } -} - -function Install-AdministratorAuthorizedKey { - $authorizedKeys = Join-Path $env:ProgramData 'ssh\administrators_authorized_keys' - $publicKey = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCwsF2ZDSHDaXM9BdDq3Vxkp6T+DJEakKaVZQJUEHexS34mbrxYAxmGBUPCrddfE01dS31kGS4XHVBa+wGUYodY+nPwnrfD1Q4phKVSzXr65K1Y/sCcjSiANBPWpv2Xd7IMOfLlrdLtmf5QcKWroIqO2LaIDGECwzUUHrfprgeaF9N0FGcmrgbmm23JUk+f6guRQ4br88L4rWIWEBvL9bTdwErNkdfsYE2F/U8aIFpMcVy2eJIOgy8ZjZvkGdm4r730YkTDL1VmAjiHH3/m2R1EOvwLzFhyWKoa4ULk/IQW+8iNnG42QEcaWRM+hMwlVdnNhPJP6WzS+fAEbibD3zM0q2X/4ex+cXRNOCd2/0KhnD2+3p1BM5QeFTzDappkk8W2meQkDE3hvTjtIQCzygFO6LNWtEEa7BTvvlMqF3CZWh88J9XiP750SjESe3Ge5o9A0T2hcJa+KZ1LxVEmNt4nD6E/OD4EymoaLIJZ1fH5ksSFjHzJ+mJouSVjc/H/VSE= guofang@GUOFANG-OFFICE' - - [IO.File]::WriteAllText( - $authorizedKeys, - $publicKey + [Environment]::NewLine, - [Text.Encoding]::ASCII - ) - - & icacls.exe ` - $authorizedKeys ` - '/inheritance:r' ` - '/grant' ` - '*S-1-5-32-544:F' ` - '*S-1-5-18:F' - - if ($LASTEXITCODE -ne 0) { - throw "icacls.exe exited with code $LASTEXITCODE." - } -} - function Enable-AutomaticLogon { $winlogonPath = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' @@ -172,8 +157,6 @@ try { if ($InstallVirtIO) { Install-VirtIOGuestTools } - Install-OpenSSHServer - Install-AdministratorAuthorizedKey if ($EnableAutomaticLogon) { Enable-AutomaticLogon } diff --git a/vm-images b/vm-images index 2ae7658..21604f5 160000 --- a/vm-images +++ b/vm-images @@ -1 +1 @@ -Subproject commit 2ae7658df5f063294a22f12a01b854821281eb6a +Subproject commit 21604f511fc05e91350c08ba39cffca694767812