diff --git a/.gitignore b/.gitignore
index 1807dedf9..aeab15586 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
/node_modules
/.svelte-kit
pnpm-lock.yaml
-build/
\ No newline at end of file
+build/
+custom-disk-images/*
+!custom-disk-images/.gitkeep
\ No newline at end of file
diff --git a/README.md b/README.md
index e73e58223..2823d99f5 100644
--- a/README.md
+++ b/README.md
@@ -9,273 +9,234 @@ Try out the new Alpine / Xorg / i3 graphical environment: [https://webvm.io/alpi
-WebVM is a server-less virtual environment running fully client-side in HTML5/WebAssembly. It's designed to be Linux ABI-compatible. It runs an unmodified Debian distribution including many native development toolchains.
+## What is WebVM?
-WebVM is powered by the CheerpX virtualization engine, and enables safe, sandboxed client-side execution of x86 binaries on any browser. CheerpX includes an x86-to-WebAssembly JIT compiler, a virtual block-based file system, and a Linux syscall emulator.
+WebVM is a server-less virtual environment running fully client-side in HTML5/WebAssembly. It's designed to be Linux ABI-compatible and runs an unmodified Debian distribution including many native development toolchains.
+
+WebVM is powered by the **CheerpX** virtualization engine, which provides:
+
+- x86-to-WebAssembly JIT compiler
+- Virtual block-based file system
+- Linux syscall emulator
+- Safe, sandboxed client-side execution
## Table of Contents
-- [Fork, deploy, customize](#fork-deploy-customize)
-- [Running WebVM locally with a custom Debian mini disk image](#run-webvm-locally-with-a-custom-debian-mini-disk-image)
-- [Example customization: Python3 REPL](#example-customization-python3-repl)
-- [How to use Claude AI](#how-to-use-claude-ai)
-- [Bugs and Issues](#bugs-and-issues)
-- [More links](#more-links)
-- [Thanks to...](#thanks-to)
-- [Versioning](#versioning)
+- [Quick Start](#quick-start)
+- [Networking](#networking)
+- [Development & Customization](#development--customization)
+ - [Local Serving & Image Configuration](#local-serving--image-configuration)
+ - [Deploy to GitHub Pages](#deploy-to-github-pages)
+- [Features](#freatures)
+ - [Claude AI Integration](#claude-ai-integration)
+- [Community & Support](#community--support)
+- [Learn More](#learn-more)
- [License](#license)
-# Enable networking
+## Quick Start
-Modern browsers do not provide APIs to directly use TCP or UDP. WebVM provides networking support by integrating with Tailscale, a VPN network that supports WebSockets as a transport layer.
+### Online (No Installation)
-1. Open the "Networking" panel from the side-bar
-2. Click "Connect to Tailscale" from the panel
-3. Log in to Tailscale (create an account if you don't have one)
-4. Click "Connect" when prompted by Tailscale
+Visit [https://webvm.io](https://webvm.io) to get started immediately in your browser. No setup required.
-WebVM now has access to machines in your own local Tailscale Network!
+For local setup, custom image builds, and fork/deploy guidance, see [Development & Customization](#development--customization).
-## The world wide web
+## Networking
-If you would like to access the public internet, you will need to set up an Exit Node on one of your _non-WebVM_ tailscale network devices.
-See the _"Advertise a device as an exit node"_ section of the [Tailscale Exit Node quickstart guide](https://tailscale.com/kb/1408/quick-guide-exit-nodes?tab=linux) for instructions. (The _“Use an exit node”_ section can be skipped, as WebVM automatically uses an available exit node once one is advertised).
+WebVM now does something browsers usually cannot: it brings **Tailscale** networking into the VM itself, so your browser VM can reach your private network and, with an exit node, the public internet too.
> [!NOTE]
-> While we support most network commands there are a few that rely on kernel-level features not available in modern browsers and are therefore not supported, most notably `ping`.You could use `curl` or `wget` for testing instead.
-
-(Depending on your network speed, you may need to wait a few moments for the Tailscale Wasm module to be downloaded.)
-Once that is set up:
-1. Log in with your Tailscale credentials.
-2. Go back to the WebVM tab.
-3. The `Connect to Tailscale` button in the Networking side-panel should be replaced by your IP address.
+> Some low-level networking operations (especially ICMP used by `ping`) are not currently available in this environment. For connectivity checks, use `curl` or `wget`.
-> [!TIP]
-> You can also check your connection status by checking the dot colour on the "connect to tailscale" button (which should now show your tailscale IP). On local network connectivity it will be orange, global will be green.
+### Local network
-## Using an authkey
+1. Open the "Networking" panel from the sidebar
+2. Click "Connect to Tailscale"
+3. Log in (create a free account at [tailscale.com](https://tailscale.com) if needed)
+4. Click "Connect" when prompted
-As an alternative to manually logging in, you can add your tailscale auth Key at the end of the webvm URL.
+WebVM now has access to all machines in your Tailscale network!
-`https://webvm.io/#authKey=`
+> [!TIP]
+> On slower connections there may be a short delay before initialisation. Connection status is shown as a colored dot on the button: orange = local network, green = global/internet. The button text shows your Tailscale IP address once connected.
-It is recommended to use an ephemeral key.
+### Internet Access (Exit Node)
-## Selfhosting your tailscale network
+To access the public internet from WebVM, set up an **Exit Node** on another device in your Tailscale network:
-We also support [headscale](https://headscale.net/stable/), a selfhosted open source implementation of the Tailscale control server.
+1. Follow the [Tailscale Exit Node quickstart](https://tailscale.com/kb/1408/quick-guide-exit-nodes?tab=linux) (sections: "Advertise a device as an exit node")
+2. WebVM automatically uses the exit node once advertised
-Though as headscale unfortunately doesn't support adding CORS headers. You will have to set up a proxy server to add them. Headscales instructions on doing so can be found [here](https://headscale.net/stable/ref/integration/reverse-proxy/#nginx).
+### Using an Auth Key
-Once ready, add the following line to your `location /` block in your nginx config file.
+As an alternative to interactive login, add your Tailscale auth key to the URL fragment:
-``` Nginx
- if ($http_origin = "https://webvm.io") {
- add_header 'Access-Control-Allow-Origin' "$http_origin";
- add_header 'Access-Control-Allow-Credentials' 'true' always;
- }
+```
+https://webvm.io/#authKey=
```
+This is equivalent to Tailscale's `--login-server` option.
-To log in to your headscale network add `#controlUrl=` to the webVM url.
-
-**Notes:**
-
-- If self hosting, replace "https://webvm.io" with your own url.
-- This is equivelant to the tailscale `--login-server` command line option.
-- If used with authkey, don't forget to seperate the URL fragments with a `&` inbetween.
-
+> [!TIP]
+> If you also need a custom control server, add `controlUrl` in the same URL fragment and separate values with `&`, for example: `#authKey=...&controlUrl=...`.
-# Fork, deploy, customize
+### Self-Hosting Tailscale with Headscale
-
+We also support [headscale](https://headscale.net/stable/), a selfhosted open source implementation of the Tailscale control server.
+Because Headscale does not add CORS headers by default, you will need a proxy in front of it. See the [Headscale reverse proxy setup docs](https://headscale.net/stable/ref/integration/reverse-proxy/#nginx) for an example.
-- Fork the repository.
-- Enable Github pages in settings.
- - Click on `Settings`.
- - Go to the `Pages` section.
- - Select `Github Actions` as the source.
- - If you are using a custom domain, ensure `Enforce HTTPS` is enabled.
-- Run the workflow.
- - Click on `Actions`.
- - Accept the prompt. This is required only once to enable Actions for your fork.
- - Click on the workflow named `Deploy`.
- - Click `Run workflow` and then once more `Run workflow` in the menu.
-- After a few seconds a new `Deploy` workflow will start, click on it to see details.
-- After the workflow completes, which takes a few minutes, it will show the URL below the `deploy_to_github_pages` job.
+Once ready, add the following line to your `location /` block in your nginx config file.
-
+```nginx
+if ($http_origin = "https://yourdomain.com") {
+ add_header 'Access-Control-Allow-Origin' "$http_origin";
+ add_header 'Access-Control-Allow-Credentials' 'true' always;
+}
+```
-You can now customize `dockerfiles/debian_mini` to suit your needs, or make a new Dockerfile from scratch. Use the `Path to Dockerfile` workflow parameter to select it.
+Then access WebVM with:
-- If you would like to use our full desktop Alpine image, you can find it's dockerfile [**here**](https://github.com/leaningtech/alpine-image).
+```
+https://yourdomain.com/#controlUrl=
+```
-- For more information on creating custom images, see our [Custom disk Image documentation](https://cheerpx.io/docs/guides/custom-images).
+## Development & Customization
+### Local Serving & Image Configuration
-# Run WebVM locally with a custom Debian mini disk image
+If you are running WebVM locally, this is the primary flow.
-### 1. Clone the WebVM Repository
+#### 1. Clone the repository
```sh
git clone https://github.com/leaningtech/webvm.git
cd webvm
```
-### 2. Download the Debian mini Ext2 image
-
-Run the following command to download the Debian mini Ext2 image:
-
-```sh
-wget "https://github.com/leaningtech/webvm/releases/download/ext2_image/debian_mini_20230519_5022088024.ext2"
-```
-
-(*You can also build your own disk image by selecting the **"Upload GitHub release"** workflow option*)
+#### 2. Put your image in `custom-disk-images/`
-### 3. Update the configuration file
+This repository includes a persistent `custom-disk-images/` directory for local `.ext2` files.
- Edit `config_public_terminal.js` to reference your local disk image:
+To use the official Debian mini image, download it from Releases:
-- Replace:
-
- `"wss://disks.webvm.io/debian_large_20230522_5044875331.ext2"`
-
- With:
-
- `"/disk-images/debian_mini_20230519_5022088024.ext2"`
+[debian_mini_20230519_5022088024.ext2](https://github.com/leaningtech/webvm/releases/download/ext2_image/debian_mini_20230519_5022088024.ext2)
- (*Use an absolute or relative URL pointing to the disk image location.*)
+You can also copy in an image you built yourself.
+#### 3. Point WebVM to your local image
-- Replace `"cloud"` with the correct disk image type: `"bytes"`
+Edit `config_public_terminal.js`:
-
-### 4. Build WebVM
+```js
+export const diskImageUrl =
+ "/custom-disk-images/debian_mini_20230519_5022088024.ext2";
+export const diskImageType = "bytes";
+```
-Run the following commands to install dependencies and build WebVM:
+#### 4. Install dependencies and build
```sh
npm install
npm run build
```
-The output will be placed in the `build` directory.
-
-### 5. Configure Nginx
-
-- Create a directory for the disk image:
-
-```sh
-mkdir disk-images
-mv debian_mini_20230519_5022088024.ext2 disk-images/
-```
-
-- Modify your `nginx.conf` file to serve the disk image. Add the following location block:
-
-```nginx
-location /disk-images/ {
- root .;
- autoindex on;
-}
-```
-
-### 6, Start Nginx
-
-Run the following command to start Nginx:
+#### 5. Start Nginx and open WebVM
```sh
nginx -p . -c nginx.conf
```
-*Nginx will automatically serve the build directory.*
+Then open `http://127.0.0.1:8081` and enjoy your local WebVM!
+
+### Deploy to GitHub Pages
-### 7. Access WebVM
+Fork the WebVM repository to deploy your own version to GitHub Pages:
-Open a browser and visit: `http://127.0.0.1:8081`.
+
-Enjoy your local WebVM!
+1. **Fork the repository**
+2. **Enable GitHub Pages** in Settings → Pages using "GitHub Actions" as source
+3. **Run the `Deploy` workflow** from Actions
+4. After completion, open the URL shown under the `deploy_to_github_pages` job
----
+
+The same `Deploy` workflow also builds custom `.ext2` disk images from a Dockerfile. You can point it at `dockerfiles/debian_mini` or another Dockerfile, then either publish the result as a GitHub Release asset or deploy the Pages build from your fork.
+For the full Alpine desktop environment, see [leaningtech/alpine-image](https://github.com/leaningtech/alpine-image).
-# Example customization: Python3 REPL
+For more details, see [CheerpX Custom Images documentation](https://cheerpx.io/docs/guides/custom-images).
-The `Deploy` workflow takes into account the `CMD` specified in the Dockerfile. To build a REPL you can simply apply this patch and deploy.
+> [!TIP]
+> For Python3 REPL, the `Deploy` workflow takes into account the `CMD` specified in the Dockerfile.
+>
+> To build a REPL you can simply change `CMD [ "/bin/bash" ]` to `CMD [ "/usr/bin/python3" ]` and deploy.
-```diff
-diff --git a/dockerfiles/debian_mini b/dockerfiles/debian_mini
-index 2878332..1f3103a 100644
---- a/dockerfiles/debian_mini
-+++ b/dockerfiles/debian_mini
-@@ -15,4 +15,4 @@ WORKDIR /home/user/
- # We set env, as this gets extracted by Webvm. This is optional.
- ENV HOME="/home/user" TERM="xterm" USER="user" SHELL="/bin/bash" EDITOR="vim" LANG="en_US.UTF-8" LC_ALL="C"
- RUN echo 'root:password' | chpasswd
--CMD [ "/bin/bash" ]
-+CMD [ "/usr/bin/python3" ]
-```
+## Freatures
-# How to use Claude AI
+### Claude AI Integration
To access Claude AI, you need an API key. Follow these steps to get started:
-### 1. Create an account
-- Visit [Anthropic Console](https://console.anthropic.com/login) and sign up with your e-mail. You'll receive a sign in link to the Anthropic Console.
+#### 1. Create an account
-
+- Visit [Anthropic Console](https://console.anthropic.com/login) and sign up with your e-mail. You'll receive a sign in link to the Anthropic Console.
+
+#### 2. Get your API key
-### 2. Get your API key
- Once logged in, navigate to **Get API keys**.
- Purchase the amount of credits you need. After completing the purchase, you'll be able to generate the key through the API console.
-
+#### 3. Log in with your API key
-### 3. Log in with your API key
- Navigate to your WebVM and hover over the robot icon. This will show the Claude AI Integration tab. For added convenience, you can click the pin button in the top right corner to keep the tab in place.
- You'll see a prompt where you can insert your Claude API key.
-- Insert your key and press enter.
-
+#### 4. Start using Claude AI
-### 4. Start using Claude AI
- Once your API key is entered, you can begin interacting with Claude AI by asking questions such as:
- __"Solve the CTF challenge at `/home/user/chall1.bin.` Note that the binary reads from stdin."__
+**"Solve the CTF challenge at `/home/user/chall1.bin.` Note that the binary reads from stdin."**
-**Important:** Your API key is private and should never be shared. We do not have access to your key, which is not only stored locally in your browser.
+**Important:** Your API key is private and should never be shared. We do not have access to your key, it is only stored locally in your browser.
+
+## Community & Support
+
+**Report issues:** Use [GitHub Issues](https://github.com/leaningtech/webvm/issues) to report bugs or request features.
-# Bugs and Issues
+**Chat with us:** Join our [Discord community](https://discord.gg/yTNZgySKGa) to discuss WebVM, share ideas, and get help.
-Please use [Issues](https://github.com/leaningtech/webvm/issues) to report any bug.
-Or come to say hello / share your feedback on [Discord](https://discord.gg/yTNZgySKGa).
+## Learn More
-# More links
+**Articles & Resources:**
-- [WebVM: server-less x86 virtual machines in the browser](https://leaningtech.com/webvm-server-less-x86-virtual-machines-in-the-browser/)
+- [WebVM: Server-less x86 virtual machines in the browser](https://leaningtech.com/webvm-server-less-x86-virtual-machines-in-the-browser/)
- [WebVM: Linux Virtualization in WebAssembly with Full Networking via Tailscale](https://leaningtech.com/webvm-virtual-machine-with-networking-via-tailscale/)
- [Mini.WebVM: Your own Linux box from Dockerfile, virtualized in the browser via WebAssembly](https://leaningtech.com/mini-webvm-your-linux-box-from-dockerfile-via-wasm/)
-- Reference GitHub Pages deployment: [Mini.WebVM](https://mini.webvm.io)
-- [Crafting the Impossible: X86 Virtualization in the Browser with WebAssembly](https://www.youtube.com/watch?v=VqrbVycTXmw) Talk at JsNation 2022
+- [Crafting the Impossible: X86 Virtualization in the Browser with WebAssembly](https://www.youtube.com/watch?v=VqrbVycTXmw) — Talk at JsNation 2022
+
+**Example Deployment:**
+
+- [Mini.WebVM Reference](https://mini.webvm.io) — A running example deployed to GitHub Pages
+
+**Technology Behind WebVM:**
-# Thanks to...
-This project depends on:
-- [CheerpX](https://cheerpx.io/), made by [Leaning Technologies](https://leaningtech.com/) for x86 virtualization and Linux emulation
-- xterm.js, [https://xtermjs.org/](https://xtermjs.org/), for providing the Web-based terminal emulator
-- [Tailscale](https://tailscale.com/), for the networking component
-- [lwIP](https://savannah.nongnu.org/projects/lwip/), for the TCP/IP stack, compiled for the Web via [Cheerp](https://github.com/leaningtech/cheerp-meta/)
+This project is powered by:
-# Versioning
+- **[CheerpX](https://cheerpx.io/)** — x86-to-WebAssembly JIT compiler | by [Leaning Technologies](https://leaningtech.com/)
+- **[xterm.js](https://xtermjs.org/)** — Web-based terminal emulator
+- **[Tailscale](https://tailscale.com/)** — VPN networking layer
+- **[lwIP](https://savannah.nongnu.org/projects/lwip/)** — TCP/IP stack, compiled for the Web via [Cheerp](https://github.com/leaningtech/cheerp-meta/)
-WebVM depends on the CheerpX x86-to-WebAssembly virtualization technology, which is included in the project via [NPM](https://www.npmjs.com/package/@leaningtech/cheerpx).
+**Versioning:**
-The NPM package is updated on every release.
+WebVM uses the [CheerpX](https://www.npmjs.com/package/@leaningtech/cheerpx) NPM package, which is updated on every release.
-Every build is immutable, if a specific version works well for you today, it will keep working forever.
+Every build is immutable. If a specific version works well for you today, it will keep working forever.
-# License
+## License
WebVM is released under the Apache License, Version 2.0.
@@ -283,6 +244,6 @@ You are welcome to use, modify, and redistribute the contents of this repository
The public CheerpX deployment is provided **as-is** and is **free to use** for technological exploration, testing and use by individuals. Any other use by organizations, including non-profit, academia and the public sector, requires a license. Downloading a CheerpX build for the purpose of hosting it elsewhere is not permitted without a commercial license.
-Read more about [CheerpX licensing](https://cheerpx.io/docs/licensing)
+Read more [here](https://cheerpx.io/docs/licensing) about our licensing practices.
-If you want to build a product on top of CheerpX/WebVM, please get in touch: sales@leaningtech.com
+If you want to build a product on top of CheerpX/WebVM, please see our other licensing options: [CheerpX licensing](https://cheerpx.io/licensing) or get in touch: sales@leaningtech.com
diff --git a/config_public_terminal.js b/config_public_terminal.js
index 0d8cc8768..2c49d4a71 100644
--- a/config_public_terminal.js
+++ b/config_public_terminal.js
@@ -1,6 +1,6 @@
-// The root filesystem location
+// The root OS image location, change to local filepath if serving locally
export const diskImageUrl = "wss://disks.webvm.io/debian_large_20230522_5044875331_2.ext2";
-// The root filesystem backend type
+// The root filesystem backend type use "cloud" for serving remotely or "bytes" for serving locally
export const diskImageType = "cloud";
// Print an introduction message about the technology
export const printIntro = true;
diff --git a/nginx.conf b/nginx.conf
index 6ab81c53b..b828a3677 100644
--- a/nginx.conf
+++ b/nginx.conf
@@ -32,8 +32,7 @@ http {
server_name localhost;
gzip on;
- # Enable compression for .wasm, .js and .txt files (used for the runtime chunks)
- gzip_types application/javascript application/wasm text/plain
+ gzip_types application/javascript application/wasm text/plain;
charset utf-8;
@@ -48,5 +47,8 @@ http {
add_header 'Cross-Origin-Embedder-Policy' 'require-corp' always;
add_header 'Cross-Origin-Resource-Policy' 'cross-origin' always;
}
+ location /custom-disk-images/ {
+ root .;
+ }
}
}