UserVM Handbook/Windows

From Computernewb Wiki
Jump to navigation Jump to search

This guide details how to set up a UserVM on a host machine running Microsoft Windows.

The Rules

First, the boring part. We ask that all hosts review and follow the UserVM Hosting Rules.

Prerequisites

You'll need:

  • A machine with decent specs (8GB of RAM and a modern CPU, probably)
  • Microsoft Windows 10 or later. For Linux, see the main UserVM Handbook.
  • A decently fast network that allows you to forward a port. We will not accept UserVMs behind services like ngrok. Cloudflare tunnels are fine. You must also have a URL that stays persistent. If your IP is dynamic, you can use services like NOIP or setup a script to auto-update your domain using cloudflare.
  • Basic knowledge of how computers and Windows systems work. We aren't going to hold your hand, you need to be comfortable with a command line
    • IF YOU DO NOT UNDERSTAND HOW TO FOLLOW THE INSTRUCTIONS IN THIS GUIDE, DO NOT HOST PUBLIC INTERNET CONNECTED VMS ON THE INTERNET THAT ANYONE CAN ACCESS
  • A few hours

Compiling the server

Install dependencies

Open Command Prompt as administrator.

First, install the Chocolatey package manager. If you already have it installed, you can skip this step.

powershell -c "Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))"

Restart CMD to apply the changes to PATH. Now, we'll install the various dependencies CollabVM has:

choco install qemu git nasm cmake nodejs nssm rust-ms visualstudio2019-workload-vctools
refreshenv

Enable corepack:

corepack enable

Prepare the server

We can now get the server ready. First, create a directory for all CollabVM related files. For the purposes of this guide, we use C:\collabvm. If you use a different directory, be sure to substitute it in all future commands.

mkdir C:\collabvm

Clone the CollabVM server source:

git clone https://github.com/computernewb/collabvm-1.2.ts.git C:\collabvm\collabvm-1.2.ts --depth 1 --recursive
cd C:\collabvm\collabvm-1.2.ts

Install dependencies and build the server:

yarn
yarn build

Set up your VM

Now is a good time to get your VM set up. Currently, the only supported hypervisor is QEMU. We have many guides on this wiki for setting up different OSes in QEMU, check them out here. Here are some ideas to make your VM interesting:

  • A funny wallpaper
  • Development software (Visual Studio, etc.)
  • Some games
  • Some harmless malware (for the love of god no GDI rapists)

Windows Hypervisor Support

By default, QEMU uses the TCG software emulator, which is very slow. You can greatly increase the speed of your VM by enabling Windows Hypervisor.

First, enable the Windows Hypervisor:

dism /online /enable-feature /featurename:HypervisorPlatform

Reboot your system to apply changes

Now, you can enable WHPX hypervision by using the -accel whpx argument somewhere in your QEMU command line. If you're copying your QEMU command from somewhere that expects KVM (which is the Linux equivalent to the Windows Hypervisor), make sure you REPLACE the -accel kvm with -accel whpx in the command or it will not run.

Note that there is also a fork of QEMU that uses the Android Emulator Hypervisor Driver, which may be faster than the Windows Hypervisor but is also known to be very buggy.

Multi-threaded TCG

QEMU with the Windows Hypervisor tends to be very unstable and may not work on your system at all. (This is one of the reasons we strongly recommend that you use a Linux host) In this case, you can still achieve some performance by using -accel tcg,thread=multi, although it still won't be anywhere near native speeds.

Setting up a Virtual Network

QEMU's user-mode networking used by default isn't very customizable and lacks the ability to block certain abuse vectors. For this reason we very strongly recommend setting up a Virtual Network using the CollabNet Guide. Depending on the full situation we may refuse to add VMs that use QEMU user-mode networking.

It's also VERY important that mail ports are BLOCKED on your VM (the CollabNet guide config includes this). If you do not block them, your IP effectively becomes an open relay which will very likely get you suspended by your ISP or hosting provider. We will not add VMs with accessible mail ports

The following is the Windows version of the Host Preparation section of the CollabNet Guide.

IP Forwarding

First, we're going to enable IP forwarding on your host. This will allow traffic from the VMs to be routed to and from the router. The following command will write this to the registry.

reg add HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters /v IPEnableRouter /d 1 /t REG_DWORD /f

Reboot your system.

Bridge configuration

Next, we'll set up a network bridge with multiple TAP interfaces. You can think of a TAP interface as a virtual Ethernet port connected to your VM, and the network bridge as a virtual Ethernet switch connecting them all together.

First, install OpenVPN, which contains the TAP driver for Windows:

choco install openvpn
refreshenv

Now, create a TAP interface for the router and each of your VMs:

cd "C:\Program Files\OpenVPN\bin"
tapctl create --name ktrouter
tapctl create --name ktvm1
(...)

The last step is to bridge all of our TAP interfaces together. For some reason Microsoft decided you can't do this from the command line, so go ahead and open the Network Connections control panel:

ncpa.cpl

You should see a list of network adapters. Hold down the Ctrl key and click each of the TAP interfaces we created (ktrouter, ktvm1) to select them. Now, right click one of them and select Bridge Connections to create the bridge

Now, simply right click the new Network Bridge and rename it something friendly, like collabnet.

If you add new TAPs in the future, simply right click the collabnet bridge and go to properties, and tick the new TAP in the Adapters list.

You can now continue from the Router section of the CollabNet Guide, with some obvious adjustments for windows.

Configuration

Now we need to fill out the config file for your VM. Copy config.example.toml to config.toml, and open it in an editor. It is well commented so each value should be self-explanatory. If you have questions, feel free to ask in our Discord server.

QEMU Args

On Windows, if QEMU is installed to the default directory, you'll need to configure your qemuArgs like this:

qemuArgs = "C:\\Program\ Files\\QEMU\\qemu-system-x86_64.exe [args]"

Example of a production QEMU command:

qemuArgs = "C:\\Program\ Files\\QEMU\\qemu-system-x86_64.exe -M q35,usb=on,acpi=on,hpet=off -cpu host -accel whpx -m 2G -smp cores=2 -device usb-tablet -nic none -hda C:\\collabvm\\images\\vm1.qcow2"

Running your VM

Now that everything is set up, you can bring your VM online. To run the server right from your terminal, run the following command:

yarn serve

Or alternatively, to run it directly:

node cvmts/dist/index.js

Running a local webapp

Before you put your VM on the UserVM roster, you'll probably want to test it out for yourself. For that, we'll throw up a test webapp. Start by cloning the source:

cd C:\collabvm
git clone https://github.com/computernewb/collab-vm-1.2-webapp.git --recursive
cd collab-vm-1.2-webapp

Then, copy config.example.json to config.json, and replace ServerAddresses with your server address:

    "ServerAddresses": [
        "ws://127.0.0.1:6004",
    ],

Now you can build the webapp, and serve it:

yarn
yarn build
yarn serve

This will run the webapp at 127.0.0.1:1234, which you can navigate to in your browser. If all went well, your VM should show up. If not, and you don't know why, join our discord and ask for help there!

Setting up a service

We will now set your VM up as a background service using the NSSM runner.

In admin CMD:

nssm install collabvm

This will open the NSSM setup GUI. Configure each page as follows

Application

Path: C:\Program Files\nodejs\node.exe

Startup directory: C:\collabvm\collabvm-1.2.ts

Arguments: C:\collabvm\collabvm-1.2.ts\cvmts\dist\index.js

Details

Startup type: Automatic if you want your VM to start with your computer, Manual if you want to start it manually

Log on

Log on as: Virtual Service Account (very important for security)

I/O

Output (stdout): C:\collabvm\out.log

Error (stderr): C:\collabvm\err.log


Permissions

Give the CollabVM Virtual Service User permissions to the C:\collabvm directory:

icacls C:\collabvm /grant "NT SERVICE\collabvm:F" /Q /C /T

NOTE: If you encounter permissions errors when running the CollabVM service after adding new VM images, run this command again.

Starting the service

You can now start your VM with:

net start collabvm

And stop it with:

net stop collabvm

Setting up reverse proxying

This is REQUIRED for UserVM as, for technical reasons, only TLS-equipped WebSockets can be accepted

We strongly recommend you proxy your UserVM behind Nginx, to provide additional security and allow things like TLS. It also makes your VM look a lot cleaner, allowing people to access it on your main HTTP(s) port and on a subdirectory, like https://example.com/collab-vm/ rather than http://example.com:6004. Here's a brief tutorial of how to set that up on the Nginx side.

This assumes you're setting up a Nginx site from scratch. If not, you can skip most of this and just add the relevant config snippets to your configuration.

First, you'll need to acquire a domain. You can also get free subdomains from https://freedns.afraid.org. Make sure your domain or subdomain is pointed to your IP address and ports are open.

Next, install nginx:

choco install nginx

Then, you'll want to save wsproxy_params to your Nginx directory, which enables WebSocket proxying.

cd C:\tools\nginx*
curl https://computernewb.com/~elijah/wsproxy_params -o wsproxy_params

If you use Cloudflare reverse proxying, make SURE to open this file and uncomment the indicated line.

Create a directory to store site configurations:

mkdir sites

Open up conf\nginx.conf and add the following to the bottom of your http { ... } block:

map $http_upgrade $connection_upgrade {  
    default upgrade;
    ''      close;
}
include ../sites/*.conf;

Now, create a configuration for your nginx site that includes a proxy statement for your VM.

C:\tools\nginx-[version]\sites\example.com.conf

server {
    server_name example.com;
    listen 80;
    index index.html;
    # You can change this to the absolute path of your site's webroot, or leave it if you don't have a site other than CollabVM
    root html;

    location /collab-vm/vm1 {
        include ../wsproxy_params;
        proxy_pass http://127.0.0.1:6004/; 
    }
}

The last step is to set up SSL (if you use Cloudflare reverse proxying you can skip this as Cloudflare will handle SSL for you). Install win-acme:

choco install win-acme
refreshenv

Create a directory for the SSL certs:

mkdir ssl

Grab the certs. Example command:

wacs --host example.com (REPLACE WITH YOUR DOMAIN) --webroot html (REPLACE WITH YOUR WEBROOT IF YOU CHANGED IT) --validation filesystem --source manual --store pemfiles --pemfilespath ssl --accepttos

Install the certs to your nginx conf:

C:\tools\nginx-[version]\sites\example.com.conf

server {
    server_name example.com;
    listen 80;
    listen 443 ssl;
    ssl_certificate ../ssl/example.com-chain.pem;
    ssl_certificate_key ../ssl/example.com-key.pem;
}

Finally, restart nginx to apply the config

net stop nginx
net start nginx

If all went well, your VM is now available at wss://example.com/collab-vm/vm1

Permanently host the webapp

If you want to host the webapp on your website, you can build it as follows:

cd C:\collabvm\collab-vm-1.2-webapp
yarn build

Then, copy the contents of the dist directory to your website. For example, if your webroot is at /var/www/example.com, and you want your webapp at example.com/collab-vm/:

xcopy /S /Y dist C:\path\to\your\webroot\collab-vm\

The webapp should now be accessible at your website.

Logging in as an admin (or mod)

Logging in is very simple. Just join the VM, and double click your username. Enter your admin or mod password into the prompt, and you should be authenticated and able to use staff actions.

Getting your UserVM on the roster

Now you can have your UserVM put on the roster! Join our Discord, and create a post in #support with the uservm roster update tag, including your VM's WebSocket URL. You can ping me (@elijahr.dev) if you'd like.