UserVM Handbook: Difference between revisions
No edit summary |
(add KillMode=mixed to .service template) |
||
(26 intermediate revisions by 2 users not shown) | |||
Line 6: | Line 6: | ||
*A machine with decent specs (8GB of RAM and a modern CPU, probably) |
*A machine with decent specs (8GB of RAM and a modern CPU, probably) |
||
*A Linux distribution; You can pick any mainstream distro, for the purposes of this guide I recommend either Debian or Arch, or their OpenRC counterparts if you prefer OpenRC. Yes, Ubuntu will work, it's terrible though |
*A Linux distribution; You can pick any mainstream distro, for the purposes of this guide I recommend either Debian or Arch, or their OpenRC counterparts if you prefer OpenRC. Yes, Ubuntu will work, it's terrible though |
||
** If you REALLY want to run CollabVM on Windows, there is an unofficial and unsupported guide for that at [[UserVM Handbook/Windows]] |
|||
*A decently fast network that allows you to forward a port. We will not accept UserVMs behind services like ngrok. 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. |
|||
*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 Linux systems work. We aren't going to hold your hand, you need to be comfortable with a command line |
*Basic knowledge of how computers and Linux 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 |
*A few hours |
||
== Compiling the server<br> == |
== Compiling the server<br> == |
||
=== Install |
=== Install Dependencies === |
||
First up make sure you have git installed |
First up make sure you have git, nasm, cmake, and a C(++) compiler installed |
||
{{code|lang=bash| |
{{code|lang=bash| |
||
sudo pacman - |
$ sudo pacman --needed --noconfirm -Sy git nasm base-devel cmake # Arch |
||
sudo apt-get install -y git # Debian |
$ sudo apt-get install -y git nasm build-essential cmake # Debian |
||
}} |
}} |
||
Next, we need to install Node.js. |
|||
=== Prepare the server === |
|||
Now let's clone the source. It's recommended that you do this somewhere like /srv/collabvm or /home/collabvm. For the purposes of this guide we'll use the former. |
|||
{{code| |
|||
sudo mkdir -p /srv/collabvm |
|||
sudo chown -R $USER /srv/collabvm # Temporary, we'll change this to a dedicated CollabVM user later |
|||
git clone https://github.com/computernewb/collabvm-1.2.ts.git /srv/collabvm/collabvm-1.2.ts |
|||
cd /srv/collabvm/collabvm-1.2.ts |
|||
}} |
|||
Next, we need to install Node.js, as well as the server dependencies. |
|||
First, we'll install node. On arch, you can just run the following command: |
First, we'll install node. On arch, you can just run the following command: |
||
{{code| |
{{code| |
||
sudo pacman --needed -S npm nodejs |
$ sudo pacman --needed -S npm nodejs |
||
}} |
}} |
||
On Debian, the packaged node version is too old to run CollabVM, so we'll add the nodesource repository. |
On Debian, the packaged node version is too old to run CollabVM, so we'll add the nodesource repository. |
||
{{code|<nowiki> |
{{code|<nowiki> |
||
sudo apt-get install -y |
$ sudo apt-get install -y curl |
||
$ curl -fsSL https://deb.nodesource.com/setup_21.x | sudo bash - |
|||
sudo mkdir -p /etc/apt/keyrings |
|||
$ sudo apt-get install nodejs -y |
|||
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg |
|||
NODE_MAJOR=20 |
|||
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list |
|||
sudo apt-get update |
|||
sudo apt-get install nodejs -y |
|||
</nowiki>}} |
</nowiki>}} |
||
Enable Corepack: |
|||
{{code|<nowiki> |
|||
$ sudo corepack enable |
|||
</nowiki>}} |
|||
=== Prepare the server === |
|||
Now let's get the server ready. First, we'll create a dedicated CollabVM user to run the server from <code>/srv/collabvm</code>: |
|||
{{code| |
|||
$ sudo useradd -rmd /srv/collabvm collabvm |
|||
$ sudo usermod -aG kvm collabvm # Give the CollabVM user permission to use KVM hypervision |
|||
}} |
|||
Now, we can shell in as the CollabVM user. For the remainder of this guide, any line that starts with <code>(collabvm) $</code> indicates that this should be run as the <code>collabvm</code> user. |
|||
{{code| |
|||
$ sudo -iu collabvm |
|||
(collabvm) $ pwd # This should output /srv/collabvm |
|||
}} |
|||
Install the Rustup toolchain for the CollabVM user: |
|||
{{code|lang=bash|<nowiki> |
|||
(collabvm) $ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh |
|||
# Restart the shell to apply changes |
|||
(collabvm) $ exit |
|||
$ sudo -iu collabvm |
|||
</nowiki>}} |
|||
Now, we can clone the CollabVM Server source code: |
|||
{{code| |
|||
(collabvm) $ git clone https://github.com/computernewb/collabvm-1.2.ts.git /srv/collabvm/collabvm-1.2.ts --depth 1 --recursive |
|||
(collabvm) $ cd /srv/collabvm/collabvm-1.2.ts |
|||
}} |
|||
Then install dependencies |
Then install dependencies |
||
{{code| |
{{code| |
||
(collabvm) $ yarn |
|||
npm i |
|||
}} |
}} |
||
Finally, build the server |
Finally, build the server |
||
{{code| |
{{code| |
||
(collabvm) $ yarn build |
|||
}} |
}} |
||
== Set up your VM == |
== 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, [[QEMU/Guests|check them out here.]] |
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, [[QEMU/Guests|check them out here.]] |
||
Line 55: | Line 75: | ||
*Some games |
*Some games |
||
*Some harmless malware (for the love of god no GDI rapists) |
*Some harmless malware (for the love of god no GDI rapists) |
||
We recommend setting up your VM as the collabvm user to make sure permissions are set correctly, but this is not a requirement. |
|||
== Setting up a Virtual Network == |
== 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. |
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. |
||
Line 60: | Line 82: | ||
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 |
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 |
||
== Configuration == |
== 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. |
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. |
||
<!-- Wikitext table syntax is SO ass I'll stick to HTML thanks --> |
|||
<table class="wikitable"> |
|||
<tr><th>Config value</th><th>Explanation</th></tr> |
|||
<tr><td>host</td><td>Host IP for the server to bind to. 99% of the time this will be 127.0.0.1 on proxied instances and 0.0.0.0 on non-proxied (see below)</td></tr> |
|||
<tr><td>port</td><td>Port for your server to bind to. This must be different for each VM you host, and cannot be the same as any other server running on your system (see the output of <code>ss -tuln</code> to see what ports are used)</td></tr> |
|||
<tr><td>proxying</td><td>If your server will be behind a reverse proxy, usually Nginx. This isn't a requirement, however, we recommend you do so for things like SSL support, and minimizing the number of ports open on your server. This requires additional configuration of your web server. If you edit this, make sure to go back and update <code>host</code> accordingly</td></tr> |
|||
<tr><td>proxyAllowedIps</td><td>IPs allowed to reverse proxy your server. Can be ignored if you're not using proxying mode. 99% of the time, this will just be 127.0.0.1</td></tr> |
|||
<tr><td>qemuArgs</td><td>Command line to launch QEMU with. You'll have this from setting up your VM earlier. If you're not sure, check out the QEMU guides linked above</td></tr> |
|||
<tr><td>vncPort</td><td>Port to be used internally for VNC. Must be at least 5900. You don't need to pay too much attention to this unless you're running multiple VMs (In which case just increment the port by 1 for each VM)</td></tr> |
|||
<tr><td>snapshots</td><td>Whether or not your VM should have vote resets, and reset to its initial state on server restart. If you disable this on a public VM, prepare for it to get trashed quickly.</td></tr> |
|||
<tr><td>qmpSockDir</td><td>Directory for QEMU to put its QMP socket for internal use. This can stay default unless you have a special reason to change it</td></tr> |
|||
<tr><td>node</td><td>A unique ID for your VM. Your VM will be directly accessible at <code>https://computernewb.com/collab-vm/user-vm/#<this id></code>. You should take care to name this something separate from any other VM on the UserVM roster, or your VM might be unaccessible</td></tr> |
|||
<tr><td>displayname</td><td>VM title that shows up in the list. Format with HTML</td></tr> |
|||
<tr><td>motd</td><td>Message of the day, displayed when someone joins your VM. Format with HTML</td></tr> |
|||
<tr><td>bancmd</td><td>Command to be run when you click the ban button. By default this adds a non-persistent iptables rule, but we recommend you change this</td></tr> |
|||
<tr><td>moderatorEnabled</td><td>Whether or not the moderator rank is enabled, in addition to Admin.</td></tr> |
|||
<tr><td>usernameblacklist</td><td>Array of usernames the server should not allow</td></tr> |
|||
<tr><td>maxChatLength</td><td>Max amount of characters a user can send in a chat message. Further characters will be truncated.</td></tr> |
|||
<tr><td>automute</td><td>Whether or not the server should automatically mute users who spam messages. You can also specify how many messages within how many seconds should trigger the mute.</td></tr> |
|||
<tr><td>tempMuteTime</td><td>How long a temporary mute lasts</td></tr> |
|||
<tr><td>turnTime</td><td>How long a turn lasts</td></tr> |
|||
<tr><td>voteTime</td><td>How long a vote to reset lasts, before results are tallied</td></tr> |
|||
<tr><td>voteCooldown</td><td>How long before another reset vote can be started after one ends</td></tr> |
|||
<tr><td>adminpass</td><td>SHA256 hash of your admin password. Can be generated with the command <code>printf "<your admin password"> | sha256sum -</code>. Make sure this is something hard to guess as anyone with this password could execute arbitrary commands on your server.</td></tr> |
|||
<tr><td>modpass</td><td>SHA256 hash of your mod password. Generated same as admin. Does nothing if the moderator rank is not enabled.</td></tr> |
|||
<tr><td><b>moderatorPermissions</b></td><td>Controls the individual actions a moderator can do. Each one is described below. Does nothing if the moderator rank is not enabled.</td></tr> |
|||
<tr><td>restore</td><td>Reset the VM back to it's initial state.</td></tr> |
|||
<tr><td>reboot</td><td>Reboot the VM</td></tr> |
|||
<tr><td>ban</td><td>Ban a user from your VM</td></tr> |
|||
<tr><td>forcevote</td><td>Forcibly pass or cancel a vote to reset</td></tr> |
|||
<tr><td>mute</td><td>Mute a user, preventing them from chatting or taking turns</td></tr> |
|||
<tr><td>kick</td><td>Kick a user from the VM</td></tr> |
|||
<tr><td>bypassturn</td><td>Jump to the front of the turn queue, as well as clear the turn queue and end individual turns</td></tr> |
|||
<tr><td>rename</td><td>Rename another user</td></tr> |
|||
<tr><td>grabip</td><td>Get the IP address of another user</td></tr> |
|||
<tr><td>xss</td><td>Send a raw (not HTML-sanitized) chat message, allowing the execution of arbitrary scripts on another user's browser. Admins will not be affected by XSS messages sent by mods.</td></tr> |
|||
</table> |
|||
=== Setting up reverse proxying (Optional) === |
|||
'''This is REQUIRED for UserVM as, for technical reasons, only SSL-equipped WebSockets can be accepted''' |
|||
=== QEMU Args === |
|||
We strongly recommend you proxy your UserVM behind Nginx, to provide additional security and allow things like SSL. 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 <code>https://yoursite.xyz/collab-vm/</code> rather than <code>http://yoursite.xyz:6004</code>. Here's a brief description of how to set that up on the Nginx side. This assumes you already have your site set up with Nginx, and if not there are numerous guides for that around the internet. |
|||
Example of a production QEMU command: |
|||
First, you'll want to save [https://computernewb.com/~elijah/wsproxy_params wsproxy_params] to your Nginx directory, which enables WebSocket proxying. Here's a one-liner to do that: |
|||
{{code|lang=toml|<nowiki> |
|||
qemuArgs = "qemu-system-x86_64 -M q35,usb=on,acpi=on,hpet=off -cpu host -accel whpx -m 2G -smp cores=2 -device usb-tablet -nic none -hda /srv/collabvm/images/vm1.qcow2" |
|||
</nowiki>}} |
|||
<!-- expansion on this is tbd --> |
|||
Additionally, it is possible to use [https://github.com/modeco80/lilyvm LilyVM] to help with building more complex VM configurations. |
|||
== 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: |
|||
{{code| |
{{code| |
||
(collabvm) $ yarn serve |
|||
sudo curl https://computernewb.com/~elijah/wsproxy_params -o /etc/nginx/wsproxy_params |
|||
}} |
}} |
||
Or alternatively, to run it directly: |
|||
Next, you can add the following to your Nginx server block: |
|||
{{code| |
{{code| |
||
(collabvm) $ node cvmts/dist/index.js |
|||
location /collab-vm/ { |
|||
include wsproxy_params; |
|||
proxy_pass http://127.0.0.1:6004/; # Replace 6004 if you changed the HTTP port in the config file. |
|||
} |
|||
}} |
}} |
||
== Running a local webapp == |
|||
If you get an error about <code>connection_upgrade</code>, edit <code>/etc/nginx/nginx.conf</code> and add the following to your http block: |
|||
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: |
|||
{{code| |
{{code| |
||
$ git clone https://github.com/computernewb/collab-vm-1.2-webapp.git --recursive |
|||
map $http_upgrade $connection_upgrade { |
|||
$ cd collab-vm-1.2-webapp |
|||
default upgrade; |
|||
'' close; |
|||
} |
|||
}} |
}} |
||
Then, copy <code>config.example.json</code> to <code>config.json</code>, and replace ServerAddresses with your server address: |
|||
If you have multiple VMs running, you can have them all proxied like so: |
|||
{{code| |
{{code| |
||
"ServerAddresses": [ |
|||
location /collab-vm/vm1 { |
|||
"ws://127.0.0.1:6004", # If you're not using proxying |
|||
include wsproxy_params; |
|||
"wss://example.com/collab-vm/vm1" # If you are using proxying. Remove one of these lines. |
|||
proxy_pass http://127.0.0.1:6004/; |
|||
], |
|||
} |
|||
location /collab-vm/vm2 { |
|||
include wsproxy_params; |
|||
proxy_pass http://127.0.0.1:6005/; |
|||
} |
|||
# ...etc |
|||
}} |
}} |
||
Now you can build the webapp, and serve it: |
|||
== 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: |
|||
{{code| |
{{code| |
||
$ yarn |
|||
npm run serve |
|||
$ yarn build |
|||
$ yarn serve |
|||
}} |
}} |
||
This will run the webapp at <code>127.0.0.1:1234</code>, 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! |
|||
Or alternatively, to run it directly: |
|||
== Setting up a service == |
|||
{{code| |
|||
node build/index.js |
|||
}} |
|||
=== Setting up a service === |
|||
While it's useful and convenient to run your VM from the console while debugging, we <b>strongly</b> recommend you set it up as a service once you're ready to leave it on for extended periods of time. This is done differently depending on what init system your distro uses (Probably systemd, if you're not sure) |
While it's useful and convenient to run your VM from the console while debugging, we <b>strongly</b> recommend you set it up as a service once you're ready to leave it on for extended periods of time. This is done differently depending on what init system your distro uses (Probably systemd, if you're not sure) |
||
=== Systemd === |
|||
First, we highly recommend you create a separate user for CollabVM, to maximize security |
|||
To make your VM a systemd service, you can put the following into <code>/etc/systemd/system/collabvm.service</code> |
|||
{{code| |
|||
sudo useradd -rM collabvm |
|||
sudo chown -R collabvm:collabvm /srv/collabvm/ # Set the collabvm user as the owner of the server files |
|||
sudo usermod -aG kvm collabvm # Give the CollabVM user permission to use KVM hypervision |
|||
}} |
|||
==== Systemd ==== |
|||
To make your VM a systemd service, you can put the following into <code>/etc/systemd/system/collabvm.service</code> (Change the filename accordingly) |
|||
{{code|<nowiki> |
{{code|<nowiki> |
||
Line 161: | Line 135: | ||
[Service] |
[Service] |
||
Restart=always |
|||
Type=simple |
Type=simple |
||
User=collabvm |
User=collabvm |
||
Group=collabvm |
Group=collabvm |
||
KillMode=mixed |
|||
Restart=always |
|||
RestartSec=5 |
|||
# Make sure to change the following two lines according to where you put your server. |
# Make sure to change the following two lines according to where you put your server. |
||
# If you have multiple VMs, |
# If you have multiple VMs, it's possible to make your service file a template unit file (by making the file name, for example, "[email protected]"), and use %i in WorkingDirectory |
||
# allowing you to use the same server for all your VMs. |
# to automatically set WorkingDirectory to a different directory for each VM, allowing you to use the same server for all your VMs. |
||
WorkingDirectory=/srv/collabvm/collabvm-1.2.ts/ |
WorkingDirectory=/srv/collabvm/collabvm-1.2.ts/ |
||
ExecStart=/bin/node /srv/collabvm/collabvm-1.2.ts/ |
ExecStart=/bin/node /srv/collabvm/collabvm-1.2.ts/cvmts/dist/index.js |
||
# Tell systemd that we manage our own cgroup hierarchy, and delegate |
|||
# all controllers that are either implicitly or explicitly enabled. |
|||
# |
|||
# This is used for resource limits (in your VM's config.toml). |
|||
# Can be omitted if you are not using it. (It's probably a good idea to however!) |
|||
Delegate=yes |
|||
# Hardening |
|||
PrivateTmp=yes |
|||
NoNewPrivileges=true |
|||
RestrictNamespaces=uts ipc pid user cgroup |
|||
ProtectKernelTunables=yes |
|||
ProtectKernelModules=yes |
|||
PrivateDevices=no |
|||
RestrictSUIDSGID=true |
|||
[Install] |
[Install] |
||
Line 177: | Line 172: | ||
Reload the daemon cache: |
Reload the daemon cache: |
||
{{code| |
{{code| |
||
sudo systemctl daemon-reload |
$ sudo systemctl daemon-reload |
||
}} |
}} |
||
Then you can start your VM with: |
Then you can start your VM with: |
||
{{code| |
{{code| |
||
sudo systemctl start collabvm |
$ sudo systemctl start collabvm |
||
}} |
}} |
||
And make it automatically run on startup with: |
And make it automatically run on startup with: |
||
{{code| |
{{code| |
||
sudo systemctl enable collabvm |
$ sudo systemctl enable collabvm |
||
}} |
}} |
||
=== OpenRC === |
|||
Put the following into /etc/init.d/collabvm to make your VM an OpenRC service (change filename as appropriate): |
Put the following into /etc/init.d/collabvm to make your VM an OpenRC service (change filename as appropriate): |
||
{{code|<nowiki> |
{{code|<nowiki> |
||
Line 195: | Line 190: | ||
name="collabvm" |
name="collabvm" |
||
command="/bin/node" |
command="/bin/node" |
||
command_args="/srv/collabvm/collabvm-1.2.ts/ |
command_args="/srv/collabvm/collabvm-1.2.ts/cvmts/dist/index.js" |
||
# If you have multiple VMs, you can change --chdir to a different directory on each VM, to use different config files on the same server |
# If you have multiple VMs, you can change --chdir to a different directory on each VM, to use different config files on the same server |
||
supervise_daemon_args="--user collabvm --group collabvm --chdir /srv/collabvm/collabvm-1.2.ts --stdout /srv/collabvm/out.log --stderr /srv/collabvm/error.log" |
supervise_daemon_args="--user collabvm --group collabvm --chdir /srv/collabvm/collabvm-1.2.ts --stdout /srv/collabvm/out.log --stderr /srv/collabvm/error.log" |
||
Line 201: | Line 196: | ||
Make it executable: |
Make it executable: |
||
{{code| |
{{code| |
||
sudo chmod +x /etc/init.d/collabvm |
$ sudo chmod +x /etc/init.d/collabvm |
||
}} |
}} |
||
Now you can start your VM with: |
Now you can start your VM with: |
||
{{code| |
{{code| |
||
sudo rc-service collabvm start |
$ sudo rc-service collabvm start |
||
}} |
}} |
||
And make it run on startup with: |
And make it run on startup with: |
||
{{code| |
{{code| |
||
sudo rc-update add collabvm |
$ sudo rc-update add collabvm |
||
}} |
}} |
||
== |
== Setting up reverse proxying == |
||
'''This is REQUIRED for UserVM as, for technical reasons, only TLS-equipped WebSockets can be accepted''' |
|||
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: |
|||
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 <code>https://example.com/collab-vm/</code> rather than <code>http://example.com:6004</code>. Here's a brief description of how to set that up on the Nginx side. This assumes you already have your site set up with Nginx, and if not there are numerous guides for that around the internet. |
|||
First, you'll want to save [https://computernewb.com/~elijah/wsproxy_params wsproxy_params] to your Nginx directory, which enables WebSocket proxying. Here's a one-liner to do that: |
|||
{{code| |
{{code| |
||
$ sudo curl https://computernewb.com/~elijah/wsproxy_params -o /etc/nginx/wsproxy_params |
|||
git clone https://github.com/computernewb/collab-vm-1.2-webapp.git |
|||
cd collab-vm-1.2-webapp |
|||
}} |
}} |
||
Next, you can add the following to your Nginx server block: |
|||
{{code| |
{{code| |
||
location /collab-vm/vm1 { |
|||
serverAddresses: [ |
|||
include wsproxy_params; |
|||
"ws://127.0.0.1:6004", # If you're not using proxying |
|||
proxy_pass http://127.0.0.1:6004/; # Replace 6004 if you changed the HTTP port in the config file. |
|||
} |
|||
] |
|||
}} |
}} |
||
If you get an error about <code>connection_upgrade</code>, edit <code>/etc/nginx/nginx.conf</code> and add the following to your http block: |
|||
Now you can build the webapp, and serve it: |
|||
{{code| |
|||
map $http_upgrade $connection_upgrade { |
|||
default upgrade; |
|||
'' close; |
|||
} |
|||
}} |
|||
If you have multiple VMs running, you can have them all proxied like so: |
|||
{{code| |
|||
location /collab-vm/vm1 { |
|||
include wsproxy_params; |
|||
proxy_pass http://127.0.0.1:6004/; |
|||
} |
|||
location /collab-vm/vm2 { |
|||
include wsproxy_params; |
|||
proxy_pass http://127.0.0.1:6005/; |
|||
} |
|||
# ...etc |
|||
}} |
|||
== Permanently host the webapp == |
|||
If you want to host the webapp on your website, you can build it as follows: |
|||
{{code| |
|||
$ yarn build |
|||
}} |
|||
Then, copy the contents of the <code>dist</code> directory to your website. For example, if your webroot is at <code>/var/www/example.com</code>, and you want your webapp at example.com/collab-vm/: |
|||
{{code| |
{{code| |
||
$ cp -r dist/. /var/www/example.com/collab-vm/ |
|||
npm run build |
|||
npm run serve |
|||
}} |
}} |
||
The webapp should now be accessible at your website. |
|||
This will run the webapp at <code>127.0.0.1:3000</code>, 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! |
|||
== 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. |
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 == |
== Getting your UserVM on the roster == |
Latest revision as of 16:08, 2 November 2024
Welcome to the official guide on setting up a UserVM.
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)
- A Linux distribution; You can pick any mainstream distro, for the purposes of this guide I recommend either Debian or Arch, or their OpenRC counterparts if you prefer OpenRC. Yes, Ubuntu will work, it's terrible though
- If you REALLY want to run CollabVM on Windows, there is an unofficial and unsupported guide for that at UserVM Handbook/Windows
- 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 Linux 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
First up make sure you have git, nasm, cmake, and a C(++) compiler installed
$ sudo pacman --needed --noconfirm -Sy git nasm base-devel cmake # Arch
$ sudo apt-get install -y git nasm build-essential cmake # Debian
Next, we need to install Node.js. First, we'll install node. On arch, you can just run the following command:
$ sudo pacman --needed -S npm nodejs
On Debian, the packaged node version is too old to run CollabVM, so we'll add the nodesource repository.
$ sudo apt-get install -y curl
$ curl -fsSL https://deb.nodesource.com/setup_21.x | sudo bash -
$ sudo apt-get install nodejs -y
Enable Corepack:
$ sudo corepack enable
Prepare the server
Now let's get the server ready. First, we'll create a dedicated CollabVM user to run the server from /srv/collabvm
:
$ sudo useradd -rmd /srv/collabvm collabvm
$ sudo usermod -aG kvm collabvm # Give the CollabVM user permission to use KVM hypervision
Now, we can shell in as the CollabVM user. For the remainder of this guide, any line that starts with (collabvm) $
indicates that this should be run as the collabvm
user.
$ sudo -iu collabvm
(collabvm) $ pwd # This should output /srv/collabvm
Install the Rustup toolchain for the CollabVM user:
(collabvm) $ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Restart the shell to apply changes
(collabvm) $ exit
$ sudo -iu collabvm
Now, we can clone the CollabVM Server source code:
(collabvm) $ git clone https://github.com/computernewb/collabvm-1.2.ts.git /srv/collabvm/collabvm-1.2.ts --depth 1 --recursive
(collabvm) $ cd /srv/collabvm/collabvm-1.2.ts
Then install dependencies
(collabvm) $ yarn
Finally, build the server
(collabvm) $ 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)
We recommend setting up your VM as the collabvm user to make sure permissions are set correctly, but this is not a requirement.
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
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
Example of a production QEMU command:
qemuArgs = "qemu-system-x86_64 -M q35,usb=on,acpi=on,hpet=off -cpu host -accel whpx -m 2G -smp cores=2 -device usb-tablet -nic none -hda /srv/collabvm/images/vm1.qcow2"
Additionally, it is possible to use LilyVM to help with building more complex VM configurations.
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:
(collabvm) $ yarn serve
Or alternatively, to run it directly:
(collabvm) $ 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:
$ 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", # If you're not using proxying
"wss://example.com/collab-vm/vm1" # If you are using proxying. Remove one of these lines.
],
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
While it's useful and convenient to run your VM from the console while debugging, we strongly recommend you set it up as a service once you're ready to leave it on for extended periods of time. This is done differently depending on what init system your distro uses (Probably systemd, if you're not sure)
Systemd
To make your VM a systemd service, you can put the following into /etc/systemd/system/collabvm.service
[Unit]
Description=CollabVM
[Service]
Type=simple
User=collabvm
Group=collabvm
KillMode=mixed
Restart=always
RestartSec=5
# Make sure to change the following two lines according to where you put your server.
# If you have multiple VMs, it's possible to make your service file a template unit file (by making the file name, for example, "[email protected]"), and use %i in WorkingDirectory
# to automatically set WorkingDirectory to a different directory for each VM, allowing you to use the same server for all your VMs.
WorkingDirectory=/srv/collabvm/collabvm-1.2.ts/
ExecStart=/bin/node /srv/collabvm/collabvm-1.2.ts/cvmts/dist/index.js
# Tell systemd that we manage our own cgroup hierarchy, and delegate
# all controllers that are either implicitly or explicitly enabled.
#
# This is used for resource limits (in your VM's config.toml).
# Can be omitted if you are not using it. (It's probably a good idea to however!)
Delegate=yes
# Hardening
PrivateTmp=yes
NoNewPrivileges=true
RestrictNamespaces=uts ipc pid user cgroup
ProtectKernelTunables=yes
ProtectKernelModules=yes
PrivateDevices=no
RestrictSUIDSGID=true
[Install]
WantedBy=multi-user.target
Reload the daemon cache:
$ sudo systemctl daemon-reload
Then you can start your VM with:
$ sudo systemctl start collabvm
And make it automatically run on startup with:
$ sudo systemctl enable collabvm
OpenRC
Put the following into /etc/init.d/collabvm to make your VM an OpenRC service (change filename as appropriate):
#!/sbin/openrc-run
supervisor="supervise-daemon"
name="collabvm"
command="/bin/node"
command_args="/srv/collabvm/collabvm-1.2.ts/cvmts/dist/index.js"
# If you have multiple VMs, you can change --chdir to a different directory on each VM, to use different config files on the same server
supervise_daemon_args="--user collabvm --group collabvm --chdir /srv/collabvm/collabvm-1.2.ts --stdout /srv/collabvm/out.log --stderr /srv/collabvm/error.log"
Make it executable:
$ sudo chmod +x /etc/init.d/collabvm
Now you can start your VM with:
$ sudo rc-service collabvm start
And make it run on startup with:
$ sudo rc-update add 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 description of how to set that up on the Nginx side. This assumes you already have your site set up with Nginx, and if not there are numerous guides for that around the internet.
First, you'll want to save wsproxy_params to your Nginx directory, which enables WebSocket proxying. Here's a one-liner to do that:
$ sudo curl https://computernewb.com/~elijah/wsproxy_params -o /etc/nginx/wsproxy_params
Next, you can add the following to your Nginx server block:
location /collab-vm/vm1 {
include wsproxy_params;
proxy_pass http://127.0.0.1:6004/; # Replace 6004 if you changed the HTTP port in the config file.
}
If you get an error about connection_upgrade
, edit /etc/nginx/nginx.conf
and add the following to your http block:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
If you have multiple VMs running, you can have them all proxied like so:
location /collab-vm/vm1 {
include wsproxy_params;
proxy_pass http://127.0.0.1:6004/;
}
location /collab-vm/vm2 {
include wsproxy_params;
proxy_pass http://127.0.0.1:6005/;
}
# ...etc
Permanently host the webapp
If you want to host the webapp on your website, you can build it as follows:
$ 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/:
$ cp -r dist/. /var/www/example.com/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.