Commit Graph
14 Commits
Author SHA1 Message Date
James Stringer af241cdaf3 Bump version to 0.1.8
App Sandbox 0.1.8

### Added

- Choose a specific GPU when creating or editing a VM on Windows, with automatic fallback if that GPU becomes unavailable.
  Thanks to @TejasPersonal, @Mungr3ss and @JasonSTX for requesting this ([#109](https://github.com/jamesstringer90/appsandbox/issues/109)), and @trevmlt for documenting the multi-GPU problem and a workaround ([#110](https://github.com/jamesstringer90/appsandbox/issues/110)).

### Fixed

- Preserve VM MAC addresses across restarts on Windows and macOS, allowing router address reservations to keep working.
  Thanks to @kurokawaikki for identifying the changing MAC addresses ([#92](https://github.com/jamesstringer90/appsandbox/issues/92)).
- Keep automatic login enabled and prevent password expiry for newly created Windows VMs on Windows and macOS hosts.
  Thanks to @macg4dave for reporting unexpected login prompts ([#133](https://github.com/jamesstringer90/appsandbox/issues/133)).
- Fix network setup failures when starting multiple VMs at the same time on Windows.
- Reduce unexpected SSH port changes on Windows by retrying the saved port, with clearer failure messages.
- Fix missing network drivers in newly created Windows VMs on macOS.
  Thanks to @YiwenLu-yiwen for reporting the failed download and confirming the workaround ([#107](https://github.com/jamesstringer90/appsandbox/issues/107#issuecomment-5689676123)).
2026-09-15 21:55:30 -04:00
James Stringer c654b940d0 Bump version to 0.1.7
App Sandbox 0.1.7

### Added

- NVIDIA DLSS support in compatible Vulkan games running in Windows VMs on x64 Windows hosts.
  Thanks to @darkjezza for reporting this ([#139](https://github.com/jamesstringer90/appsandbox/issues/139)).
- A dedicated VM settings dialog on Windows and macOS, and a clearer snapshot and branch manager on Windows.

### Fixed

- Corrected GPU and network information on macOS and removed unsupported network options.
2026-09-14 22:49:27 -04:00
James Stringer 3480763be3 Bump version to 0.1.6
App Sandbox 0.1.6

### Added

- Native NVIDIA OpenGL and Vulkan support in Windows VMs on x64 Windows hosts, including 32-bit games and applications.
  **Special thanks to @Poldino95 for figuring out why NVIDIA's native graphics drivers weren't working inside VMs and demonstrating working solutions. Their detailed research provided the foundation for these improvements.** ([#130](https://github.com/jamesstringer90/appsandbox/pull/130), [#131](https://github.com/jamesstringer90/appsandbox/pull/131))
  Thanks also to @N1qro for reporting Vulkan game launch failures ([#73](https://github.com/jamesstringer90/appsandbox/issues/73)).

- NVIDIA DLSS support in compatible 64-bit games running in Windows VMs on x64 Windows hosts.
  Thanks again to @Poldino95 for identifying what prevented DLSS from working and demonstrating the solution ([#129](https://github.com/jamesstringer90/appsandbox/pull/129)), and @Giraffe886 for raising this ([#98](https://github.com/jamesstringer90/appsandbox/issues/98)).

### Fixed

- Improved OpenGL and Vulkan support for Intel and AMD GPUs in Windows VMs by using their native graphics drivers, including supplying missing AMD driver files.
- Fixed Ubuntu 26.04.1 VMs getting stuck during installation.
  Thanks to @EzYDark for diagnosing the package compatibility problem and proposing a fix ([#120](https://github.com/jamesstringer90/appsandbox/pull/120)).
- Fixed Firefox failing to launch in newly created Ubuntu VMs.
  Thanks to @EzYDark for identifying the cause and proposing a fix ([#120](https://github.com/jamesstringer90/appsandbox/pull/120)).
- Fixed package update errors in newly created Ubuntu VMs caused by leftover installation-disc sources.
2026-09-13 20:28:37 -04:00
James Stringer 2d9eae869a Bump version to 0.1.4
App Sandbox 0.1.4

- **Windows 11 (ARM64) VMs on macOS.** On an Apple Silicon Mac, App Sandbox can
  now create and run Windows 11 ARM guests -- previously a macOS host could only
  run macOS guests. The Windows guest gets its own display window, keyboard and
  mouse, sound, clipboard (including copying files to and from your Mac),
  one-click SSH, and networking, and is built from a Windows 11 ARM64 ISO you
  provide. It runs on a self-contained virtual-machine engine bundled with the
  app, and the guest agent and drivers are downloaded (code-signed) when you
  create the VM, so no test-signed components ship inside App Sandbox.

- **Non-ASCII usernames and passwords now work when creating a VM through the
  scriptable API.** Characters outside plain ASCII (for example Chinese) arrive
  from the API JSON-escaped; App Sandbox stored the escape sequences literally
  instead of decoding them, so a VM created via the API with such a credential
  would reject the login. They are now decoded correctly. (The desktop app was
  unaffected.)
- **The virtual display now recovers if it gets disabled in the guest.** The
  guest agent kept trying to restart the App Sandbox display driver -- which
  can't re-enable a disabled device -- so the picture never came back; it is now
  re-enabled and recovers.
- Various stability and bug fixes across the Windows and macOS components.

- **Windows VMs on macOS are not GPU-accelerated.**
- **x64 (emulated) apps in ARM Windows VMs don't get the OpenGL fix** -- the Mesa
  driver shipped on ARM is ARM64-only; native ARM64 apps get full GPU OpenGL.
  (carried over from 0.1.2)
- **ARM Linux (Ubuntu 26.04 LTS) guests do not work -- on ARM, Windows is the
  only working guest** (Ubuntu 26.04's arm64 kernel churns BPF JIT memory and
  never reaches the desktop). (carried over from 0.1.2)
2026-06-30 20:57:07 -04:00
James Stringer dfd6fe475f Win-on-Mac: fix ivshmem AGENT/SSH region overlap and display readiness
Post-review fixes and release prep for the win-on-mac feature.

* asb_shm_layout.h: fix a region-sizing bug -- the AGENT (ch1) slot stride
  (0x20070) exceeded ASB_AGENT_REGION_SIZE (0x20000) by 112 bytes, so the agent
  host->guest ring overran into the adjacent SSH (ch7) region and corrupted its
  slot state under sustained traffic. Enlarge the AGENT region to 0x21000
  (downstream offsets cascade) and add per-region compile-time guards
  (n_slots*stride <= region_size) so this class of overlap fails the build.
  Host/publisher-side only -- the guest reads geometry from the published directory.

* headless.m: GET /display readiness now includes idd_ready for a Windows guest,
  matching the open precondition (asb_core_mac.m) and the Windows host
  (asb_vm_idd_ready). Before, the Mac readiness was running && agent_online only,
  so it could report ready before the VDD was up and a poll-then-open would
  spuriously 409 display_not_ready. macOS guests are unchanged.

* iso-patch-mac.m (stage): wipe the plaintext password buffer on the
  --shadowhash-file read-failure path, matching the sibling --kcpassword-file path.

* iso_patch_mac.m: point the signed Windows guest payload at the v0.1.4 release.

* vm_lifecycle.py: raise the Windows build-stall budget to 3600 s for the
  signal-less first-boot window under concurrent multi-VM load.

* tools/headless-api/README.md: document Windows guests on macOS hosts (platform
  matrix, host-fixed line, requirements heading, osType field).
2026-06-30 18:12:32 -04:00
James Stringer 303b34dab8 Win-on-Mac: encode the guest password in the daemon for all three configs
All three guest configs now obfuscate/hash the account credential in the daemon
and hand the disk-applier child only the non-plaintext result -- the plaintext
never crosses the process boundary, mirroring the Windows-on-Windows model.

  * Win-on-Mac: the daemon generates unattend.xml / setup.cmd / SetupComplete.cmd
    in-process via the shared asb_provision_* (base64 of UTF-16LE(pass+"Password"),
    the same encoder the Windows backend uses) and passes build-windows only
    --prov-dir; the plaintext --pass argv is gone. The child still detects the
    install.wim language and reports LANG:, and the daemon re-generates unattend.xml
    in-process with the detected tag -- the exact mirror of vhdx_create_thread.
  * Mac-on-Mac: the salted PBKDF2-SHA512 ShadowHash + kcpassword are computed in
    the daemon via the new shared tools/provision/mac_account_hash.{h,m}; the stage
    child takes --shadowhash-file / --kcpassword-file. --user-password-file remains
    a direct-CLI fallback.
  * Verified end-to-end on live Windows + macOS guests with a 12-character mixed
    Chinese/English password (ValidateCredentials / dscl -authonly), exercising the
    UTF-16 surrogate path.

Also in this checkpoint of accumulated win-on-mac work:

  * agent: report_idd_status re-runs on the device-check loop (force-on-connect +
    on-change) so display readiness tracks the live, self-healed VDD state instead
    of a single one-shot sample.
  * disk builder (tools/iso-patch-mac/engine): WIM reader gains the install-image
    default-language reader behind the language auto-detect; win_disk locale/apply
    refinements.
  * display + transport: idd_display Metal render + clipboard-reader paths;
    asb_ivshmem_transport slot-reclaim hardening.
  * housekeeping: remove the dev-only transport test harness (tools/transport/test/*);
    update headless-api test scripts; drop changelog-style comments.
2026-06-29 20:50:32 -04:00
James Stringer df0e2532e0 Bump version to 0.1.3
### Added
- **Headless mode with a scriptable HTTP/JSON API (Windows + macOS).** Launch
  App Sandbox with `--headless` to run a single-owner background daemon exposing
  a loopback HTTP/JSON API that mirrors the GUI: create, start, shut down, edit,
  and delete VMs; manage snapshots, branches, and templates (Windows); read SSH
  connection info; subscribe to a live event stream; and open or close a VM's
  display window -- all from a script. Ships a dependency-free Python SDK,
  runnable examples, and a cross-platform test suite (bundled in the release
  package under headless-api/, alongside the app). Launching normally (no
  `--headless`) is unchanged.
- **One-click SSH key login.** With the SSH server enabled, the new "Deploy SSH
  key" option installs an App Sandbox key into the guest (Windows, Linux, and
  macOS) so the GUI's SSH button and the SDK connect without a password.

### Fixed
- **Excessive GPU usage while viewing a Windows VM.** The display window was
  redrawing as fast as it could -- presenting ~2,100 frames a second and holding
  the host GPU near 90% even on a static screen. It now redraws only when the
  picture changes (plus a small safety refresh), dropping to the real frame rate
  (~30-60 fps) with no added latency.
- **A graceful shutdown could report a false error.** On a busy guest, a
  shutdown that actually succeeded could surface as a failure; shutdown and
  restart now report success once the request is delivered and confirm it by the
  guest exiting.
- **The headless daemon now cleans up its VMs when it exits**, instead of
  leaving them running with no owner.
- **macOS: text fields no longer autocorrect or autocapitalize** VM names,
  usernames, paths, and snapshot names as you type.
- Various stability and bug fixes across the Windows, macOS, and Linux
  components.

### Known issues
- **Create VMs one at a time.** Creating several at once can race on the
  disk-image build/staging step, causing a build to fail and the VM to be
  removed; create them sequentially.
- **x64 (emulated) apps in ARM Windows VMs don't get the OpenGL fix** -- the
  Mesa driver shipped on ARM is ARM64-only; native ARM64 apps get full GPU
  OpenGL. (carried over from 0.1.2)
- **ARM Linux (Ubuntu 26.04 LTS) guests do not work -- on ARM, Windows is the
  only working guest** (Ubuntu 26.04's arm64 kernel churns BPF JIT memory and
  never reaches the desktop). (carried over from 0.1.2)
2026-06-11 22:03:47 -04:00
James Stringer 9b9b92f053 Add the display window to the macOS headless daemon; retire the plan docs
Bring macOS to parity with the Windows display feature: open/close/poll the VM's
display window over the API (POST/DELETE/GET /v1/vms/{name}/display, plus
displayOpen on every status object), so a script can show the same view the GUI's
Connect button does. Validated live on Apple silicon.

The GUI already creates the per-VM VZVirtualMachineView window on the Running
transition (gated off under --headless); the daemon now opens it on an explicit
request after two gates:
  - A-gate: asb_mac_have_gui_session() (CGSessionCopyCurrentDictionary /
    kCGSessionOnConsoleKey) -- a daemon with no console Aqua session (launchd /
    SSH) refuses with 409 no_display instead of spawning an invisible window;
  - readiness: running && agent_online. macOS has no frame channel or display
    driver (the view binds the in-process VM framebuffer directly), so there is
    nothing to probe -- unlike the Windows/Linux idd_status latch.
New core API asb_mac_open_display / asb_mac_close_display (asb_core_mac.m); new
codes BACKEND_ERR_NO_DISPLAY / BACKEND_ERR_NOT_READY (asb_types.h).

run_headless swaps the bare CFRunLoopRun() for [NSApp run] (Accessory policy)
ONLY in a console GUI session -- the window needs the window server; otherwise it
keeps the bare CFRunLoop so the daemon still runs headless over SSH/launchd. Both
loops drain the main dispatch queue, so every VZ op and the SIGINT/SIGTERM sources
are unaffected; cleanup_and_exit exit()s directly, so no quit-path change. The
spike the design flagged as unverifiable without a Mac was confirmed here: VZ
main-queue dispatches still fire under [NSApp run], and windows open, take focus,
and deliver windowWillClose:.

Close tracking avoids a mid-close use-after-free: VzDisplayWindow gains a
userClosed flag set in windowWillClose:; displayOpen reads display && !userClosed,
and open_display reaps a self-(X)-closed window on the next request (off the WM
close stack), mirroring the Windows reap. showDisplay also calls
activateIgnoringOtherApps: so the Accessory daemon's window comes to the front.

tests: vm_lifecycle.py now runs the display open/close check on macOS too (it
self-skips on 409 no_display or a Linux guest whose agent predates idd_status).
README documents the macOS display support (matrix row, the console-session
A-gate, and the running && agentOnline readiness).

Remove tools/headless-api/PLAN.md and display-plan.md: these were the design /
decision logs for the headless port and the display feature, both now shipped and
validated. Their dangling references in README.md and headless.m comments are
cleaned up in the same change.
2026-06-11 20:27:52 -04:00
James Stringer 7ed54b1fc4 Document edit() and snap_take() stopped-only preconditions in the SDK
edit() honors ramMb/cpuCores/gpuMode/networkMode on a stopped VM (name is fixed at create, other keys ignored; 409 if running); snap_take() requires the VM stopped (409 vm_running).
2026-06-11 20:08:47 -04:00
James Stringer 82c5bd7507 Mark Linux display validated in the plan; advise sequential VM creates
display-plan.md: the Linux display half is now implemented and validated (confirmed on fresh Linux VMs built from the pushed branch, where the agent's idd_status latches readiness and the display opens).

README.md: note that VMs should be created sequentially -- concurrent creates can race on the VHDX-build prefetch/staging and a build may fail (iso-patch.exe exit 1) and be removed.
2026-06-11 18:59:16 -04:00
James Stringer 889ccbc3a1 Implement headless display open/close with agent-reported readiness
Add POST/DELETE/GET /vms/{name}/display plus the open_display/close_display/display_status/display_ready SDK methods, so a script can open and close a VM's display window like the GUI's Connect button.

Readiness is a latched flag, not a frame-channel probe: connecting to the guest frame service is itself becoming the display's single consumer, so polling it would steal the slot and blank the display. The guest agent reports the display driver state over the agent channel (idd_status) and the host latches it as idd_ready; asb_vm_idd_ready = running && agent_online && idd_ready. The Linux agent reports idd_status:ok once the user session is up (Mutter compositing).

The display window is daemon-owned (per-VM table keyed by unique_id), gated on a visible window station, and self-tears-down on the X button; displayOpen is read from the live window state, so it is honest however the window closed.
2026-06-11 18:14:13 -04:00
James Stringer b95913dc1c Add headless display-open design plan
tools/headless-api/display-plan.md: design for opening/closing a VM display window
through the headless API (POST/DELETE /v1/vms/{name}/display). Windows is implementable
(vm_display_idd_create is self-contained); macOS is design-only and unvalidated (it
swaps the daemon run loop to AppKit and needs a Mac to verify). Access model: bearer
token for auth + a runtime "can this session render a window" gate; no loopback/peer
detection.
2026-06-10 22:30:34 -04:00
James Stringer 929ad69f89 Make the headless SDK and test suite cross-platform; update docs
asb.py: resolve the support directory, daemon launch hint, and SSH key path per
platform (%ProgramData%\AppSandbox on Windows, ~/Library/Application Support/
AppSandbox on macOS) so the same SDK drives either daemon from its host.json.

tests: the suite is now capability-gated and runs on either host. helpers.py
adds IS_MAC, the per-platform VM/disk paths, the macOS IPSW location, a key-auth
login helper (chmod on mac), and wait_progress -- a stall-based wait that watches
the VM's reported progress/status instead of a fixed deadline, so a slow install
or IPSW download doesn't false-fail. run_all.py launches the macOS suite as two
concurrent VMs (one downloading a fresh IPSW, one from cache) sized 4096 MB / 2
cores / 64 GB, with a leftover sweep and IPSW housekeeping. The lifecycle and
host/validation tests assert 501 for snapshots/templates on macOS and run the
Windows-only template build only where supported.

docs: README gains a platform-support matrix (which guest OSes and host features
each platform supports) and the macOS sudo/SUDO_USER launch model alongside the
Windows instructions. PLAN.md records the macOS port, the Windows
cleanup-on-exit fix, the guest-agent threading fix, and the startup fail-fast /
GUI polish.
2026-06-10 19:00:04 -04:00
James Stringer 4087baa4bf Add headless --headless daemon, HTTP/JSON API + Python SDK, and SSH key deploy
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).
2026-06-09 20:12:18 -04:00