WinBoat
repository·main·Indexed 12 days ago
https://github.com/tibixdev/winboatA system for running Windows on Linux ('Windows for Penguins') featuring a Guest Server REST API for system metrics, RDP status, and application info, as well as a Guest Server Updater. Includes the Xel lightweight HTML5 widget toolkit for building native-like UIs and tools for managing QEMU QMP connections and container lifecycles.
What's inside WinBoat
- Xel is an HTML5 widget toolkit designed for building native-like applications for the Web, Electron, and Hybrid environments. It follows the 'Keep It Simple' principle, utilizing plain JavaScript, HTML, and CSS without heavy abstraction layers or preprocessors. This makes it lightweight and easy to integrate into existing web projects.
Understand the Xel licensing model
mainThe Xel package uses a multi-license model depending on the specific files being used. Most of the NPM package and GitHub source code are licensed under the Xel License (MIT), but specific assets like themes and icons have their own distinct licenses:
- General Files: Licensed under the Xel License (MIT).
- Cupertino Theme Files (
cupertino.css,cupertino-dark.css): Licensed under the Xel Cupertino License v1. - Material Icons (
material.svg,material-outlined.svg): Licensed under the Material Icons License v1. - Fluent Icons (
fluent.svg,fluent-outlined.svg): Licensed under the Fluent Icons License v1.
Manage USB device passthrough with USBManager
mainThe
USBManagerclass provides a singleton interface for managing USB device passthrough to the guest VM. It automatically handles device attachment/detachment events and synchronizes the passthrough list with theWinboatConfig.Key capabilities include:
- Automatic Passthrough: When a device is added to the passthrough list, it is automatically passed to the VM if the guest is online.
- Dynamic Updates: Devices added or removed from the host are automatically passed to or removed from the VM if they are in the passthrough list.
- MTP Handling: Automatically attempts to free MTP (Media Transfer Protocol) devices using
fuserbefore passing them to the VM to prevent resource conflicts.
import { USBManager } from './usbmanager'; const usbManager = USBManager.getInstance();How Guest Server updates work
mainWinboat automatically manages the version synchronization between the host application and the Guest Server running inside the container.
The Update Process:
- Detection: When the host detects that
isOnlinehas become true, it compares its local version (VITE_APP_VERSION) with the version reported by the guest via${WINBOAT_API_URL}/version. - Trigger: If versions mismatch,
checkVersionAndUpdateGuestServer()is triggered. - Payload Delivery: The host sends a bundled update ZIP file to the
${WINBOAT_UPDATE_URL}/updateendpoint using a POST request withguestUpdaterAuthHeaders. - Atomic Application: The Guest Server Updater applies the update atomically. If the new server fails to start, it rolls back.
- Verification: The host waits (up to
GUEST_ONLINE_TIMEOUT_MS) for the guest to report a healthy status before completing the update cycle.
- Detection: When the host detects that
Generate ComposeConfig for container orchestration
mainThe
ComposeConfigtype defines the structure for generating a Docker Compose-compatible configuration. It specifically defines awindowsservice with a requiredenvironmentblock containing system variables likeVERSION,RAM_SIZE,CPU_CORES,DISK_SIZE,USERNAME,PASSWORD,HOME,LANGUAGE,ARGUMENTS, andHOST_PORTS.const compose: ComposeConfig = { name: 'winboat-instance', volumes: { '/host/path': '/guest/path' }, services: { windows: { image: 'winboat-image', container_name: 'winboat-container', environment: { VERSION: '...', // WindowsVersionKey RAM_SIZE: '8G', CPU_CORES: '4', DISK_SIZE: '64G', USERNAME: 'user', PASSWORD: 'password', HOME: '/home/user', LANGUAGE: 'en-US', ARGUMENTS: '', HOST_PORTS: '8080:80' }, ports: ['8080:80'], volumes: ['/host/data:/guest/data'], devices: ['/dev/bus/usb/001/001'] } } };Configure Windows installation with InstallConfiguration
mainUse the
InstallConfigurationtype to define the parameters for a new Windows installation. This includes OS version, language, hardware allocation (CPU/RAM), user credentials, and storage settings. You can also specify acustomIsoPathfor non-standard ISO files and asharedFolderPathfor host-to-guest file sharing.const config: InstallConfiguration = { windowsVersion: '...', // WindowsVersionKey windowsLanguage: 'en-US', cpuCores: 4, ramGB: 8, installFolder: '/path/to/install', diskSpaceGB: 64, username: 'admin', password: 'securepassword', container: '...', // ContainerRuntimes customIsoPath: '/path/to/custom.iso', sharedFolderPath: '/path/to/share' };Available widgets in Xel
mainXel provides a wide variety of UI components to build application interfaces. Supported widgets include:
- Inputs & Controls: Buttons, Text inputs, Number inputs, Sliders, Selects, Checkboxes, Switches, Radios, Steppers.
- Navigation & Layout: Tabs, Menus, Menubars, Cards, Drawers.
- Overlays: Dialogs, Popovers, Context menus.
- Feedback & Status: Progressbars, Throbbers, Swatchs.
Review the Xel Cupertino License v1 restrictions
mainThe Cupertino theme files (
cupertino.cssandcupertino-dark.css) are subject to the Xel Cupertino License v1.Key Restriction:
- The software must be used and distributed as part of an Application bundle for the Apple macOS operating system.
- Usage of these specific files with any other operating systems is PROHIBITED.
Get system metrics via /metrics
mainTo retrieve real-time hardware utilization, call the
GET /metricsendpoint. The response includes CPU usage and frequency, RAM usage (in MB and percentage), and Disk usage (in MB and percentage).Example Response:
{ "cpu": { "usage": 12.5, "frequency": 3200 }, "ram": { "used": 8192, "total": 16384, "percentage": 50.0 }, "disk": { "used": 102400, "total": 512000, "percentage": 20.0 } }GET /metrics Response: { "cpu": { "usage": 12.5, "frequency": 3200 }, "ram": { "used": 8192, "total": 16384, "percentage": 50.0 }, "disk": { "used": 102400, "total": 512000, "percentage": 20.0 } }Access the Guest Server OEM directory
mainThe
guestServerOemDir()function returns the path to the OEM payload directory. This directory contains the files that are copied into the guest'sC:\OEMmount during the installation process.import { guestServerOemDir } from './path/to/guestServer'; const oemPath = guestServerOemDir();Remove a USB device from the passthrough list
mainUse
removeDeviceFromPassthroughList(ptDevice)to stop passing a specific device to the VM and remove it from theWinboatConfig. If the guest is online and the device is currently passed through, it will be removed from the VM via QMP immediately.import { USBManager, type PTSerializableDeviceInfo } from './usbmanager'; const usbManager = USBManager.getInstance(); // ptDevice is a PTSerializableDeviceInfo object await usbManager.removeDeviceFromPassthroughList(ptDevice);Identify stale container errors
mainWhen interacting with containers, certain errors indicate that the container is in a stale or broken state (for example, if a passed-through USB device is no longer present on the host). In these cases, the container cannot be restarted and must be recreated from the compose file.
You can use the
isStaleContainerError(error)function to detect these specific failure patterns.import { isStaleContainerError } from "./path/to/container"; try { await myContainerManager.container("start"); } catch (error) { if (isStaleContainerError(error)) { console.error("Container is stale. Recreating from compose file..."); // Logic to run myContainerManager.compose("down") then "up" } }