Running it locally - rebaserHEAD/NexusForever GitHub Wiki

guide, committed verified 2026-10-14 stable a4e75b18

This guide takes you from a fresh clone to a character standing in the world, all on one Windows machine.

Warning

Run the server from stable, or from a branch that carries the loopback change. Upstream's Aspire host binds the three game listeners to every network interface, and the world server's web console has no login. See Keep it on your machine.

Before you start

What you'll have

All nine server processes running on your machine, with MySQL and RabbitMQ in Docker, an account that can use GM commands, and the 16042 client logged in to it. The whole guide was last run end to end on Windows 11.

How it works

The solution ships an Aspire host that does the orchestration. When it starts, it:

  1. Starts MySQL, RabbitMQ and phpMyAdmin in Docker containers. MySQL keeps its data in a Docker volume named mysql-data, which survives restarts.
  2. Runs a migration step that creates seven databases, applies every migration, and imports the world database's .sql files.
  3. Starts the nine servers, handing each its network, database and broker settings as environment variables.

The client opens exactly three connections, in order: STS, then Auth, then World. Everything else talks over the broker. The ports are under Quick reference.

What you need

  • Windows 10 or 11.
  • The .NET 10 SDK.
  • Docker Desktop on the WSL 2 backend. Its installer asks for one restart, and WSL arrives with it.
  • A WildStar 16042 client.
  • A clone of upstream's world database. Strictly optional, but it holds the spawns and other world content, so without it the world is empty.
  • About 4 GB of free disk for the extracted tables and maps.

Note

Upstream's server setup guide covers a native install without Docker. If you go that way, this branch needs ten config files where the guide lists seven.

Set up

Build

Clone the fork, switch to stable and build the solution:

git clone https://github.com/rebaserHEAD/NexusForever.git
cd NexusForever
git switch stable
dotnet build Source\NexusForever.slnx

Tip

Keep the Debug build while you work. It's the only build that checks each game table model against the file it reads, so a layout mistake shows up at start-up instead of as quietly wrong data later.

Extract the game tables and maps

The server reads three things out of the client: the game tables (.tbl), the text tables (.bin) and a map file per world (.nfmap). NexusForever.MapGenerator produces all three.

  1. Copy Source\NexusForever.WorldServer\nlog.config into Source\NexusForever.MapGenerator\bin\Debug\net10.0, next to NexusForever.MapGenerator.exe. The tool ships without a logging config, and without one it prints nothing, even when it fails.

  2. Create an empty output folder. The tool won't create it for you.

  3. Run it against the client's Patch folder:

    .\NexusForever.MapGenerator.exe -i "<client folder>\Patch" -e -g -o "<output folder>"

    -e extracts the tables into <output folder>\tbl and -g generates the maps into <output folder>\map. Expect about four minutes and around 3 GB of maps.

Note

Extraction doesn't truncate files that already exist. Point it at an empty folder when you extract again.

Write the configs

Each server reads a JSON config from the folder its executable runs in, and only the .example.json files ship. In each project's bin\Debug\net10.0 folder, copy the example to the same name without .example:

Project Config
NexusForever.WorldServer WorldServer.json
NexusForever.AuthServer AuthServer.json
NexusForever.StsServer StsServer.json
NexusForever.API.Account AccountAPI.json
NexusForever.API.Character CharacterAPI.json
NexusForever.Server.ChatServer ChatServer.json
NexusForever.Server.GroupServer GroupServer.json
NexusForever.Server.Friendship FriendshipServer.json
NexusForever.Server.Character CharacterServer.json
NexusForever.Aspire.Database.Migrations AspireMigrations.json

Leave the network, database and broker settings alone: the host's environment variables win over the JSON. Then set these, with absolute paths. A relative path resolves against each server's own output folder, and your extracted folders aren't there:

  • Table paths. In WorldServer.json, ChatServer.json and FriendshipServer.json, set GameTable:GameTablePath to your tbl folder.
  • Map path. In WorldServer.json, set Realm:Map:MapPath to your map folder.
  • World database. In AspireMigrations.json, set WorldDatabase:Path to your clone of the world database.

Note

The GameTable:Cache keys in the example configs do nothing at the moment. The table cache they configure exists in the code but nothing calls it.

Run

Start the stack

Start Docker Desktop and wait until docker version shows a server. Then, from the repository root:

$env:ASPNETCORE_ENVIRONMENT = 'Development'
$env:DOTNET_ENVIRONMENT = 'Development'
$env:ASPIRE_ALLOW_UNSECURED_TRANSPORT = 'true'
$env:ASPNETCORE_URLS = 'http://localhost:17021'
$env:DOTNET_DASHBOARD_OTLP_ENDPOINT_URL = 'http://localhost:21230'
$env:DOTNET_RESOURCE_SERVICE_ENDPOINT_URL = 'http://localhost:22075'
dotnet run --project Source\NexusForever.Aspire.AppHost --no-build --no-launch-profile

The variables run the Aspire dashboard over plain HTTP on localhost, so you don't have to trust the HTTPS developer certificate first. The three ports are arbitrary; any free ones do.

The host prints a login link for the dashboard, and every server's console output shows up there. The first start takes a couple of minutes once the container images are down.

Note

Two world database files fail on game_rework, and that's expected. 28 of the 30 import; Evil from the Ether.sql and New Player Experience.sql fail with "Table 'worlddb.entity_script' doesn't exist", because they're written for upstream's expedition branch.

Make an account

Open the web console at http://localhost:5000/console.html and run:

account create [email protected] <password> Administrator

Give the account a role. On a fresh database the default Player role holds no permissions, so an account without one can't run a single command from chat. The starter account that AccountCreation in AspireMigrations.json makes has no role either.

There's nothing else to set up on the account. On stable, each character gets the base entitlements of a full account when it loads, so the client doesn't treat it as a trial account (Account entitlements).

Launch the client

Launch the client with NexusForever.ClientConnector, which builds with the rest of the solution. Run it with the client's Client64 folder as the working directory:

Set-Location "<client folder>\Client64"
& "<repository>\Source\NexusForever.ClientConnector\bin\Debug\net10.0\NexusForever.ClientConnector.exe"

The first time, it asks for a host name (127.0.0.1) and a language (en) and saves them to config.json in that folder. After that it starts WildStar64.exe pointed at your server.

Important

A shortcut with the server address on it won't work. The client only connects straight to a server when its command line begins with /auth, with no program name in front, and neither a shortcut nor a normal command line can produce that. Otherwise the client starts the old launcher, which tries the retired patch server and quits.

If the client still opens the launcher, check the file times in Patch\. The client compares each data index's modified time against the time Patch.index records for it. A copy unpacked from a zip can come out hours off, because zip stores local time with no time zone. Use a copy that kept its original file times.

Leave the tutorial

A new character starts in the tutorial, and the tutorial is empty on game_rework: terrain, but no content. Its scripting lives on upstream's expedition branch.

Type !teleport name <zone name> in chat to leave. The three continent worlds the example config precaches (22, 51 and 1061) hold most of the imported spawns.

Look after it

Keep the logs on disk

Under Aspire, server output goes to the dashboard only. To keep it on disk as well, add a file target to the nlog.config in each server's output folder:

<target name="file" xsi:type="File" fileName="<logs folder>\${processname}.log"
        layout="${longdate} [${uppercase:${level}}][${logger:shortName=true}] ${message} ${exception:format=tostring}"/>

Then change the rule to writeTo="console,file". A build can copy the stock nlog.config over yours, so check it after building.

Two noisy patterns are healthy: the world server logs a connect and disconnect from 127.0.0.1 every 15 seconds, which is Aspire checking the port, and the friendship server logs a database job several times a second at Debug.

Stop the stack

Press Ctrl+C in the host's window, then check docker ps. A host that gets killed instead of stopped leaves its containers running. Remove any leftover mysql, rmq and phpmyadmin containers before the next start, so two MySQL servers never share the data volume.

Start from scratch

Stop the stack, then remove the database volume:

docker volume rm mysql-data

The next start migrates and imports again, and you make your account again.

Keep it on your machine

Nothing in this stack is built to face the internet. Keep every listener on loopback, and don't forward any of its ports.

  • On stable, the Aspire host binds STS, Auth and World to 127.0.0.1. Upstream's binds them to every interface, and because the host passes Network:Host as an environment variable, a JSON config can't override it.
  • The web console asks for no login, and every command it runs has every permission.
  • If you run the world server without Aspire, change Urls in WorldServer.json from the example's http://0.0.0.0:5000 to http://localhost:5000, or the console listens on every interface.

Troubleshooting

Symptom Cause Fix
World server stops at start-up with "Invalid path to base maps!" Realm:Map:MapPath doesn't point at your map folder Use the absolute path
World server stops at start-up with "Invalid world id N supplied for precached base maps!", or a missing .nfmap A world in Realm:Map:PrecacheBaseMaps has no map file Generate the maps, or empty that list
World server stops at start-up after "Failed to load" lines A table is missing or damaged in GameTablePath Extract again into an empty folder
A null reference in CustomisationManager at start-up en-US.bin isn't in the table folder Extract again; the text tables land next to the .tbl files
Two world database files fail to import They need the expedition branch's schema Nothing, it's expected
The client opens the launcher and closes It wasn't started through the connector, or the Patch\ file times are off See Launch the client
Your account can't use any ! command The account has no role Make the account with Administrator
The web console answers "Invalid target for this command!" The command acts on a character and none is attached See Using the web console

Quick reference

Process Listens on
STS server 127.0.0.1:6600
Auth server 127.0.0.1:23115
World server 127.0.0.1:24000, and http://localhost:5000 for the web console
Character API localhost:4000
Account API localhost:4001
Chat, group, friendship and character servers The message broker only
Thing Where
Aspire dashboard The login link the host prints at start-up
Web console http://localhost:5000/console.html
Database volume mysql-data
⚠️ **GitHub.com Fallback** ⚠️