The Problem
Running Windows applications on Linux typically means either a full VM (heavy, isolated, clunky) or Wine (incompatibility headaches). WinBoat targets the middle ground: a Windows VM that runs inside a Docker or Podman container, with individual apps surfaced as native Linux windows via FreeRDP's RemoteApp protocol. The pain point is the setup and orchestration complexity—container config, RDP plumbing, USB passthrough, and app discovery—which the tool automates behind an Electron UI.
What This Does
WinBoat is an Electron app (TypeScript + Vue, with Tailwind for styling) that manages a Windows VM lifecycle inside a container. The src/renderer/ directory holds the UI and orchestration logic; src/renderer/lib/winboat.ts is the core module (611 lines, 30 functions) handling app state, usage tracking, and the main API surface. src/renderer/lib/install.ts drives the Windows installation flow, src/renderer/lib/containers/ abstracts Docker and Podman (both implement a common container.ts interface), and src/renderer/lib/qmp.ts handles QEMU Machine Protocol for VM control. The guest_server/ directory (Go) runs inside Windows, exposing RDP app metadata and handling icon extraction.
How It Is Wired
Execution starts in src/main/main.ts (Electron main process), which spawns the renderer and a dev server via scripts/dev-server.ts. The renderer's src/renderer/main.ts boots the Vue app. The heavy lifting happens in src/renderer/lib/winboat.ts, which routes calls to install.ts (installation state machine), containers/docker.ts / containers/podman.ts (compose file generation via writeCompose), and utils/port.ts (port parsing). The internal call graph shows getActiveHostPort is called from 7 places—it's the hub for resolving container ports. changeState (6 callers) drives the install state machine. executeCommand (5 callers) in qmp.ts sends QMP commands to the VM.
The wiring has a notable structural cost: src/types.ts, src/renderer/lib/containers/common.ts, and src/renderer/lib/containers/container.ts form a circular import cycle, and src/renderer/lib/constants.ts is a hub with 12 dependents—changing it ripples widely. winboat.ts performs file I/O and cryptographic operations (secure key generation) directly, and install.ts also does file writes and crypto.
How To Use It
git clone https://github.com/moses-y/winboat
cd winboat
bun install # bun.lock present; package.json implies bun/npm
bun run dev # starts Electron dev server (scripts/dev-server.ts)
Prerequisites (from README): KVM enabled, 4GB+ RAM, 32GB storage, Docker or Podman with compose, FreeRDP 3.x with sound support. No environment variables are documented; configuration is UI-driven and stored in src/renderer/lib/config.ts.
Real-World Use
A typical flow: user launches WinBoat, selects Docker as runtime, picks a Windows ISO, and the app generates a docker-compose.yml via writeCompose in docker.ts. The container boots a Windows VM; the guest server (guest_server/main.go) starts inside Windows, exposing RDP apps. User clicks an app in the UI; getActiveHostPort resolves the RDP port, and FreeRDP connects to surface the app as a native Linux window. USB devices are passed through via usbmanager.ts using the usb.ids database.
Code Health & Issues
Static analysis (29 findings, 17 high) reports:
- High - Import cycle -
src/types.ts,src/renderer/lib/containers/common.ts,src/renderer/lib/containers/container.tsare mutually reachable; breaks refactoring. - High - Deep nesting (10 files) -
src/renderer/lib/config.ts,App.vue,views/Apps.vuehit indentation depth 7. - Medium - Oversized files -
winboat.ts(611 lines),views/Config.vue,views/SetupUI.vue. - High - Duplicated code - 69 repeated 6-line blocks across 7 files, notably
data/docker.tsanddata/podman.ts. - Medium - Hub module -
constants.tshas 12 dependents. - Low - TODO/FIXME markers - 3 in
usbmanager.ts,winboat.ts,utils/port.ts.
SDLC: High - No test suite (55 source files, zero tests). High - CI actions unpinned (oven-sh/setup-bun@v2, softprops/action-gh-release@v3 in .github/workflows/release.yml). Medium - No dependency vulnerability scan in CI. Low - No job timeouts in release.yml.
The Bottom Line
WinBoat is a functional, ambitious tool with a real architecture: containerized Windows VMs with RDP app integration is a legitimate approach. The codebase is dense and the circular imports, duplication, and missing tests make it risky to modify. It's beta software; use it if you're comfortable troubleshooting and want this specific workflow, but expect to invest time in cleanup before extending it.