Getting started
Self-hosting
A client installs the product on a server of their own from one release archive, natively or in Docker, and upgrades it from the next one. This guide takes a new server to its first administrator. The archive carries this guide as self-hosting.md.
What you need
- A server. Ubuntu 24.04 or Debian 12 or newer, amd64 or arm64, with a public IPv4 address. 1 GB of memory serves a small team: the installer adds 2 GB of swap to a machine with less than 2 GB. Recording meetings, on the Docker path only, needs 4 GB.
- A domain. For example
office.example.com, with an A record that points at the server. - A license key, bought on the Sharkbyte website.
- A standard license installs a platform for one organisation.
- An extended license installs a multi-tenant platform for resale. That needs more: a host for the central admin (such as
console.example.com), a domain for tenants' subdomains with a wildcard record (such as*.tenants.example.com), and an OpenID Connect identity provider that operators sign in with.
- A Mailgun account with a sending domain and an API key. People sign in with links sent by email.
- The archive for the server's architecture,
vws-<version>-linux-<amd64|arm64>.tar.gz, from My orders, with the license key.
| Port | Protocol | For |
|---|---|---|
| 22 | TCP | SSH |
| 80, 443 | TCP | the web pages, the API and certificates |
| 443 | UDP | HTTP/3 |
| 7881 | TCP | media, where UDP is blocked |
| 50000–60000 | UDP | media |
The installer opens these ports in ufw. A cloud firewall in front of the server must allow them too.
Installing
Copy the archive to the server and run, as root:
tar -xzf vws-<version>-linux-amd64.tar.gz
cd vws-<version>-linux-amd64
./install.sh native # or: ./install.sh docker
It asks for the domain, your email address, the license key and the Mailgun details. With an extended license it also asks for the tenant domain, the central admin's host and the identity provider. ./install.sh --help lists the options that answer the questions in advance; with --yes it asks nothing.
| Native | Docker | |
|---|---|---|
| Runs | Postgres 18, Redis, LiveKit, Caddy and the server as systemd services | the same in containers, from public images, with the server's image built from the archive |
| Packages | Postgres from the PostgreSQL apt repository, Caddy from Caddy's | Docker from Docker's apt repository, when missing |
| Recordings | no | on request, with LiveKit's recorder |
| Data | Postgres's directory, /var/lib/vws | /var/lib/vws-postgres, /var/lib/vws |
Either way, the installer does the same:
- Secrets. It generates the database passwords, the signing key, the encryption key and LiveKit's key in
/etc/vws/secrets, readable by root only. The server's settings in/etc/vws/vws.env, and LiveKit's, are readable by root and the service only; on the Docker path,/etc/vws/docker.envpasses the database passwords to Postgres's container and is readable by root only. - Caddy. It serves the app and LiveKit, under
/livekit, on the domain, and gets the certificate automatically. - License. It activates the license key, which the server checks every day (Licensing).
- Backups. It schedules a daily dump of the database.
- Command. It installs
vws, the server's command line with its settings, for root. - Starter room. On a standard license, it offers a starter world and room on the built-in office map, at
/office/lobby(yes by default).
The first administrator
-
Standard license. Open
https://<domain>, sign in with your email address from the account menu, and run:sudo /opt/vws/current/install.sh admin you@example.comReload the page: Administration is in the account menu. From there you invite people, set up worlds, rooms, maps and sign-in providers, and keep the license.
-
Extended license. The installer lets your email address into the central admin. Open
https://<console host>/operator, sign in with your identity provider, and create tenants. Caddy gets certificates for tenants' hosts as they are first visited, once the server confirms it serves them.
Upgrading
Copy the next version's archive to the server, extract it, and run, as root:
./install.sh upgrade
The installer keeps the settings, secrets and data, and switches /opt/vws/current to the new version. The server migrates its database when it starts. The previous version stays in /opt/vws/releases.
Backups and restoring
Every day vws-backup.timer dumps the database into /var/backups/vws, keeping the last seven dumps. Copy them off the server, together with /etc/vws and /var/lib/vws (maps, avatars, uploads and recordings).
To restore a dump into a fresh install of the same version, stop the server first:
-
Native.
systemctl stop vws runuser -u postgres -- pg_restore --clean --if-exists -d vws /var/backups/vws/vws-<time>.dump systemctl start vws -
Docker.
docker compose -f /opt/vws/compose.yaml stop vws docker compose -f /opt/vws/compose.yaml exec -T postgres pg_restore --username=postgres --clean --if-exists -d vws < vws-<time>.dump docker compose -f /opt/vws/compose.yaml start vws
Restore /etc/vws from the backup too, as its encryption key opens the sealed secrets in the database.
Day to day
| Task | Native | Docker |
|---|---|---|
| state of the services and the license | install.sh status | install.sh status |
| the server's log | journalctl -u vws | docker compose -f /opt/vws/compose.yaml logs vws |
| restart | systemctl restart vws | docker compose -f /opt/vws/compose.yaml restart vws |
| the license | vws license status, or Administration, License | the same |
Settings are in /etc/vws/vws.env (Configuration). After changing them, restart the server.
Found a mistake? Tell us.