Architecture and extending
Overview
Section titled “Overview”Repository layout
Section titled “Repository layout”| Path | Contents |
|---|---|
app/ |
Desktop app: React UI in app/src, Tauri/Rust in app/src-tauri. |
src/GpuVM/ |
The PowerShell 7 module: Private/ (helpers), Backends/ (one file per backend), Public/ (one file per exported cmdlet). |
src/bridge.ps1 |
Bridge between the app and the module. |
gpuvm.ps1 |
CLI. See CLI reference. |
profiles/ |
JSON profiles. |
guest/ |
Scripts that run inside the VM: first-boot setup, optimizations, streaming, audio, display resolution and collect-info.ps1 for labs. |
templates/ |
unattend.xml template. |
streaming/components.json |
Versions, URLs and SHA-256 of the streaming components. |
labs/ |
Labs. |
tests/ |
Pester tests. |
The module
Section titled “The module”GpuVM.psm1 loads Private, then Backends (which register themselves), then Public, and exports one function per file in Public/. Each VM created with GpuVM has a gpuvm.json state file in its folder with the resolved profile, the GPU and driver version, and the encrypted streaming and guest credentials. VMs without that file still show in the app, but only with power actions and the console.
Long cmdlets report progress with Write-Step: in a terminal it prints a line; in the app it goes to the button that started the job.
Backends
Section titled “Backends”A backend is how the GPU is given to the VM. Each one calls Register-GpuVMBackend with a name, a description and these operations:
| Operation | Receives | Does |
|---|---|---|
Test |
config | Returns host checks (Name, Status Ok/Warn/Fail, Detail). |
New |
context | Creates the VM from scratch. |
Apply |
name, config | Applies CPU, memory, GPU, etc. to a VM that is off. |
SyncDriver |
name, state | Copies the host driver again; returns the copied version. |
Remove |
name, state, delete disk | Removes the VM. |
Public cmdlets only talk to this interface. The current backend is hyperv-gpup (Backends/HyperVGpuP.ps1): it sets the processor, fixed memory, disables checkpoints, sets MMIO space, Secure Boot and TPM, connects the switch and adds the GPU partition adapter. GPU-P doesn’t support checkpoints or saved state, so if the host shuts down the guest shuts down in order.
Bridge between the app and PowerShell
Section titled “Bridge between the app and PowerShell”- Quick queries (overview, host info, power actions, saving options) go through one persistent
pwshprocess, one at a time. If the process died before the request was sent, it is restarted once; once a request is sent it is never retried, because the command may already have run (shut down, delete…). A query times out after 180 s. - Long jobs (create a VM, start and open, sync the driver, apply settings) run in their own
pwshprocess (bridge.ps1 -Once), so they don’t block the stats. Their progress arrives asjobevents. bridge.ps1reads one JSON request per line,{"id", "cmd", "args"}, and writes one JSON event per line:progress,warning(sent as soon as it appears) andresult(okwithdata, orerror). Arguments shaped{"user", "password"}become aPSCredential.- The app can only call functions exported by the module, and
Update-GpuVMComponentis blocked.
Security
Section titled “Security”- Elevation: the release build asks for administrator when it opens (the manifest requires it). In development it starts normally and offers to reopen as administrator.
- Only scripts from Program Files: the installed app runs the module and scripts bundled next to it in Program Files, which only an administrator can modify, so a program running as the user can’t change what the elevated app runs.
- PowerShell 7 by absolute path:
pwsh.exefromProgram Files\PowerShell\7(MSI) or from the Microsoft Store package folder underProgram Files\WindowsApps, never apwsh.exethat appears earlier in the user’sPATH. - Data restricted to administrators:
%ProgramData%\GpuVM(labs, downloads) and the VMs folder (C:\GpuVM, which would inherit “Authenticated Users: modify” fromC:\) are limited to Administrators, SYSTEM and Hyper-V’s virtual machines. - DPAPI: the Sunshine credentials and the guest password are stored encrypted with DPAPI on the host.
- Pinned components: Sunshine, the Virtual Display Driver, nefcon and VB-CABLE are pinned by SHA-256 in
streaming/components.json. A file whose hash doesn’t match isn’t used. The guest downloads nothing. Only the certificate that signed the virtual display driver is trusted. - Password cleanup:
unattend.xmlholds the password in plain text and is deleted inside the VM as soon as it’s no longer needed. - No argument injection: the Moonlight app name is validated before building Moonlight’s command line.
Two environment variables move data elsewhere: GPUVM_DATA (all data) and GPUVM_LABS_ROOT (labs).
Extending
Section titled “Extending”- New backend (for example
kvm-vfio): a file insrc/GpuVM/Backends/that callsRegister-GpuVMBackendwithTest,New,Apply,SyncDriverandRemove. Profiles choose it with"backend". - New guest optimization: an entry in
guest/optimizations.ps1, tested in a lab and added to a profile. - New profile: a JSON file in
profiles/that extends an existing one.
Invoke-Pester ./testsThey cover profiles, unattend.xml, the driver copy, the GPU partition, labs, component verification, streaming credentials, pairing (with simulated Sunshine and Moonlight) and sunshine.conf, and don’t need administrator.