DEV Community

Cover image for Run a Virtual Machine in Your Browser
Daniel Chifamba
Daniel Chifamba

Posted on

Run a Virtual Machine in Your Browser

Beyond the Tabs: Exploring Modern Web Capabilities. Episode. 1

We're going to run a complete virtual machine right here in your browser! And not just run the VM - we'll boot up both FreeDOS and Alpine Linux. "Wait, what? We already have VirtualBox, VMware, and DOSBox for that stuff!" Well, who needs VirtualBox when you have a web browser? (Just kidding! 😄)

But seriously, let's have some fun showcasing just how powerful modern browsers have become, especially now that they support WebAssembly (Wasm). Sure, traditional VM software is great, but being able to run an entire operating system in your browser? That's just cool! 🚀

In this guide, we'll use React.js, but I'm keeping things generic so you can adapt everything to plain HTML or whatever framework makes you happy.

What You'll Need

  • Basic HTML, Javascript, and CSS knowledge
  • Web browser with WebAssembly support. Don't worry, the browser you're using right now will likely work 😊
  • Node.js installed. You can get a copy here and follow the installation steps.

Let's Build This Thing!

1. Setting Up Our Web App

If you're already a React pro, feel free to skip the setup and jump to the Components part!

First, let's create our app using Vite (it's super fast and modern):



npm create vite@latest


Enter fullscreen mode Exit fullscreen mode

When it asks you:

  • Pick a project name (I'm going with "browser-vm")
  • Choose React as the framework.
  • Go with Javascript as the variant. (Keeping it generic as promised 😄 )
  • Then run:


cd browser-vm
npm install


Enter fullscreen mode Exit fullscreen mode

Components

Now let's set up our VM display. Open App.jsx replace all the contents with just this:



function App(){
return (
 <div id="screen_container">
 <div id="screen" style={{overflow: 'hidden'}}>Initializing Emulator…</div>
 <canvas style={{display: 'none'}}></canvas>
 </div>
 );
}
export default App


Enter fullscreen mode Exit fullscreen mode

Open index.css and replace the contents with:



#screen_container {
 white-space: pre;
 font-family: Courier, monospace;
 font-size: 14px;
 line-height: 14px;
 background-color: #000;
 color:#fff;
}


Enter fullscreen mode Exit fullscreen mode

2. Getting Our Virtual Machine Ready

We're using this cool project called V86 that turns your browser into a proper computer emulator. It uses WebAssembly to translate computer instructions on the fly - pretty neat, right? More on that here

Grab these files from V86's GitHub releases:

Next, download the following BIOS files from the bios folder of the V86 repository:

Put them in your project like this:



public/
├── v86.wasm
├── libv86.js
└── bios/
    ├── seabios.bin
    └── vgabios.bin


Enter fullscreen mode Exit fullscreen mode

3. Time to Make It Work!

Update your index.html to include our VM engine by adding <script scr="libv86.js"></script>:



<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
 <title>FreeDOS 1.2</title>
</head>
<body>
 <div id="root"></div>
+ <script src="libv86.js"></script>
 <script type="module" src="/src/main.jsx"></script>
</body>
</html>



Enter fullscreen mode Exit fullscreen mode

Now for the fun part - let's configure our virtual machine! Update the contents of App.jsx to:



import { useEffect } from 'react';
function App() {

useEffect(function initializeEmulator(){
 // See https://github.com/copy/v86/blob/master/src/browser/starter.js for options 
 window.emulator = new window.V86({
   wasm_path: '/v86.wasm',
   screen_container: document.getElementById("screen_container"),
   bios: {
     url: "/bios/seabios.bin",
   },
   vga_bios: {
     url: "/bios/vgabios.bin",
   },
   hda: { // Hard Disk
    url:  "/images/fd12-base.img",
    async:  true,
    size:  419430400, // Recommended to add size of the image in URL. see https://github.com/copy/v86/blob/master/src/browser/starter.js 
   },
   autostart: true,
 });
}, []);

return (
     <div id="screen_container">
       <div id="screen" style={{overflow: 'hidden'}}>Initializing Emulator…</div>
       <canvas style={{display: 'none'}}></canvas>
     </div>
   );
}
export default App;


Enter fullscreen mode Exit fullscreen mode

For more details on the available emulator options check out: https://github.com/copy/v86/blob/master/src/browser/starter.js

Let's Boot Some Operating Systems!

First Up: FreeDOS

Let's start with something fun - FreeDOS! It's perfect for running classic DOS games and software. Grab the pre-built version here, extract fd12-base.img, and drop it in your public/images folder.

Start the Web App by running:



npm run dev


Enter fullscreen mode Exit fullscreen mode

And open http://localhost:5173/ in your browser

Booting up FreeDOS within the browser

Want to Try Linux Instead?

Here's something even cooler - we can run Alpine Linux right in the browser! Download the latest Alpine virtual ISO and update your VM settings to:



window.emulator = new window.V86({
  wasm_path:  '/v86.wasm',
  screen_container:  document.getElementById("screen_container"),
  bios: {
    url:  "/bios/seabios.bin",
  },
  vga_bios: {
    url:  "/bios/vgabios.bin",
  },
  boot_order: '0x123', // Boot from CD-ROM first
  memory_size: 512 * 1024 * 1024, // 512MB RAM
  vga_memory_size: 64 * 1024 * 1024, // 64MB VGA RAM
  // See more: https://github.com/copy/v86/blob/master/docs/networking.md
  net_device: {
    type: 'virtio',
    relay_url: "wisps://wisp.mercurywork.shop",
  },
  cdrom: {
    // Source: https://dl-cdn.alpinelinux.org/alpine/v3.20/releases/x86/alpine-virt-3.20.3-x86.iso
    url: "/images/alpine-virt-3.20.3-x86.iso", 
  },
  autostart:  true,
});


Enter fullscreen mode Exit fullscreen mode

Refresh the browser and wait for Linux to boot. It may take 3–5 min 😅

Login prompt for Alpine Linux 3.20 running in the browser

Make It Look Extra Cool 😎

Want that authentic retro computer feel? Let's add the perfect font:

  • Get the Modern DOS font
  • Drop the files in your project in assets/fonts/ModernDOS and update index.css to:


@font-face {
 font-family: 'ModernDOS';
 src: url('./assets/fonts/ModernDOS/ModernDOS8x16.ttf') format('truetype');
}
#screen_container {
 white-space: pre;
 font-family: 'ModernDOS', 'Courier New', Courier, monospace;
 font-size: 14px;
 line-height: 14px;
 background-color: #000;
 color:#fff;
}


Enter fullscreen mode Exit fullscreen mode

Refresh the page and enjoy the new look!

FreeDOS running in the browser using a DOS-like font

What's Next?

Now that you've got a virtual machine running in your browser (how cool is that?!), here are some fun things to try:

Want the complete code? Grab it here:

Similar Cool Stuff to Check Out

Big Thanks To

Top comments (0)