From 5f34ecf2fa8e059baa25a918b6987423c984fa55 Mon Sep 17 00:00:00 2001 From: Toys0125 Date: Wed, 25 Mar 2026 16:53:07 -0500 Subject: [PATCH 1/6] Fix correct path in the linux yaml. --- content/docs/server/headless.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/server/headless.mdx b/content/docs/server/headless.mdx index 2379981..cd3127a 100644 --- a/content/docs/server/headless.mdx +++ b/content/docs/server/headless.mdx @@ -55,7 +55,7 @@ services: Password: default_password Ip: 'server1.basisvr.org' volumes: - - ./config.xml:/HeadlessLinuxServer_Data/config.xml + - ./config.xml:/app/HeadlessLinuxServer_Data/config.xml ``` ### Windows From 9bff02e65b6b61e0a5cf066542faad75eb567980 Mon Sep 17 00:00:00 2001 From: Toys0125 Date: Wed, 25 Mar 2026 17:08:52 -0500 Subject: [PATCH 2/6] Fix the font size of the command issue. --- content/docs/server/headless.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/server/headless.mdx b/content/docs/server/headless.mdx index cd3127a..a6a7869 100644 --- a/content/docs/server/headless.mdx +++ b/content/docs/server/headless.mdx @@ -89,7 +89,7 @@ If you mount a `config.xml`, treat it as the file-based fallback configuration. Docker Compose can launch multiple headless clients from the same service definition: -### `docker compose -f docker-compose.yml up -d --scale "basis-headless=10"` +

`docker compose -f docker-compose.yml up -d --scale "basis-headless=10"`

As a rough guideline, the existing note recommends budgeting about `1.5 GB` of memory per instance. For example, if you have around `30 GB` available, you can plan on roughly `20` instances. From 18af08a311a1a19d6a636733c0d29e292a6a9720 Mon Sep 17 00:00:00 2001 From: Toys0125 Date: Wed, 25 Mar 2026 18:38:51 -0500 Subject: [PATCH 3/6] Add more details. To the yaml file. --- content/docs/server/headless.mdx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/content/docs/server/headless.mdx b/content/docs/server/headless.mdx index a6a7869..46b9eef 100644 --- a/content/docs/server/headless.mdx +++ b/content/docs/server/headless.mdx @@ -50,12 +50,14 @@ When running Docker from Docker Desktop, Docker normally uses WSL2 under the hoo services: basis-headless: image: ghcr.io/basisvr/basis-headless:nightly-linux + scale: 3 # You should change based on how much RAM you have. 1.5GB per instance is normally required. environment: Port: 4296 Password: default_password Ip: 'server1.basisvr.org' volumes: - - ./config.xml:/app/HeadlessLinuxServer_Data/config.xml + - ./Basis:/root/.config/unity3d/Basis Unity/Basis Unity # For Sharing Cached files. Optional not required + - ./config.xml:/app/HeadlessLinuxServer_Data/config.xml # Optional will be overridden when using environment variables ``` ### Windows @@ -64,12 +66,14 @@ services: services: basis-headless: image: ghcr.io/basisvr/basis-headless:nightly-windows + scale: 3 # You should change based on how much RAM you have. 1.5GB per instance is normally required. environment: Port: 4296 Password: default_password Ip: 'server1.basisvr.org' volumes: - - ./config.xml:/app/HeadlessWindowsServer_Data/config.xml + - ./Basis:/root/.config/unity3d/Basis Unity/Basis Unity # For Sharing Cached files. Optional not required + - ./config.xml:/app/HeadlessLinuxServer_Data/config.xml # Optional will be overridden when using environment variables ``` ## What the Settings Mean @@ -89,7 +93,7 @@ If you mount a `config.xml`, treat it as the file-based fallback configuration. Docker Compose can launch multiple headless clients from the same service definition: -

`docker compose -f docker-compose.yml up -d --scale "basis-headless=10"`

+

`docker compose -f docker-compose.yml up -d --scale "basis-headless=10"`

*--scale when not set in the docker-compose.yml* As a rough guideline, the existing note recommends budgeting about `1.5 GB` of memory per instance. For example, if you have around `30 GB` available, you can plan on roughly `20` instances. From 47fb249d345cc4a14ca00f4625f9036ee3c30e2e Mon Sep 17 00:00:00 2001 From: Toys0125 Date: Wed, 25 Mar 2026 18:40:19 -0500 Subject: [PATCH 4/6] Windows has a different path. --- content/docs/server/headless.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/content/docs/server/headless.mdx b/content/docs/server/headless.mdx index 46b9eef..47bce12 100644 --- a/content/docs/server/headless.mdx +++ b/content/docs/server/headless.mdx @@ -72,7 +72,6 @@ services: Password: default_password Ip: 'server1.basisvr.org' volumes: - - ./Basis:/root/.config/unity3d/Basis Unity/Basis Unity # For Sharing Cached files. Optional not required - ./config.xml:/app/HeadlessLinuxServer_Data/config.xml # Optional will be overridden when using environment variables ``` From acc34597e4fa05db604b65faab24b6e9c5b92022 Mon Sep 17 00:00:00 2001 From: Toys0125 Date: Wed, 25 Mar 2026 19:06:04 -0500 Subject: [PATCH 5/6] Correct mistake on Windows Config. --- content/docs/server/headless.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/server/headless.mdx b/content/docs/server/headless.mdx index 47bce12..62efa9f 100644 --- a/content/docs/server/headless.mdx +++ b/content/docs/server/headless.mdx @@ -72,7 +72,7 @@ services: Password: default_password Ip: 'server1.basisvr.org' volumes: - - ./config.xml:/app/HeadlessLinuxServer_Data/config.xml # Optional will be overridden when using environment variables + - ./config.xml:/app/HeadlessWindowsServer_Data/config.xml # Optional will be overridden when using environment variables ``` ## What the Settings Mean From c67fdb5e2657eb6c4d01a1ffa20698010b7c7167 Mon Sep 17 00:00:00 2001 From: Toys0125 Date: Mon, 30 Mar 2026 00:21:02 -0500 Subject: [PATCH 6/6] Update Headless docs with the healthcheck info. --- content/docs/server/headless.mdx | 98 +++++++++++++++++++++++--------- 1 file changed, 71 insertions(+), 27 deletions(-) diff --git a/content/docs/server/headless.mdx b/content/docs/server/headless.mdx index 62efa9f..f41b30d 100644 --- a/content/docs/server/headless.mdx +++ b/content/docs/server/headless.mdx @@ -3,6 +3,8 @@ title: Headless Clients --- import { Callout } from 'fumadocs-ui/components/callout'; +import { Step, Steps } from 'fumadocs-ui/components/steps'; + ## Introduction @@ -25,11 +27,15 @@ This page focuses on running the headless client itself. For the server-side set You have two main ways to run headless clients: -- Download the Linux or Windows headless client build from the GitHub artifacts +- Download the Linux or Windows headless client build from the [GitHub artifacts](https://nightly.link/BasisVR/Basis/workflows/build-docker-server/developer?preview) - Run the published headless Docker images Docker is useful when you want repeatable containerized setups or need to scale many instances quickly. If you only need to run one or a few headless clients, downloading the platform build directly is also valid. + +By default the Windows Version of the headless is built with Mono instead of IL2CPP and is a limitation of the UnityCI for building. Mono uses about 1.5-2x more memory than IL2CPP so use the linux version unless package states its IL2CPP version. + + ## Before You Start Make sure the server you want to target is already reachable. @@ -40,11 +46,50 @@ Make sure the server you want to target is already reachable. The server documentation also notes that `config.xml` values can be overridden by environment variables. That matters here because the same pattern is used for the headless client examples below. +## Setting up Desktop Docker + + +Open `System Information` and check if Virtualization-based security says `Running` and Virtualization-based security Available has:`Security Properties Base Virtualization Support` + +If not go into your bios and Enable AMD-Vi or Intel VT-d based on your CPU. + +Google your motherboard that under `BaseBoard Product` to found out where the setting is and what key to open bios. + + +Go to [Docker and Download for Windows](https://docs.docker.com/desktop/setup/install/windows-install/) and install Docker Desktop. + + +Make a folder for the `docker-compose.yml` and copy the example below. + + +Start a Command Prompt or Powershell in that directory. When using file explorer you can launch Command Prompt by typing `cmd.exe` in the url bar or explorer. + + +Type the command `docker compose up -d` to start the containers + + +Use `docker ps` to see the health of all containers and wait until all say healthy. Should take about 30 seconds to a minute. + + +Use `docker compose scale "basis-headless=#` to increase the number of containers. Than go back to a step and repeat until either you out of CPU or RAM. + +*Replace `#` with a number in increments of 5* + + +You can also measure usage with `docker compose stats` + + + + ## Docker Compose Configuration -When running Docker from Docker Desktop, Docker normally uses WSL2 under the hood, so the Linux image is usually the correct choice there. If you are specifically running Windows containers, use the Windows image instead. +When running Docker from Docker Desktop, Docker engine normally uses WSL2 under the hood, so the Linux image is usually the correct choice there. If you are specifically running Windows containers *for example Windows Server 2016*, use the Windows image instead found in the Basis-Headless package on github. + + +By Default use the linux version of the docker image as its built using IL2CPP and if you get manifest errors about linux, you need to use the `-linux` versions. + -### Linux +### docker-compose.yml ```yml services: @@ -55,24 +100,20 @@ services: Port: 4296 Password: default_password Ip: 'server1.basisvr.org' + HealthCheckEnabled: "true" + HealthCheckHost: "0.0.0.0" + HealthCheckPort: 10666 + HealthPath: "/health" volumes: - ./Basis:/root/.config/unity3d/Basis Unity/Basis Unity # For Sharing Cached files. Optional not required + - "${APPDATA}/../LocalLow/Basis Unity/Basis Unity:/root/.config/unity3d/Basis Unity/Basis Unity" #If you want to use your own cache and avatar files. *Corruption possible - ./config.xml:/app/HeadlessLinuxServer_Data/config.xml # Optional will be overridden when using environment variables -``` - -### Windows - -```yml -services: - basis-headless: - image: ghcr.io/basisvr/basis-headless:nightly-windows - scale: 3 # You should change based on how much RAM you have. 1.5GB per instance is normally required. - environment: - Port: 4296 - Password: default_password - Ip: 'server1.basisvr.org' - volumes: - - ./config.xml:/app/HeadlessWindowsServer_Data/config.xml # Optional will be overridden when using environment variables + healthcheck: + test: ["CMD-SHELL","bash -lc 'exec 3<>/dev/tcp/127.0.0.1/10666 && printf \"GET /health HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n\" >&3 && grep -q \"200\" <&3`"] + interval: 30s + timeout: 5s + retries: 3 + start_period: 20s ``` ## What the Settings Mean @@ -84,6 +125,10 @@ The examples above use the minimum values needed to connect: | `IP` | Hostname or IP address of the Basis server | | `Port` | UDP port the server listens on, usually `4296` | | `Password` | Server password required to join | +| `HealthCheckEnabled` | Enable or Disable HealthCheckEndpoint | +| `HealthCheckHost` | Ip Endpoint listens on | +| `HealthCheckPort` | Port Endpoint listens on | +| `HealthPath` | Path for Health info | If you mount a `config.xml`, treat it as the file-based fallback configuration. If you also set environment variables, the docs for the main server note that environment values override xml values, so keep one source of truth where possible to avoid confusion during testing. @@ -92,10 +137,16 @@ If you mount a `config.xml`, treat it as the file-based fallback configuration. Docker Compose can launch multiple headless clients from the same service definition: -

`docker compose -f docker-compose.yml up -d --scale "basis-headless=10"`

*--scale when not set in the docker-compose.yml* +

`docker compose --scale "basis-headless=10"`

*--scale when not set in the docker-compose.yml* As a rough guideline, the existing note recommends budgeting about `1.5 GB` of memory per instance. For example, if you have around `30 GB` available, you can plan on roughly `20` instances. + +Do not try launching all clients at once. You will overload your computers ram, and at the current moment we don't offer a script that provides easy launching of instance. + +Best way is to wait until the health status of all launched containers are showing healthy before adding more. + + This is only a starting estimate. Actual limits depend on: - Available RAM @@ -103,13 +154,6 @@ This is only a starting estimate. Actual limits depend on: - The server's `PeerLimit` - Bandwidth available between the headless clients and the server -## Suggested Load Testing Workflow - -1. Start the Basis server and confirm it is listening. -2. Check the server health endpoint at `http://localhost:10666/health` or the equivalent host for your deployment. -3. Launch a small number of headless clients first. -4. Verify they can connect with the expected `IP`, `Port`, and `Password`. -5. Increase the scale gradually and watch server health, bandwidth, and machine resource usage. ## Monitoring During Tests @@ -144,7 +188,7 @@ The server docs explicitly note that client and server code must agree on the se If the headless clients do not connect, check these first: -- The server address in `IP` is reachable from the container +- The server address in `Ip` is reachable from the container - The server password matches - `4296/udp` is open and mapped correctly - You are using the correct image for your container runtime