name: install-windows-3-11 description: Guidance for setting up legacy Windows VMs (like Windows 3.11) in QEMU with web-based remote access via noVNC. This skill should be used when tasks involve running legacy operating systems in virtual machines, configuring QEMU for older OS images, setting up VNC/noVNC web interfaces, or establishing programmatic keyboard control via QMP. Covers VM boot verification strategies, nginx reverse proxy configuration, and websockify setup.
Install Windows 3.11
Overview
This skill provides guidance for setting up legacy Windows virtual machines (particularly Windows 3.11) using QEMU with web-based remote access. The core challenge is not just launching the VM, but verifying it reaches a usable state and providing reliable remote access.
Critical Success Criteria
Before marking any VM setup task complete, verify:
- The VM actually boots to the expected state - Screenshots, VNC connection tests, or QMP display queries must confirm the desktop/expected state
- Web interface is fully functional - End-to-end test through the browser, not just service status checks
- Keyboard/mouse input works - Verify input actually affects VM state, not just that commands are accepted
Approach
Phase 1: Environment Assessment
Before installing anything:
- Check QEMU version requirements in task description - note any specific version compatibility statements
- Audit existing nginx configuration to understand current server blocks
- Identify required ports and check for conflicts
- Determine the disk image format and any special QEMU flags needed
Phase 2: QEMU Configuration
When configuring QEMU for legacy operating systems:
- Memory allocation: Windows 3.11 typically needs 16-64MB RAM. Check image documentation for requirements
-
VNC setup: Use
-vnc :1for display 1 (port 5901). Consider-vnc :1,share=ignore-disconnectsfor stability -
QMP socket: Enable with
-qmp unix:/path/to/qmp.sock,server,nowaitfor programmatic control -
Display: Legacy OS may need specific display settings like
-vga stdor-vga cirrus
Example QEMU command structure:
qemu-system-i386 \
-m 32 \
-hda /path/to/disk.img \
-vnc :1 \
-qmp unix:/tmp/qmp.sock,server,nowait \
-vga std
Phase 3: Web Access Stack
The typical stack for web-based VNC access:
Browser → nginx (port 80) → websockify → VNC server (QEMU)
nginx configuration approach:
- First, examine
/etc/nginx/nginx.conffor existing server blocks - Check if
sites-enabledis included in the main config - Create configuration in the appropriate location to avoid conflicts
- Test configuration with
nginx -tbefore reloading
websockify setup:
websockify --web=/usr/share/novnc 6080 localhost:5901
Key parameters:
-
--webserves noVNC static files - Port 6080 is the WebSocket endpoint
- Target is the VNC port (5901 for display :1)
Phase 4: Boot Verification
This is the most commonly failed step. Never assume boot succeeded based on process status alone.
Verification strategies:
-
QMP display query: Send
{"execute": "query-status"}to check VM state -
VNC screenshot: Use
vncsnapshotor similar to capture current display -
QMP screendump:
{"execute": "screendump", "arguments": {"filename": "/tmp/screen.ppm"}} - Connect via VNC client: Actually view the display, not just test connectivity
Boot timing considerations:
- Legacy OS may need user interaction to complete boot (pressing Enter, clicking OK)
- Implement polling rather than fixed sleep delays
- Consider boot sequence: BIOS → DOS → Windows (multiple stages)
Phase 5: Input Verification
After establishing QMP connection:
- Send test keystrokes and verify display changes
- Each QMP connection requires capability negotiation first:
{"execute": "qmp_capabilities"} - Then send keys:
{"execute": "send-key", "arguments": {"keys": [{"type": "qcode", "data": "ret"}]}}
Common Pitfalls
QEMU Version Compatibility
If task specifies "compatible with QEMU X.Y.Z" but a different version is installed:
- Document the version mismatch
- Test if the image actually boots with the available version
- Report any compatibility issues observed
nginx Configuration Conflicts
Symptoms: 502 Bad Gateway, connection refused
Prevention:
- Always audit existing nginx config before adding new server blocks
- Check for conflicting
listendirectives - Verify upstream (websockify) is running before nginx tries to proxy to it
Premature Task Completion
Never mark "VM booted successfully" without:
- Visual confirmation (screenshot or VNC connection)
- Or QMP state verification showing expected state
QMP Socket Issues
- Stale socket files from previous runs cause connection failures
- Always clean up
/tmp/*.sockor equivalent before starting QEMU - Use
socatorncto test socket connectivity
Boot Detection
Arbitrary sleep commands are unreliable. Instead:
- Poll QMP status at intervals
- Check for specific display content changes
- Implement timeout with failure handling
Verification Checklist
Before declaring task complete:
- QEMU process is running (check with
pgreporps) - VNC port is listening (
ss -tlnp | grep 5901) - Websockify is running and connected to VNC
- nginx is proxying correctly (test with curl to WebSocket endpoint)
- Visual confirmation of expected OS state (screenshot or live view)
- Keyboard input affects VM display (send test key, verify change)
- Web interface loads in browser and connects to VM
Resources
references/
Refer to references/qemu_legacy_os.md for detailed QEMU flags and compatibility notes for legacy operating systems.
Refer to references/novnc_nginx_config.md for production-ready nginx configuration templates.
chat Comments (0)
Sign in to join the discussion and leave a comment.
Skill Details
Related Skills
Build your own?
Join 12,000+ developers contributing to the Claude ecosystem.
No comments yet. Be the first to share your thoughts!