Skip to main content

Server Setup

Introduction

The focus here is on Basis Server specific configuration and not the many ways you can host game servers in the cloud.

The multithreading on the server runs best the more cores avaiable but it has been shown to work well on as little as two cores. Social VR demands a lot of bandwidth so you'll want to keep that in mind when picking your service provider.

This doc applies to an Unmodified Basis Server: Version 6 from the LTS branch as of May 2025

Helpful Tip about Server Version

You can find the ServerVersion in the code you cloned from the repo.
Client and server code must agree on the version.

BasisNetworkCore\BasisNetworkVersion.cs
5: public static ushort ServerVersion = 6;


Compile and Run on Windows

Assuming you have cloned the LTS branch of the repo. git clone https://github.com/BasisVR/Basis.git

You will find the Visual Studio Solution file (sln) in the Basis Server directory. These steps assume Windows 11 using Microsoft Visual Studio Community 2022 (64-bit) - Version 17.12.3

The BasisNetworkConsole is the csproj you will need to target for compiling. You should be able to select that project from the start up item menu at the top. Once selected click the green arrow to build.

Once compiled, navigate to \Basis\Basis Server\BasisServerConsole\bin\Debug\net9.0\ to find the server exe and compiled dependencies.

To run the server on Windows locally, open a command shell in this directory and run .\BasisNetworkConsole.exe

\Basis\Basis Server\BasisServerConsole\bin\Debug\net9.0> .\BasisNetworkConsole.exe

This should open a console and show something like the following:

[20:07] [INFO] Logs are saved to C:\Basis\Basis Server\BasisServerConsole\bin\Debug\net9.0\Logs\2025-05-10.log
[20:07] [INFO] Server Booting
[20:07] [INFO] HTTP health check started at 'http://localhost:10666/health'
[20:07] [INFO] Loaded Admins 0
[20:07] [INFO] DidAuthIdentity initialized.
[20:07] [INFO] Server Wiring up SetPort 4296
[20:07] [INFO] Server Worker Threads Booted
[20:07] [INFO] CombinedURL: https://example.com/502c8e6c8405d50418.BEE, LoadAssetPassword: c661cfeaf9757e
[20:07] [INFO] Adding Object world

Be sure to point to localhost when running the Basis Demo Client. The option is in the advanced panel when you first start the client.



Compile and Run on Linux

Prerequisits Assuming Debian/Ubuntu

For Ubuntu 22.04, sudo add-apt-repository ppa:dotnet/backports

For Debian or other qurirky setups:

wget https://packages.microsoft.com/config/debian/12/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb

Then continue installation:

sudo apt-get update && sudo apt-get install -y dotnet-sdk-9.0

Get Basis

Change to the folder you wish to download Basis to, and execute the following command:

git clone https://github.com/BasisVR/Basis

Build Basis Server

Open a new terminal and cd /to/directory/with/Basis Server/, i.e. cd Basis/Basis\ Server

dotnet restore

Then build, with either:

dotnet build (for debug)

or

dotnet build --configuration Release (For release)

Executing

Navigate to the BasisServerConsole directory (Something like /BasisServerConsole/bin/Debug/net9.0/BasisNetworkConsole) and run:

dotnet .\BasisNetworkConsole.dll

For More Targeted Linux Release

You may compile with the following:

dotnet publish -f net9.0 --self-contained --os Linux

The --self-contained switch is added to allow running on a OS without dotnet installed.

If you compile via this method (Or your build targeted the system) are on a you should be able to run

./BasisNetworkConsole

from BasisServerConsole/bin/Debug/net9.0/BasisNetworkConsole.

Firewall

You may want to open ports:

  • 1234/tcp
  • 10666/tcp
  • 4296/udp


Configuration Files

The first time you run the server a variety of config files and structure will be created in the directory the server exe rests in.

File/FolderDescription
config.xmlMain configuration file for the server.
initialresources/this directory contains world and object files the server will load upon request.
Log/Folder where server logs are stored.
admins.xmlList of users with admin privileges.
banned_players.xmlList of banned player accounts.


Config.xml

VariableDefaultDescription
PeerLimit1024Maximum number of players allowed on server.
SetPort4296Network port the server listens on.
QueueEvents10
UseNativeSocketstrueLNL: Use system-native socket implementation
NatPunchEnabledtrueLNL: Enable NAT punch-through
PingInterval1500LNL:
DisconnectTimeout5000LNL: Time to wait before disconnecting player
SimulatePacketLossfalseSimulate packet loss for testing.
SimulateLatencyfalseSimulate network latency.
SimulationPacketLossChance10
SimulationMinLatency50Minimum simulated latency.
SimulationMaxLatency150Maximum simulated latency.
UnsyncedEventsfalse
UnsyncedReceiveEventfalse
UnsyncedDeliveryEventfalse
ReconnectDelay500Time before attempting reconnect.
MaxConnectAttempts10Max number of reconnect attempts.
ReuseAddresstrue
DontRoutefalse
EnableStatisticstrueLNL:
IPv6EnabledtrueLNL: Enable IPv6 support.
MtuOverride1500Override MTU (Maximum Transmission Unit).
MtuDiscoverytrueEnable automatic MTU discovery.
DisconnectOnUnreachabletrueDisconnect players if unreachable.
AllowPeerAddressChangetrueLNL: Allow player clients to change IP address.
UsingLoggingFiletrueEnable logging to file.
HealthCheckHostlocalhostHostname used for health checks.
HealthCheckPort10666Port used for health checks.
HealthPath/healthPath to health check endpoint.
BSRSMillisecondDefaultInterval50
BSRBaseMultiplier1
BSRSIncreaseRate0.005
OverrideAutoDiscoveryOfIpvfalse
IPv4Address0.0.0.0IPv4 bind address.
IPv6Address::1IPv6 bind address.
PromethusPort1234Port for Prometheus metrics.
PromethusUrl/metricsURL path for Prometheus metrics.
Passworddefault_passwordDefault server access password.
MinThreadPoolThreads100Minimum number of thread pool threads.
MaxThreadPoolThreads500Maximum number of thread pool threads.
UseAuthtrueEnable or disable the server authentication.
UseAuthIdentitytrueUse DID identity verification when auth is on.
BasisUserRestrictionModeNormalPertains to the user mod tools. Not completed at this time.
HowManyDuplicateAuthCanExist2Number of times the same player can be authenticated at the same time.
AuthValidationTimeOutMiliseconds9000Timeout for auth validation (ms).
The lower-level networking is handled by a third-party library called LiteNetLib. Config variables related to this code are marked LNL.
<UseAuth>true</UseAuth> 

Meant to be used for turning off auth all together.

  <UseAuthIdentity>true</UseAuthIdentity>

Enables disable DID auth provide

  <BasisUserRestrictionMode>Normal</BasisUserRestrictionMode>

Not finished yet. Admin moderation.

  <HowManyDuplicateAuthCanExist>2</HowManyDuplicateAuthCanExist>

How many people can connect with the same Auth credentials.

The default settings you may find in the config.xml

Example Config.xml
<?xml version="1.0" encoding="utf-8"?>
<Configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<PeerLimit>1024</PeerLimit>
<SetPort>4296</SetPort>
<QueueEvents>10</QueueEvents>
<UseNativeSockets>true</UseNativeSockets>
<NatPunchEnabled>true</NatPunchEnabled>
<PingInterval>1500</PingInterval>
<DisconnectTimeout>5000</DisconnectTimeout>
<SimulatePacketLoss>false</SimulatePacketLoss>
<SimulateLatency>false</SimulateLatency>
<SimulationPacketLossChance>10</SimulationPacketLossChance>
<SimulationMinLatency>50</SimulationMinLatency>
<SimulationMaxLatency>150</SimulationMaxLatency>
<UnsyncedEvents>false</UnsyncedEvents>
<UnsyncedReceiveEvent>false</UnsyncedReceiveEvent>
<UnsyncedDeliveryEvent>false</UnsyncedDeliveryEvent>
<ReconnectDelay>500</ReconnectDelay>
<MaxConnectAttempts>10</MaxConnectAttempts>
<ReuseAddress>true</ReuseAddress>
<DontRoute>false</DontRoute>
<EnableStatistics>true</EnableStatistics>
<IPv6Enabled>true</IPv6Enabled>
<MtuOverride>1500</MtuOverride>
<MtuDiscovery>true</MtuDiscovery>
<DisconnectOnUnreachable>true</DisconnectOnUnreachable>
<AllowPeerAddressChange>true</AllowPeerAddressChange>
<UsingLoggingFile>true</UsingLoggingFile>
<HealthCheckHost>localhost</HealthCheckHost>
<HealthCheckPort>10666</HealthCheckPort>
<HealthPath>/health</HealthPath>
<BSRSMillisecondDefaultInterval>50</BSRSMillisecondDefaultInterval>
<BSRBaseMultiplier>1</BSRBaseMultiplier>
<BSRSIncreaseRate>0.005</BSRSIncreaseRate>
<OverrideAutoDiscoveryOfIpv>false</OverrideAutoDiscoveryOfIpv>
<IPv4Address>0.0.0.0</IPv4Address>
<IPv6Address>::1</IPv6Address>
<PromethusPort>1234</PromethusPort>
<PromethusUrl>/metrics</PromethusUrl>
<Password>default_password</Password>
<MinThreadPoolThreads>100</MinThreadPoolThreads>
<MaxThreadPoolThreads>500</MaxThreadPoolThreads>
<UseAuth>true</UseAuth>
<UseAuthIdentity>true</UseAuthIdentity>
<BasisUserRestrictionMode>Normal</BasisUserRestrictionMode>
<HowManyDuplicateAuthCanExist>2</HowManyDuplicateAuthCanExist>
<AuthValidationTimeOutMiliseconds>9000</AuthValidationTimeOutMiliseconds>
</Configuration>


Loadable Configuration Files

You may setup world and object files to load on demand. These are the files you place in the InitialResources folder.

caution

Note that the remote urls you use must be served from a proper server that supports chunking. Any modern server should do this but simple local dev servers may not.

To upload something

One avenue you can use to test out a new scene is to create a scene in Unity, export the scene as a BEE file. Upload that BEE file to a server that supports HTTP, then, place the URL in CombinedURL, and get the password from dontuploadmepassword.txt and place it in UnlockPassword.

VariableDefinition
ModeMode of the configuration: 0 = Game object, 1 = Scene.
LoadedNetIDA Network ID: Server keeps a list of Network Objects that Clients can query and spawn with this value as a reference.
UnlockPasswordPassword required to unlock or access the resource.
CombinedURLURL to the .BEE file
IsLocalLoadIndicates whether the resource is loaded locally (true) or from the internet (false).
PositionXX-axis world position of the object.
PositionYY-axis world position of the object.
PositionZZ-axis world position of the object.
QuaternionXX component of the object's rotation (quaternion).
QuaternionYY component of the object's rotation (quaternion).
QuaternionZZ component of the object's rotation (quaternion).
QuaternionWW component of the object's rotation (quaternion).
ScaleXX-axis scale factor.
ScaleYY-axis scale factor.
ScaleZZ-axis scale factor.
PersistIf the player that spawned the object leaves the server does the object continue to exist?
BasisLoadableConfiguration Example
<BasisLoadableConfiguration>

<!-- Mode of the configuration: Mode 0 = Game object, 1 = Scene -->
<Mode>0</Mode>

<!-- A Network ID: Server keeps a list of Network Objects that Clients can query and spawn with this value. -->
<LoadedNetID></LoadedNetID>

<!-- Unlock password -->
<UnlockPassword>ffee4439eff</UnlockPassword>

<!-- Combined URL link to BEE file -->
<CombinedURL>https://www.example.com/2lkj23j.BEE</CombinedURL>

<!-- Does this resource exist on the internet or in the client? -->
<IsLocalLoad>false</IsLocalLoad>

<!-- Position values -->
<PositionX>0</PositionX>
<PositionY>0</PositionY>
<PositionZ>0</PositionZ>

<!-- Quaternion values -->
<QuaternionX>0</QuaternionX>
<QuaternionY>0</QuaternionY>
<QuaternionZ>0</QuaternionZ>
<QuaternionW>1</QuaternionW>

<!-- Scale values -->
<ScaleX>1</ScaleX>
<ScaleY>1</ScaleY>
<ScaleZ>1</ScaleZ>

<!-- If the player that spawned the object leaves the server does the object continue to exist? -->
<Persist>false</Persist>

</BasisLoadableConfiguration>

ModifyScale

        /// <summary>
/// this is used to state if the scale should be set or
/// just use whatever scale it thinks it is.
/// </summary>
public bool ModifyScale;


Advanced Server Configuration

Server Reduction System

As the number of players grows on the server the bandwidth requirements quickly grow. The SRS system attempts to reduce the network load and improve performance by slowing down how often it needs to send motion data to players based on distance.

The equation that governs how much longer the server takes to send Motion Data to users based on distance looks like:

 int adjustedInterval = (int)(Configuration.BSRSMillisecondDefaultInterval * (Configuration.BSRBaseMultiplier + (activeDistance * Configuration.BSRSIncreaseRate)));

The rest of this section will be published later.



Client Reduction System

This section will be published later.



Health Check Endpoint

When running the server locally you may can check the server status by visiting the health check endpoint at: http://localhost:10666/health

http://localhost:10666/health
{
"listening": true,
"visitors": "0",
"capacity": "1024",
"sent": "0",
"recv": "0",
"currentTime": "2025-05-09T20:19:03.200Z",
"startTime": "2025-05-09T20:19:00.049Z",
"version": "6"
}
VariableDefinition
listeningIs server listening for connections
visitorsThe number of current players aka visitors
capacitymaxium number of players allowed on server
sentTotal amount of data sent (in bytes?)
recvTotal amount of data received (in bytes?)
currentTimeThe current server time in ISO 8601 format
startTimeThe server’s start time in ISO 8601 format
versionThe version number of the server. Important: Client code must match expected ServerVersion


Terminology

Local Player
The local avatar data that represents you (the user or client).

Remote Player
Represents other players whose data is sent to you by the server.

Basis Client The application you are writing that will communicate with the server.

Motion Data The data that represents the player bone positions as well as position and rotation in the world. Stored in network serializable format in LASM data structure

LASM Stands for Local Avatar Sync Message, the data structure that contains compressed data for a players muscles, postion and rotation that is sent over the network.