Build the GameFrameX server locally, validate the Unity workflow, and then publish only the required game endpoints
GameFrameX combines a .NET multiplayer server, MongoDB-backed player data, HTTP APIs, and a Unity client in one aggregated repository. This guide starts with the installation rather than the tunnel: we download the project, start MongoDB, compile and launch the server, verify its local TCP and HTTP listeners, and test the included Unity scene. After the local client-server loop works, we configure Localtonet access for the long-lived TCP game connection and, when the client needs login or related APIs, a separate HTTP tunnel. We also explain security boundaries, endpoint configuration, routine operations, and practical troubleshooting.
๐ What's in this guide
How the GameFrameX client-server workflow fits together

GameFrameX is an open-source game development toolbox built around clients such as Unity and a .NET server. Its aggregated repository contains the server, Unity project, Docker support files, protocol definitions, tools, and related project resources. That repository is the appropriate starting point for this walkthrough because it provides the complete example needed to test the documented client-server loop without assembling several independent repositories.
The server uses more than one network endpoint. The default TCP listener on port 29100 handles long-lived game-client connections. The HTTP listener on port 28080 serves login and other APIs under paths such as /game/api/.... These endpoints solve different problems, so a remotely running Unity client may need both. Sending both kinds of traffic to one port or assuming an HTTP URL can replace the game TCP connection will not produce an equivalent setup.
GameFrameX also documents an optional WebSocket service on port 29110, but it is disabled by default. An optional metrics and health listener uses port 29090 when explicitly enabled. Neither optional listener is required for the installation path in this guide, and neither should be exposed merely because the server supports it.
--IsEnableWebSocket true startup option when deliberately needed.
The cleanest implementation is therefore staged. First, prove that MongoDB and the GameFrameX server work on the host. Second, prove that the included Unity project can complete its local flow. Third, expose only the application listeners the remote client actually uses. This separation makes failures easier to diagnose because it distinguishes application, database, client-configuration, and tunnel problems.
| Default port | Protocol and purpose | Default state | Remote-access guidance |
|---|---|---|---|
29100 |
TCP, long-lived game-client connections | On | Use a Localtonet TCP tunnel when remote game clients need this listener. |
28080 |
HTTP, login and other game APIs | On | Use a separate Localtonet HTTP tunnel if the client calls these APIs remotely. |
29110 |
WebSocket service | Off | Do not expose it unless the application is deliberately configured to use it. |
29090 |
Metrics and health service | Off | Keep private unless there is a specific, protected observability requirement. |
27017 |
MongoDB used by the local server | Started through the supplied Compose setup | Do not create a public game tunnel for the database. |
Prerequisites for the complete server and Unity walkthrough
The server quick start has several distinct prerequisites. Install the required tools before downloading or building the project so that an error from one missing dependency is not mistaken for a GameFrameX problem.
.NET SDK
The aggregated GameFrameX repository documents .NET SDK 10.0 or newer as a hard requirement for both the server and its table-generation tooling. Confirm that the active dotnet command resolves to a compatible SDK:
dotnet --version
If the displayed major version is older than 10, install a compatible SDK and make sure the correct executable is available in the shell used for the build. A runtime installation alone is not sufficient because this workflow invokes dotnet build.
Docker and Docker Compose
GameFrameX supplies a Docker Compose definition for its local MongoDB dependency. Install a recent Docker Desktop release or another Docker installation that provides the docker compose command. Start the Docker engine before running the database step, then verify that the command is available:
docker compose version
This guide uses MongoDB from docker/mongo. The repository also contains PostgreSQL resources for the administrative backend, but PostgreSQL is not required for the documented game-server and Unity quick-start flow covered here.
Git or a ZIP extraction tool
Git is the most direct download method and makes later updates easier. The project also documents downloading the complete repository as a ZIP. Use one method, not both, and ensure that the resulting top-level directory contains at least Server, Unity, and docker.
Unity Editor for the included demonstration project
For the exact aggregated-project walkthrough, install Unity 2019.4.40f1 through Unity Hub. The separately maintained GameFrameX Unity framework describes broader compatibility with Unity 2019.4 and above, but that broader framework statement should not be used to silently substitute another editor version for this repository's documented demonstration procedure. Using the exact documented editor version removes an avoidable variable.
The first Unity import downloads packages and therefore needs internet access. It can take longer than later project openings. Wait for package resolution and script compilation to finish before judging whether the client works.
Localtonet client and account
Remote access is a separate phase. Install and run our client on the GameFrameX server host, or on another device that can reach the host's local TCP and HTTP listeners. The device is identified by its Localtonet authentication token. Treat that token as a secret, never place it in game code or screenshots, and never copy an example token from a tutorial.
You can start MongoDB, build GameFrameX, launch the server, and verify ports 29100 and 28080 without opening Unity. Unity 2019.4.40f1 is required here only for the complete included client-server demonstration.
Install and start the GameFrameX server
The following sequence follows the aggregated repository's quick-start path. Run commands from the stated directories. Relative paths such as ../../Server work only when the preceding directory changes have succeeded.
Download the aggregated GameFrameX repository
Clone the complete project and enter its root directory. The repository is designed to run as the complete project, so this path does not require a separate pull of the server or Unity client.
Start the supplied MongoDB service
Enter docker/mongo and run Docker Compose in detached mode. The supplied development setup creates the MongoDB service used by the server and stores its data beneath docker/mongo/database/.
Build the .NET server
Move from docker/mongo to the repository's Server directory and run dotnet build. Resolve compilation or SDK errors before attempting to launch the generated assembly.
Launch the server with the local database URL
Enter Server/bin/app_debug and launch GameFrameX.Launcher.dll, explicitly replacing the project's default database destination with the local MongoDB connection string.
Confirm the application listeners
From another terminal, test localhost TCP ports 29100 and 28080. Both must accept connections for the complete default client flow. You can also inspect the server output for successful startup and listener messages.
Clone the repository
git clone https://github.com/GameFrameX/GameFrameX.git
cd GameFrameX
If Git is unavailable, download the repository ZIP from its GitHub page, extract it, and open a terminal in the extracted GameFrameX directory. The commands below assume that this is the current directory.
Start MongoDB
cd docker/mongo
docker compose up -d
The documented development MongoDB instance uses admin as both its username and password and listens locally on port 27017. Its database files are stored under docker/mongo/database/. Check that the container is running before building the server:
docker compose ps
Do not expose MongoDB port 27017 through Localtonet, a router rule, or a public firewall rule. Do not reuse the documented admin/admin combination for an internet-facing or production database. The tunnel configuration later in this guide targets only the GameFrameX application listeners.
Build the server
From docker/mongo, move to the server directory and build:
cd ../../Server
dotnet build
Let the build complete before proceeding. The documented launch location is Server/bin/app_debug, relative to the repository root. If that directory or the launcher assembly is missing, do not create an arbitrary replacement path. Review the build output first because the expected artifacts may not have been generated.
Launch GameFrameX against local MongoDB
cd bin/app_debug
dotnet GameFrameX.Launcher.dll --DataBaseUrl="mongodb://admin:admin@localhost:27017/?authSource=admin"
The explicit --DataBaseUrl value is important. The repository states that its default points to a public demonstration database, while this self-hosted workflow should use the MongoDB instance started on the same machine. The remaining application ports use the project's defaults, so no port arguments are required for the basic walkthrough.
Keep this terminal running. Stopping the process stops the game server, and the Localtonet tunnels cannot make an inactive listener available.
Optional IDE startup
GameFrameX also documents opening Server/Server.slnx in Rider or Visual Studio. If the IDE does not support the newer solution format, use Server.sln. Set GameFrameX.Launcher as the startup project and use Server/bin/app_debug as the working directory.
The documented IDE alternative changes the default DataBaseUrl in Server/GameFrameX.Launcher/StartUp/AppStartUpGame.cs and starts without arguments. For repeatable local and remote testing, the command-line override has an advantage: it avoids committing a development credential or machine-specific database address into source control.
Verify GameFrameX locally before creating tunnels
A successful build proves only that the code compiled. It does not prove that MongoDB is reachable, startup completed, or the required ports are listening. Validate each layer while the server process remains active.
Check the TCP and HTTP listeners
On a system with Netcat available, run:
nc -z localhost 29100
nc -z localhost 28080
A successful connection check on 29100 confirms that a process accepts TCP connections at the game endpoint. A successful check on 28080 confirms that the HTTP listener is reachable at the transport layer. These checks do not validate a complete login or game protocol exchange, but they quickly distinguish a closed port from a higher-level client problem.
If nc is not installed, use an operating-system networking utility capable of testing a TCP port or inspect the server log for startup text indicating that the application has started and is listening. This article does not prescribe an unevidenced package-installation command because the correct package manager varies by operating system.
Interpret the result carefully
| Observed result | Likely layer | Next check |
|---|---|---|
| Both 29100 and 28080 accept connections | Core server listeners are active | Proceed to the Unity client test. |
| Neither port accepts connections | Server process or startup failure | Inspect launcher output, build artifacts, and MongoDB availability. |
| 29100 works but 28080 fails | HTTP listener did not start or is unavailable | Review server logs before testing login-related client behavior. |
| 28080 works but 29100 fails | Game TCP listener did not start or is unavailable | Do not create the TCP tunnel until the local listener works. |
| Ports work but Unity fails | Client configuration, protocol, package, or application layer | Finish Unity imports and confirm that it targets the documented local endpoints. |
Port tests establish reachability only. The strongest local verification is the included Unity flow: reach the login screen, create a character, and enter the main city. Complete that test before replacing localhost endpoints with public tunnel addresses.
Connect and test the included Unity client locally

The aggregated repository includes a Unity project already aligned with the server defaults. This makes it useful as an integration test before modifying endpoints for remote access.
Add the Unity project through Unity Hub
Select the repository's Unity/ directory and open it with Unity 2019.4.40f1, the editor version documented for this complete quick-start project.
Wait for the first import to finish
Allow Unity to download packages, import assets, and compile scripts. The first opening requires internet access and may take substantially longer than subsequent starts.
Open the launcher scene
Load Assets/Scenes/Launcher.unity. Keep the GameFrameX server and MongoDB running on the same machine for the initial local test.
Enter Play mode and test the complete loop
Press Play. The included client defaults to 127.0.0.1, with TCP on 29100 and HTTP on 28080. Reaching login, creating a character, and entering the main city verifies the documented client-server path.
Do not change the client to a public address before this local test works. If remote access is introduced too early, a single visible failure could originate from Unity package imports, application startup, MongoDB, client endpoint configuration, DNS, the TCP tunnel, or the HTTP tunnel.
When the local demonstration succeeds, record which operations use HTTP and which use the persistent game connection. Login may reach the HTTP service before gameplay establishes or depends on the TCP connection. This is why opening only port 29100 may leave a remote client at a login or API error even though the game tunnel itself is healthy.
Expose the working GameFrameX endpoints with Localtonet

With Localtonet, our client establishes an outbound connection from the server-side device to a relay. The TCP tunnel supplies a public host and port that forwards to the local GameFrameX TCP listener. The HTTP tunnel supplies a public HTTPS address that forwards to the local HTTP service. This avoids inbound router port forwarding, firewall changes, VPN setup, and the requirement for a public IP address.
Creating a tunnel does not automatically make it active. It must be started, and it remains available only while the selected Localtonet client is connected and the tunnel is running.
Create the TCP tunnel for the game connection
Run our client where it can reach GameFrameX
Install and run the Localtonet client on the GameFrameX host or on another trusted device with network access to the server's TCP port 29100 and HTTP port 28080.
Select the device authentication token
In the Localtonet dashboard, select the device-specific token belonging to the connected client. Do not paste the token into Unity, GameFrameX configuration, logs, or public documentation.
Select an available relay server
Choose from the server or region values currently available in your dashboard. Availability can vary, so this guide does not hardcode a relay code or claim that every region is included in every plan.
Create a TCP tunnel to the local game listener
Choose the TCP tunnel type and set its local target to the GameFrameX server address and port 29100. Use 127.0.0.1 when our client runs on the same machine and the service is reachable there.
Start the tunnel
Use the Start control after creating the configuration. Wait until the client is connected and the tunnel is running, then note the assigned public TCP host and port.
Test the public TCP endpoint
From a different network, test the assigned host and port. A transport connection confirms the tunnel path, while a complete Unity session confirms the application protocol.
Create a separate HTTP tunnel for login and APIs
If the Unity client performs login or other API calls against port 28080, create an HTTP tunnel whose local target is the GameFrameX host on port 28080. Select the connected device token and a currently available relay server, create the HTTP configuration, and start it. HTTP tunnels provide a public HTTPS address.
HTTP process types can use a random subdomain, a custom subdomain, or a custom domain, with availability depending on the current product configuration and plan. All serve the target content at a public HTTPS address. This guide does not provide exact custom-domain DNS records because those requirements must be checked against the current dashboard and documentation.
The public HTTPS address maps to local port 28080 and is intended for HTTP requests. The Unity game's long-lived TCP connection must use the public host and port assigned to the TCP tunnel for local port 29100. Preserve the distinction in client configuration.
Point a remote Unity client at the public endpoints
Replace the client's local TCP destination, 127.0.0.1:29100, with the public host and port assigned by the Localtonet TCP tunnel. Replace the local HTTP base address for 127.0.0.1:28080 with the public HTTPS address assigned by the HTTP tunnel.
The supplied evidence establishes the default endpoints but does not identify a single authoritative configuration file, Inspector field, or runtime setting for replacing both addresses in every GameFrameX revision. We therefore do not invent a file path or variable name. Locate the endpoint configuration used by the included client revision, change only the host, port, and HTTP base address it already defines, and keep the original local values available for rollback.
If the project splits its login URL and game server destination, configure both. If it constructs the game endpoint from data returned by an API, account for that application behavior rather than assuming that changing one visible URL automatically changes the TCP destination.
Test from a genuinely remote network
A test from the server itself can hide DNS, local routing, and client-network differences. Run the Unity client on another machine or network after changing its endpoints. Observe the sequence:
- The HTTP login or related API request reaches the public HTTPS address.
- The game client connects to the public TCP host and port.
- Character creation and entry into the main city complete as they did locally.
If the login interface appears but entering the game fails, test the TCP tunnel. If login itself fails while the TCP endpoint accepts a connection, inspect the HTTP tunnel and client API base address. If both public endpoints fail, first confirm that our client remains connected and both tunnels are running.
Security boundaries for a remotely accessible development server
A tunnel removes the need for inbound router configuration, but it does not remove the need for application security. A public endpoint can receive traffic from outside the local network. Expose only the listeners required for the intended test and stop them when the session ends.
Replace development credentials before production use
The supplied Compose environment and command line are appropriate for reproducing the documented local quick start. They are not a complete production database-security design. Replace default credentials, manage secrets outside source control and command histories where appropriate, restrict database reachability, establish a backup policy, and validate the project's deployment guidance before treating the environment as production.
Keep observability endpoints private by default
Metrics often reveal service names, operation patterns, or runtime details. The GameFrameX metrics listener is disabled by default, and this guide leaves it disabled. If a later observability design enables --IsOpenTelemetryMetrics true with --MetricsPort 29090, place access controls around that endpoint rather than publishing it alongside the game service without review.
Do not enable WebSocket without a client requirement
WebSocket on port 29110 is also disabled by default. The documented startup option is --IsEnableWebSocket true, but merely enabling it does not prove that a particular Unity workflow requires or uses it. Keep the default until the application architecture calls for WebSocket and the client has been configured accordingly.
Routine operation and troubleshooting
Recommended startup order
A consistent startup sequence reduces false failures:
- Start Docker and the supplied MongoDB Compose service.
- Launch
GameFrameX.Launcher.dllwith the local database URL. - Verify local ports 29100 and 28080.
- Start the Localtonet client and confirm that its device is connected.
- Start the TCP tunnel and, when required, the HTTP tunnel.
- Launch the remote Unity client using the public endpoints.
Reverse the exposure portion when ending a test: close remote clients, stop the public tunnels, stop the GameFrameX server when no longer needed, and then stop MongoDB if no other local process depends on it.
MongoDB does not start
Run docker compose ps from docker/mongo and inspect the Compose output. Confirm that the Docker engine is active and that another process is not already using the required local resources. If a container starts and then exits, use Docker's container logs rather than repeatedly rebuilding the .NET server. The database and server are separate layers.
The server cannot connect to MongoDB
Confirm that MongoDB is running and that the launcher receives the complete local URL:
mongodb://admin:admin@localhost:27017/?authSource=admin
The authSource=admin portion matters because the supplied credentials authenticate against the administrative database. Also confirm that the server and MongoDB share the expected interpretation of localhost. The command in this guide assumes the .NET server runs directly on the same host as the Compose-published MongoDB service.
The build fails before creating the launcher
Check dotnet --version and confirm .NET SDK 10.0 or newer. Make sure the command is running inside the repository's Server directory. Do not troubleshoot tunnels at this stage because there is no functioning local target until the build and launch succeed.
Local ports work, but the Localtonet TCP endpoint does not
Verify that the selected device token belongs to the currently connected Localtonet client, the TCP tunnel targets the correct local address and port 29100, and the tunnel was started after creation. If our client runs on a different device, 127.0.0.1 refers to that client device, not automatically to the GameFrameX host. In that topology, use the GameFrameX host address that is reachable from the Localtonet client device.
Remote login fails, but the TCP endpoint is open
Check whether the client still points its HTTP requests to 127.0.0.1:28080. On a remote machine, that address refers to the remote machine itself. Configure the client to use the public HTTPS address from the HTTP tunnel and confirm that the HTTP tunnel targets local port 28080.
Login works, but gameplay cannot connect
Confirm that the Unity client uses the public TCP host and public TCP port exactly as assigned. Do not substitute local port 29100 for the assigned public port unless the dashboard actually assigns that value. The remote side connects to the public endpoint; Localtonet forwards it to local port 29100.
The tunnel worked and then became unavailable
Check the complete lifecycle. The GameFrameX process must still be running, our client device must remain connected, and the tunnel must remain started. Closing the Localtonet client, stopping the tunnel, losing the device's outbound connectivity, or stopping GameFrameX makes the public endpoint unavailable.
The Unity project reports errors on first opening
Confirm that Unity 2019.4.40f1 opened the repository's Unity/ folder and that package downloads completed. Wait for compilation to settle before entering Play mode. If the project was opened with another editor version, reproduce the issue with the documented version before attributing it to GameFrameX networking.
Do not debug every layer at once
First test MongoDB, then server startup, then local ports, then the local Unity loop, then each public tunnel, and finally the remote Unity loop. The first failing layer is usually where investigation should remain. Later layers depend on all earlier ones.
Frequently asked questions
Which GameFrameX port should I expose for a remote Unity client?
Use a Localtonet TCP tunnel for local port 29100, which handles the long-lived game-client connection. If the client also performs login or related API calls through the default HTTP service, create a separate HTTP tunnel for local port 28080.
Can one HTTP tunnel handle both GameFrameX ports?
No. The default services use different protocols and ports. The HTTP tunnel maps HTTP requests to port 28080, while the persistent game connection uses a TCP tunnel mapped to port 29100. Configure the Unity client with both public endpoints when it uses both services.
Do I need to expose MongoDB for GameFrameX clients?
No. MongoDB is a server-side dependency. Unity clients communicate with the GameFrameX application listeners, not directly with the database. Keep port 27017 private, especially because the quick-start Compose environment uses development credentials.
Is Unity required to self-host the GameFrameX server?
Unity is not required to compile, launch, or test whether the server ports are listening. Unity 2019.4.40f1 is required for the complete included demonstration that verifies login, character creation, and entry into the main city.
Does creating a Localtonet tunnel start it automatically?
No. Creating and starting are separate lifecycle actions. After configuring the local target, use the Start control. The endpoint remains available only while the selected client device is connected and the tunnel is running.
Do I need router port forwarding or a public IP address?
No. Our client establishes an outbound connection to a Localtonet relay. This allows the selected local service to receive traffic through its assigned public endpoint without inbound router port forwarding, firewall changes, VPN setup, or a public IP address.
Should I enable GameFrameX WebSocket port 29110?
Not for the default walkthrough. WebSocket is disabled by default and requires the documented --IsEnableWebSocket true option. Enable and expose it only when the application and client are intentionally designed to use that service.
Can the Localtonet client run on a different machine from GameFrameX?
Yes, provided that the client device can reach the GameFrameX host and its required local ports. In that arrangement, target the GameFrameX host's reachable network address. Do not use 127.0.0.1, because it would refer to the separate Localtonet client device.
Connect your verified GameFrameX server with Localtonet
Once the local Unity loop works, run our client, map a TCP tunnel to port 29100, and add an HTTP tunnel for port 28080 when the remote client needs login and API access. Keep MongoDB and optional diagnostic services private, then stop the tunnels when testing is complete.
Get Started Free โ