Correct the Xcode file reference and CoreGraphics API call. Keep creation actions disabled for invalid configuration and use the v0.1.5 ARM64 guest resource ZIP.
Run Windows 11 ARM64 guests on macOS over QEMU+HVF, with an ivshmem
shared-memory transport carrying every guest channel (agent control,
display/VDD, input, audio, clipboard, SSH, 9P) - no guest networking
required.
- tools/transport: one guest transport API, two backends (PC AF_HYPERV,
Mac ivshmem); SPSC ring with an acquire-barrier fix for SSH integrity
- tools/ivshmem: our own KMDF ivshmem BAR-mapping driver (no third party)
- src/backend_mac: Mac-host ivshmem transport, QEMU VM lifecycle, IDD
display consumer, agent/SSH proxies, ISO->disk patcher, Windows create
- tools/agent + channel EXEs + tools/vdd: wired to asb_transport
- tools/agent_win: staged guest payload (interim, pending JIT pull)
- vendor/qemu-ivshmem: vendored QEMU 11.0.1 fork (ivshmem-plain) + LGPL
source mirror for the self-contained app bundle
- tools/sign/make-release.ps1: use the host-native ARM64 MSBuild so the
WDK driver ApiValidator runs (the x86 validator fails on ARM64)
On macOS the WebView was autocorrecting and autocapitalising VM names,
usernames, paths, and snapshot names as they were typed. There is no clean
public WKWebView toggle, so disable it in the markup: spellcheck="false" on
<body> (inherits to all descendants) plus the WebKit autocorrect="off" /
autocapitalize="off" extensions on the body and the free-text inputs (vm-name,
image-path, admin-user, modal-input). These attributes are inert on Windows, so
the shared web assets behave the same there.
style.css greys a disabled checkbox and its label (opacity, default cursor, via
:has()) so the "Deploy SSH key" option reads as unavailable until "SSH Server"
is enabled.
Headless mode: `appsandbox.exe --headless` runs a single-owner daemon that hosts
the core over a loopback HTTP/JSON API (http.sys) with a host.json discovery
file. A dependency-free Python SDK, examples, and a self-contained regression
suite live under tools/headless-api/ (PLAN.md = design rationale).
The API mirrors the GUI: create/start/shutdown/stop/delete/edit, snapshots and
branches (incl. base branches via the new asb_snap_base_branch_count), templates,
sshInfo, an SSE /v1/events stream, GUI-mirrored input validation, a startup
fail-fast (admin / Win11 build / VirtualMachinePlatform), and a single-instance
mutex shared with the GUI so only one of GUI/headless runs at a time.
SSH key deploy: sshDeployKey (requires sshEnabled) has the core generate an
AppSandbox ed25519 keypair once and the guest agent write the public key into
authorized_keys -- Windows administrators_authorized_keys (+ ACL), Linux/macOS
~/.ssh -- reporting a new ssh_key_deployed status (sshState 4). The GUI SSH
button and the SDK use the key for password-less login. Verified end-to-end on
Windows.
The Linux guest builds its agent/driver source from this branch's GitHub repo;
asb_core.c points the prefetch at "headless-api" (revert to "main" before merge,
see PLAN.md).
RAM (MB) must be 2 MB-aligned for Hyper-V/HCS, but the smart default (half of a 15982 MB host = 7991) and odd user-entered values were passed through unaligned and failed to boot. Round odd RAM down to even in the default, the create form (gatherConfig + a live field snap), and inline row edits; add step=2 on the field.
Also stop the New Sandbox modal from closing when a press starts inside it (e.g. selecting text in a field) and releases on the backdrop -- only close when the press also started on the backdrop.
web/app.js: renderVmTable's per-row rebuild signature omitted the
snapshot tree, so taking/deleting/renaming a snapshot did not re-run
makeSnapCell (the row only refreshed when edit mode toggled, which is why
clicking edit revealed the new snapshot). Add hasSnapshots, snapCurrent,
snapCurrentBranch and the serialized snapshots/baseBranches to the
signature. These change only on user snapshot actions (a running VM can't
be snapshotted), so the install-progress-tick rebuild-skip optimization
is preserved.
YubiKey-gated signing/packaging driven from the VS Release|x64 build:
- make-release.ps1 / sign-drivers.ps1: EV-sign all binaries + driver
.sys/.dll, submit drivers to Microsoft for attestation in parallel,
deposit the returned MS-signed drivers into bin\Release\drivers, and
build a flat AppSandbox-<ver>-x64.zip. Token presence is detected via
WinSCard + a silent NCrypt key-open, so an unplugged or unrelated card
never triggers an "insert smart card" dialog; no token => test-sign
only, no packaging.
- AppSandboxPackage.vcxproj runs it as a post-build step.
- Directory.Build.props/targets + build/version.rc: single-source version
stamped into every binary and into the driver INFs (StampInf).
- VDD INF: pull WUDFRd via Include/Needs + Win11 decoration to pass
infverif /h for Partner Center submission.
- Default new Windows VMs to Test Mode off (shipped drivers are MS-signed).
- SIGNING.md documents the git-ignored partner-center.local.json that you
must create with the Entra API secrets for driver attestation.
Partner Center credentials stay in git-ignored tools/sign/*.local.* files.
Linux guest provisioning now mirrors the host's regional settings instead
of hardcoding en_US / us / America/New_York / "ubuntu":
- detect_host_locale_settings() reads the current Windows user's locale
(GetUserDefaultLocaleName), keyboard (GetKeyboardLayoutList) and
timezone (GetDynamicTimeZoneInformation), translating each to the
Linux equivalent. Language is gated to the 8 ISO-preinstalled
languages (de/en/es/fr/it/pt/ru/zh) and falls back to en_US.UTF-8
otherwise; keyboard + timezone always match the host (every XKB
layout and IANA zone ships in the squashfs offline).
- VM name flows through as the guest hostname (mirrors Windows
ComputerName), staged as /etc/appsandbox-hostname.
- All four values staged as marker files; firstboot STEP 2/3/4 read
them with safe fallbacks and STEP 17 echoes the applied values.
Create-VM UI validation is now per-guest-OS, keyed consistently off
osType across validateVmName / validateUsername / validatePassword:
- Linux hostname: lowercase, RFC-1123 charset
- Linux username: ^[a-z_][a-z0-9_-]*$, <=32 chars
- Linux password: all chars allowed (host $6$ hash path), <=255 bytes
- default name lowercases to "myappsandbox" when Linux is selected
- OS Type moved above VM Name in the modal; .field-warn now wraps so
long messages don't break the modal layout; added admin-pass-warn span
IDD audio: drop the unused GetMixFormat call that returned
AUDCLNT_E_UNSUPPORTED_FORMAT on some AMD endpoints and needlessly killed
the audio path. renderfmt is built from the guest header and Initialize
runs with AUTOCONVERTPCM, so the host mix format was never used.
iso-patch.exe gains a new --ubuntu-to-vhdx mode that produces a fully
installed, bootable Ubuntu VHDX in one shot:
- vendored xz-embedded + custom ext4 writer + squashfs reader
- mounts the ISO, partitions GPT (ESP + Linux root), streams
casper/minimal.squashfs into a freshly-built ext4 rootfs through
a producer/N-decompress-worker/single-writer pipeline
- installs signed shim + grub from the ISO's pool .debs onto ESP,
writes a redirect grub.cfg pointing at the rootfs by UUID
- plants a defensive one-shot first-boot systemd unit that runs
grub-install + update-grub + AppSandbox guest setup (agent ELFs,
kernel modules, systemd units, wsl-mesa, wsl-deps, ldconfig,
no-sleep dconf, etc.) and reboots
linux_create_thread now spawns iso-patch with --ubuntu-to-vhdx
and a --stage manifest covering the full extras tree (reuses
stage_linux_agent_and_extras to populate a staging dir then walks
it). image_path is cleared post-build so the ISO isn't re-attached
to the runtime VM. ComPorts/com1 named pipe and the do_connect_rdp
window path are dropped (IDD is the only live display path now).
VideoMonitor stays unconditional (vmwp.exe crashes 0xC0000005
without it) — but with no ConnectionOptions/named pipe, matching
master.
JS frontend: "Installing Linux" branch added so the spinner label
no longer says "Installing Windows" for Linux VMs. Progress %
now tracks ingest fraction (n_processed / total_inodes) mapped
into 10..75%, with post-ingest phases at 82..99%.
Ubuntu 26.04 LTS guest end-to-end:
- cidata-driven autoinstall pipeline (subiquity user-data + nested
cloud-init bootcmd) in disk_util.c. Static NAT IP, ssh-via-vsock
marker, serial-debug kernel cmdline injected into ESP grub.cfg by
iso-patch.exe. Five separate firstboot pipeline fixes get the VM
to GDM unattended on Hyper-V Gen 2.
- Linux guest stack under tools/linux/:
- appsandbox-agent (vsock :1 control + clipboard helper spawn)
- appsandbox-audio (snd-aloop -> vsock :4)
- appsandbox-display (KMS framebuffer capture -> vsock :2)
- appsandbox-input (uinput injection <- vsock :3)
- appsandbox-clipboard (XCB selection bridge <-> vsock :5/:6)
Helper binaries staged via release/resources/linux/.
- asb_drm DRM module: virtual single-CRTC display sink the host
captures over vsock. Platform-bus, DRIVER_GEM/MODESET/ATOMIC/RENDER,
linear shmem framebuffers. asb-evict-simpledrm.service unbinds the
EFI simple-framebuffer before display-manager so mutter binds
asb_drm as the sole DRM card.
- dxgkrnl vendored byte-identical from microsoft/WSL2-Linux-Kernel
linux-msft-wsl-6.18.y with our DKMS/out-of-tree shim (dxgkrnl_compat.h
+ Kbuild + dkms.conf). Autoinstall late-commands dkms-builds against
every /target/lib/modules/<kver> so kernel-version drift between ISO
and post-update reboot still leaves a working .ko.
- wsl-mesa custom build (Mesa 25.3 + d3d12 gallium + microsoft-
experimental dzn Vulkan). Installs to /opt/wsl-mesa parallel to
Ubuntu's stock Mesa. Prebuilt tarball for ubuntu-26.04-amd64
shipped under tools/linux/wsl-mesa/prebuilt/ (21 MB).
- Per-VM GPU acceleration policy:
- /etc/systemd/user-environment-generators/50-appsandbox-gpu
emits GALLIUM_DRIVER=d3d12 + LD_LIBRARY_PATH + VK_DRIVER_FILES
into the user@1000 systemd-user environment when /dev/dxg and
/opt/wsl-mesa are present. Inherited by every app-*.scope a
.desktop launch creates.
- /etc/systemd/user/org.gnome.Shell@.service.d/no-gpu.conf
UnsetEnvironment= strips these for the compositor — mutter
stays on llvmpipe so asb_drm scanout works (the d3d12 pipe has
no GBM compatibility with asb_drm).
- /usr/local/bin/appsandbox-gpu wrapper for terminal-launched
opt-in GPU acceleration (probes /dev/dxg; no-op on no-GPU VMs).
- Host changes:
- vm_display_idd.c, vm_clipboard.c, vm_agent.c, vm_ssh_proxy.c,
asb_display.c: hcs_service_guid(os_type, port) so the same code
paths reach the per-OS service identifiers (HV_GUID for Windows,
vsock template for Linux).
- asb_core.c: linux_create_thread builds an empty VHDX, cidata
ISO with extras (agent ELFs, dxgkrnl src, asb_drm src, wsl-mesa
tarball, wsl-deps libs), and boots the desktop ISO + cidata.
- hcs_vm.c: HostLxssLib Plan9 share appended for Linux VMs;
VideoMonitor + ComPorts retained for serial debug.
- gpu_enum.c/h: gpu_append_lxsslib_share helper.
- vm_clipboard.c file-drop support (CF_HDROP / x-special/gnome-
copied-files round-trip).
- vm_display_idd.c: 32-bit S32_LE PCM audio path matches the
Linux daemon's snd-aloop capture format.
- iso-patch.c gains a patch_ubuntu_esp_grub_for_debug pass that
rewrites /EFI/ubuntu/grub.cfg via the FAT32 ESP, plus a qcow2->
vhdx converter with a RFC 1951 DEFLATE inflater for compressed
cluster handling.
- wsl-deps: Microsoft's libd3d12.so / libd3d12core.so / libdxcore.so
fetched on demand from the public NuGet feed
pkgs.dev.azure.com/shine-oss/wsl (no auth). Staged at
/opt/appsandbox/wsl-deps on the guest and put on /etc/ld.so.conf.d
rather than /usr/lib/wsl/lib (which is overlaid by the agent's
9P mount).
UI: web/{app.js,index.html} expose Linux VM creation + GPU selection,
distribution dropdown for cached Ubuntu ISOs, and the ISO picker for
custom images.
The dropdown was hidden on macOS causing osType to be missing
from the create request. Now it's visible with a macOS option
added and auto-selected/disabled on Mac.
The macOS backend auto-downloads the restore image from Apple,
so image/template selection, GPU, credentials, and Windows
options are unnecessary. The Create button is always enabled on
macOS since no image path is required.
bugs fixed: the agent -> host messaging passing was unreliable
The NAT IP address failed to automatically set on first boot for VMs created from ISO.
SSH doesn't require internet which is cool, goes over Hyper-V sockets.
set nat as default network, set IP address automatically when in NAT mode, don't open the rdp display on win11 home, fix a bug where display would open again at shutdown if it was closed