Configure Nebula
Set project defaults in NebulaConfig and nebula.json, then override them for individual processes or CLI runs.
Use these configuration layers:
- Edit
NebulaConfigin Unity to configure the runtime. - Edit
nebula.jsonto configure the CLI for one project. - Run
nebula configto store machine-specific paths and credentials. - Pass a command-line option when you need to override a value for one run.
Configure the runtime in Unity
Open Assets/Resources/NebulaConfig.asset in the Inspector. Every Nebula process loads this asset, so the client, workers, gateway, and orchestrator use the same defaults.
Run nebula init to create the asset. For every field and its current default, see the NebulaConfig reference.
Game content and world loading
| Field | Default | What to set |
|---|---|---|
GameScene | Arena | Select the scene that contains your containers and gameplay. |
NetworkPrefabs | empty | Add every prefab that Nebula can spawn. The list index becomes the prefab ID sent over the network. |
WorldManifest | none | Assign a baked manifest when you partition a large world. Leave it empty for a single scene or a RuntimeWorld. |
RuntimeWorld | none | Assign a WorldDefinition for a procedural world whose containers are registered at runtime. Leave WorldManifest empty. |
ClientLoadRadiusCells | 1 | Choose how many cells clients load around their pawn. A value of 1 loads a 3 × 3 × 3 group of cells. |
WorkerLoadRingCells | 1 | Choose how many neighboring cell rings a worker loads around its leased cells. |
OriginShiftThresholdCells | 4 | Move the floating origin after the client pawn or worker lease center crosses this many cells. |
SceneEntityGraceSeconds | 2 | Wait this long before a new container owner spawns scene entities that did not arrive in a handover. |
Editor dev loop
These fields change only what pressing Play in the Editor starts. Builds ignore them. See Iterate without building.
| Field | Default | What to set |
|---|---|---|
EditorRunMode | Mesh | Mesh runs NebulaBootstrap.EditorRole against a mesh started with nebula start. MultiplayerPlayMode lets a Multiplayer Play Mode virtual player host the server while the main Editor joins as a client, with no build. |
EditorPersistence | DevSaveFile | DevSaveFile keeps the dev server's saved entities in Library/Nebula/DevSaves/world.bin between Play sessions. InMemory starts every Play from an empty world. |
EditorPortOffset | 50 | Add this to the gateway, worker and dashboard ports in MultiplayerPlayMode, so a mesh started with nebula start can run at the same time. 0 uses the configured ports. A checkout's UserSettings/NebulaEditorPortOffset.txt overrides it for that checkout. |
Server build
These fields apply to the Linux dedicated server that nebula build --linux and nebula deploy build (and to Nebula > Build), in the Editor only. The defaults are the build every server was before: a Mono development build.
| Field | Default | Meaning |
|---|---|---|
ServerBuildDevelopment | on | A development build: slower, with the profiler and script debugging. Turn it off for a release server. |
ServerBuildScriptingBackend | Mono | Mono or IL2CPP. IL2CPP needs the Linux IL2CPP module in the Unity install. |
nebula build --linux --release-build --il2cpp (or --development-build, --mono) overrides them for one build, and nebula deploy takes the same flags.
IL2CPP notes. Nebula finds [ClientRpc], [ServerRpc] and [AuthorityRpc] methods, NetworkVariable fields and INetworkSerializable types by reflection, so managed stripping must not remove them. The package keeps its own assembly with a link.xml; your game's assemblies need the same, for example a link.xml beside your scripts with <assembly fullname="YourGame" preserve="all" />. Test an IL2CPP server with a bot or client before you deploy it: a stripped RPC fails at run time, not at build time. In a release build Debug.isDebugBuild is false; Nebula does not read it.
Connections and processes
| Field | Default | What to set |
|---|---|---|
GatewayAddress, GatewayPort | 127.0.0.1, 7000 | Set the address and port clients use to reach the gateway. |
WorkerBasePort | 7100 | Set the base for worker ports. Worker 1 uses 7101, worker 2 uses 7102, and so on. A worker started with -nebula-port, or with the PORT environment variable set, listens on that port instead. |
WorkerAdvertiseAddress | 127.0.0.1 | Set the address workers advertise to peers and the gateway. |
WebClients | true | Let the standalone gateway accept clients from a Unity Web build over WebRTC. See Build for the web. |
WebPort | 0 | Set the gateway's TCP port for WebRTC offers and the web build. 0 uses the same number as GatewayPort. A web client connects to this port. |
WebRtcPort | 0 | Set the gateway's UDP port for WebRTC traffic. 0 uses GatewayPort + 1. |
ControlPlaneUrl | http://127.0.0.1:7080/ | Set the orchestrator's dashboard address for a worker or gateway you start by hand. The orchestrator passes it to the processes it launches. |
MeshToken | empty | Set a shared secret that workers and gateways present to the orchestrator, and to each other when they connect. Empty means no token and every peer is accepted. nebula deploy generates one per deployment. |
UseLocalControlPlane | false | Enable the in-process control plane only when all server roles run in one process, such as in a test. |
DatabaseUrl | empty | Select where the orchestrator keeps the control plane and saved entities: sqlite:<file>, postgres://..., file:<folder>, or memory. Empty means a default next to the process. |
WorkerCount | 4 | Set the number of workers to start with. |
WorkerHost | process | Use process for child processes, hetzner for one Hetzner Cloud VM per worker, or cloud to request machines from a hosting platform's resource API. See Choose where workers run. |
OrchestratorSpawnsGateway | true | Let the orchestrator start one gateway (gw1) as a child process. Turn it off when whoever runs the gateway fleet starts every gateway. |
DashboardPort | 7080 | Set the dashboard port. Use 0 to disable the dashboard. |
Autoscaling
The orchestrator keeps the worker count between MinWorkers and MaxWorkers from the tick time workers report, and
checks every change against a dry run of the assignment policy first. See
Autoscale.
| Field | Default | Command line | nebula.json | What to set |
|---|---|---|---|---|
MinWorkers | 1 | -nebula-min-workers <n> | mesh.minWorkers | Set the fewest workers autoscaling leaves running. 0 allows scaling to zero: the first player then waits for a worker to boot. |
MaxWorkers | 32 | -nebula-max-workers <n> | mesh.maxWorkers | Set the most workers the orchestrator will ever run. |
AutoScale | true | -nebula-autoscale true|false | — | Turn autoscaling off to keep WorkerCount workers running whatever the load. |
ScaleOutUtilization | 0.7 | — | — | Grow when the busiest worker spends more than this fraction of its tick budget simulating (0.7 = 11.7 ms of a 16.7 ms tick). |
ScaleInUtilization | 0.3 | — | — | Shrink when the mesh's mean utilization stays under this fraction and the survivors would stay under ScaleOutUtilization. |
ScaleHoldSeconds | 30 | — | — | Choose how long a condition must hold before a worker is added or retired. Only one change happens per hold. |
ScaleWindowSeconds | 20 | — | — | Set the length of the rolling per-worker tick-time window whose 90th percentile is the scaling signal. |
ScaleMinGain | 0.1 | — | — | Require this much predicted improvement in the busiest worker before adding a worker or re-dealing containers. Below it the orchestrator reports the hot container as unsplittable instead of growing. |
SeamGraceMeters | 10 m | — | — | Leave a container alone for a pass when a player is within this distance of a seam that would move. Configured but not enforced yet: occupancy reports carry counts, not positions. |
IdlePoolSeconds | 0 | -nebula-idle-pool <seconds> | mesh.idlePoolSeconds | Keep a retired worker parked for at most this long on a host that parks. 0 means as long as it is already paid for (Hetzner: the rest of the billed hour). See Idle pool. |
The fields without a command-line option are set on the NebulaConfig asset. nebula start --workers N fixes the
count (min = max = N); nebula start --min A --max B opens the band, starts the mesh at A, and lets
autoscaling grow it towards B.
Failure and handover timing
| Field | Default | What to set |
|---|---|---|
WorkerHeartbeatSeconds | 1 | Choose how often each worker reports that it is alive. |
WorkerTimeoutSeconds | 5 | Choose how long the orchestrator waits before it treats a silent worker as dead. |
TickRate | 60 | Set how many ticks per second the whole mesh simulates, from 10 to 240. Every worker, the orchestrator and the gateway run at this rate, and a client takes it from the gateway when it joins. Unity's fixed step is one tick. A lower rate gives each tick a longer budget (33 ms at 30 Hz) and halves every per-tick cost, and adds up to one tick of latency to each hop. Nebula's own timing settings are in seconds, so they mean the same at any rate; convert your own tick counts with NetworkTime.SecondsToTicks. A mesh that is not at 60 Hz refuses clients older than protocol 30. -nebula-tick-rate <hz> or the NEBULA_TICK_RATE environment variable overrides it. |
WorkerCatchUpBudgetMs | 40 | Limit the time a worker spends simulating ticks in one frame while it catches up with the clock. Ticks past the limit run in later frames, or are skipped when the worker is more than a quarter of a second behind. Set 0 to remove the limit. |
ServerFrameRate | 0 | Set how many frames per second a worker or gateway process runs. 0 runs at the tick rate (TickRate), one tick a frame. Simulation stays at the tick rate whatever you set. The process polls its network once per frame, so a higher rate lowers latency a little, but every extra frame costs CPU. A lower rate, down to 10, runs several ticks in a frame, which is a way to see how a loaded server behaves. Clients are not affected. -nebula-server-fps <n> overrides it. |
WorkerPollBeforeTick | true | Poll the worker's network at the start of each frame's first fixed update, before it simulates, so an input that has just arrived is handled by the tick that follows. -nebula-poll-before-tick <true|false> overrides it. |
FlushRpcsImmediately | true | Send an OwnerRpc and a Delivery.Sequenced client RPC onto the wire as soon as the worker sends it and the gateway forwards it, and let a gateway send what it forwarded from a poll before it does its other work. -nebula-flush-rpcs <true|false> overrides it. |
DeadWorkerReplaceDelaySeconds | 8 | Wait this long before starting a replacement for a dead worker. |
WorkerDrainTimeoutSeconds | 10 | Give a retiring worker this long to transfer its entities before stopping it. |
SessionReclaimSeconds | 30 | Keep a player's pawn this long after the player's link drops, so the player can reconnect (through any gateway of the mesh) with the same session and pawn. 0 despawns at once. See Sessions and reconnection. |
SingleSessionPerPlayer | true | Gateways coordinate one connection per identity. A replacement waits for the previous gateway to acknowledge disconnection; admission fails if coordination is unavailable. Turn it off on every gateway to allow multiple sessions per identity. See One connection per player. |
GatewayDrainReconnectSeconds | 10 | Tell the clients of a draining gateway that they have this long to reconnect before it closes their links. |
GatewayShutdownDrainSeconds | 0.5 s | When a gateway process stops, it first tells its clients that it is draining, or that the server is shutting down when no other gateway is serving, and waits up to this long for the notice to go out. It stops sooner once every client has hung up. 0 stops at once without telling anyone. See Replace gateways and workers. |
GhostBandMargin | 4 m | Create a ghost copy when an entity comes within this distance of a neighboring container. |
HandoverHysteresis | 0.35 m | Require an entity to move this far into a new container before transferring authority. |
GhostLingerSeconds | 2 | Keep a ghost copy for this long after it leaves the ghost band. |
ScopeRenderingLayers | 0 | A mask of rendering-layer bits a client reserves for drawn scopes, one per scope drawn at once. Nebula stamps a scope's bit, and only that bit, on its static content, its chunks' content and its entities' renderers. 0 turns slots off; eight bits allow eight scopes. See Draw what is through a portal. |
PortalProxyLayer | 31 | The physics layer Nebula puts a portal's proxies and aperture colliders on. Keep it free of your own objects and out of your own layer masks. See Collide across a portal. |
StateHistorySeconds | 0.533 | Seconds of pose and [SyncHistory] state each worker keeps per entity, for NetworkIdentity.StateAt: 32 ticks at 60 Hz, 16 at 30. 0 turns recording off. See Lag compensation. |
Persistence
Entities carrying a PersistentEntity component are saved and restored. See Persistence.
| Field | Default | What it does |
|---|---|---|
PersistenceMode | auto | Select the store: auto (the orchestrator's database, a worker's remote store, or local when UseLocalControlPlane is on), database, remote, local, memory, or off. |
PersistenceLocalFile | empty | Set the file the local store writes to. Empty uses <persistentDataPath>/nebula-persistence.bin. |
PersistenceCheckpointSeconds | 5 | Choose how often an authoritative persistent entity is checkpointed. A change or a move saves sooner. |
PersistenceRestoreGraceSeconds | 3 | Wait this long after gaining a container lease before restoring that container's saved entities. |
ScopeIdleRetireSeconds | 300 | Retire a simulation scope that has held nothing for this long: checkpoint its persistent entities, release its containers, and bring it back when the key is activated again. 0 turns retirement off. Never applies to the public world. |
ScopeRetireWithEntities | false | Retire an idle scope that no player is in even though it still holds entities, such as saved crates or parked vehicles. See Retire a world that still holds things. |
Interest management
Interest management decides which entities a client hears about at all. These fields are on NebulaConfig; see that guide for the full explanation, the policy API, and the observability fields.
| Field | Default | What it does |
|---|---|---|
InterestRadius | 120 m | How far a client hears about an entity. A prefab's RelevanceRadius overrides it per entity. |
InterestExitMargin | 16 m | Extra distance past InterestRadius an entity must cross before it leaves a client's set. |
InterestLingerSeconds | 1 s | How long an entity must stay past the exit radius before the client is told to despawn it. |
InterestCellSize | 64 m | Edge length of one interest region. Snapped to an integer divisor of the world's cell size when a world definition exists. |
InterestPlanar | true | Regions are infinite columns; height does not affect the region key. Turn off for a volumetric or space game. |
InterestEvalHz | 4 | How often each client's interest set is re-evaluated per second. |
InterestSubscribeMargin | 32 m | Extra distance of regions a gateway subscribes beyond a focus, ahead of a client's exact filter needing them. |
InterestRegionLingerSeconds | 3 s | How long a region stays subscribed after the last client needed it. |
InterestLinkLingerSeconds | 10 s | How long a gateway keeps a worker connection after the last reason to hold it is gone. |
InterestResyncSeconds | 30 s | How often a gateway resends its whole subscription as an audit. |
InterestMaxRadius | 1024 m | Ceiling on a prefab's RelevanceRadius, and the farthest a wide entity may reach. Never uncapped: a value of 0 or less is reported and replaced with InterestRadius. |
InterestMaxFoci | 8 | Most foci one client may have at once. |
InterestHintMaxDistance | 60 m | How far a client's focus hint may sit from its pawn before it is clamped. |
InterestHintMaxHz | 5 | Most focus hints accepted from one client per second. |
InterestMaxExplicitPerClient | 16 | Most entities one client's policy may subscribe to by ID. |
InterestFarMaxEntities | 64 | Most entities one client holds in the far tier at once, nearest first. 0 turns the far tier off. |
InterestMaxFocusSpeed | 12 m/s | The fastest a player is expected to travel, used to check InterestSubscribeMargin. |
InterestMaxTravelPerUpdate | 4 m | Send a fast entity often enough that it travels no more than this between two updates a client receives. 0 turns it off. See Fast movers. |
InterestFocusLeadSeconds | 0.5 s | Add a focus this many seconds of travel ahead of a fast pawn, when that is further than InterestExitMargin. 0 turns it off. |
PartitionWarnEntities | 2000 | A worker warns when one container holds more entities than this. 0 disables the warning. |
PartitionWarnFilterMs | 2 ms | A worker warns when per-gateway filtering takes longer than this per tick. 0 disables the warning. |
NebulaConfig.Validate checks the interest settings at startup. A non-positive InterestRadius or InterestCellSize blocks startup. Other invalid values are adjusted, with warnings for most corrections.
- Update-rate bands satisfy
InterestNearRadius <= InterestFarRadius <= InterestRadius. - The exit margin is positive, and the subscription margin covers at least one evaluation interval of travel at
InterestMaxFocusSpeed. - Region size is aligned to a divisor of the world cell size. A ghost band at least as wide as a region produces a warning; validation does not change the ghost band.
ClientLoadRadiusCellsis raised to coverInterestRadius + InterestExitMargin. The effective streaming radius,NearCells, also includes movement during removal delays. The runtime allocator usesNearCells + ChunkedWorldServerRingMargin(NearCells + 1by default).InterestMaxRadiusis at leastInterestRadius. Zero does not disable this limit.
Gateway extension
See Extend the gateway to build and load the class library.
| Field | Default | What to set |
|---|---|---|
GatewayExtension | empty | Your game's code inside the standalone gateway: the extension assembly's file name (next to the gateway executable) or an absolute path. Empty means no extension. |
GatewayExtensionType | empty | Which class to load, only needed when the assembly defines more than one IGatewayExtension. |
GatewayExtensionOptions | empty | Options your extension reads with context.Option(key), as key=value;key=value. |
These are not numeric knobs and are not clamped: a configured extension that fails to load stops the gateway from starting.
chunked world
See Build an infinite runtime world for the full setup.
| Field | Default | What to set |
|---|---|---|
ChunkedWorld | false | Turn on the unbounded chunked world: with RuntimeWorld assigned, Nebula builds the chunk grid from its cell size, leases chunks around every pawn on workers, keeps the floating origin near the pawn on clients, and raises NebulaChunks.Loaded/Unloading on every role. |
ChunkPlanar | true | Chunks are columns: the grid has one layer at y = 0 and RuntimeWorld.CellSize.y is the column height. Turn off for a volumetric world. |
ChunkRetireSeconds | 30 | Seconds a chunk nobody needs stays leased before the worker retires it. Its persistent contents are checkpointed and restored when the chunk is requested again. |
ChunkedWorldServerRingMargin | 1 | Chunks the worker leases beyond NearCells around every pawn. 0 leases only the chunks interest can reach (9 instead of 25 at near 1) and warns when the time to build a newly requested chunk gets short. See Chunk ring. |
Client update rates and prediction
| Field | Default | What to set |
|---|---|---|
InterestNearRadius | 30 m | Forward each available unreliable root update inside this distance from the client's pawn. This throttles update rate for entities already in the client's interest set; it does not decide whether they are in it. See Interest management. |
InterestFarRadius | 80 m | Use the middle update rate between the near and far distances. |
InterestMidDivisor | 4 | Forward available unreliable root updates on every fourth tick in the middle band. Use 1 to forward each available update. Divisors are counted at 60 Hz: at another TickRate they are rescaled so the band keeps its updates per second (4 is every second tick at 30 Hz). |
InterestFarDivisor | 12 | Forward available unreliable root updates on every twelfth tick beyond the far distance, counted at 60 Hz like InterestMidDivisor. Clients without a pawn also use this filter. |
InterestHighTiers, InterestLowTiers, InterestBackgroundTiers | Override off | Give entities of that relevance priority their own near and far distances and divisors (0 sends no updates in a band) instead of the four settings above, shifted. Normal entities always use the four settings above. See Set the distance tiers for a crowd. |
InterpolationDelaySeconds | 0.05 | Render remote entities at least this long behind the latest received state, rounded up to whole ticks: 3 ticks at 60 Hz, 2 at 30. The client adds the lateness it measures on its world-state streams, up to MaxStreamLagSeconds; NebulaClient.RenderDelayTicks shows the total. |
AdaptiveInterpolationDelay | true | Size the added delay from a percentile of how late world-state packets arrive against the client's clock, measured per worker over the last 2 seconds and rounded down. A clean stream adds nothing; a jittery link or a worker that runs behind gets the buffer it needs. The delay rises at once and falls by one tick every half second. false adds the slowest worker's lag behind the newest stream instead, as in earlier versions. |
InterpolationJitterPercentile | 95 | The percentile of packet lateness the adaptive delay covers, from 50 to 100. A higher value buffers more and extrapolates less often. |
MaxStreamLagSeconds | 0.2 | The most the measured lateness may add to the render delay. |
SlowUpdateMaxDelaySeconds | 0.5 | Draw a remote entity whose state arrives further apart than the render delay up to this much later still, by its own gap, so it interpolates between its states instead of holding or extrapolating. Entities sent every tick or two get no extra delay. 0 turns it off. See Interpolation modes. |
InputLeadMarginSeconds | 0.033 | Add this much, rounded up to whole ticks, to half the measured round-trip time when scheduling input. |
InputLeadTargetSeconds | 0.05 | Keep client input this far ahead, rounded up to whole ticks, when it arrives at the worker. |
InputLeadMaxAdjustSeconds | 0.5 | Limit how far the client can increase its input lead. |
A config saved by an earlier version holds these as ticks (InterpolationDelayTicks, InputLeadMarginTicks and so on). Nebula reads those as ticks at 60 Hz when it loads the config, and the old names still work in code as properties in ticks at the running rate.
Client reconnection
These fields control what a client does after its connection drops. See Reconnect after a lost link or a draining gateway.
| Field | Default | What to set |
|---|---|---|
ReconnectFirstDelaySeconds | 1 s | Wait this long after a drop before the first reconnection attempt. |
ReconnectBackoffFactor | 2 | Make each later attempt wait this many times longer than the one before. Use 1 for a fixed delay. |
ReconnectMaxDelaySeconds | 2 s | Never wait longer than this between two attempts. With the defaults, the client retries after 1 s, then every 2 s. |
ReconnectGiveUpSeconds | 0 | Stop reconnecting this many seconds after the drop, and raise NebulaClient.ReconnectGiveUp. 0 never gives up. A value a little above SessionReclaimSeconds stops once the worker has let the pawn go. |
ClientDisconnectTimeoutSeconds | 8 s | Treat the link as lost after this long without a packet from the gateway. Lower values notice a dead gateway sooner, but drop players on a brief network stall. |
ClientPingIntervalSeconds | 0.5 s | Send the transport's keep-alive ping this often. Keep it well below the disconnect timeout. |
ClientStallSeconds | 2 s | Raise NebulaClient.ServerStalled after this long without state from the server while the player is in the world and the link is up. 0 turns the watch off. See Notice a stalled server. |
The two transport settings apply to the UDP transport of desktop and mobile clients. A web build's WebRTC transport uses the browser's own timeouts.
Nebula runs at 60 ticks per second. NetworkTime.TickRate is a constant, not a configuration field.
These distance filters do not create updates for static entities or unchanged transforms. Reliable root recovery, teleports, and container changes bypass the filter so the last pose can arrive after movement stops. Child component state uses a separate channel. See NetworkTransform.
Override runtime values on the command line
Use runtime options when you start a Nebula role by hand. The CLI and orchestrator add these options for the processes they manage.
Pass options as -name value. Pass a Boolean option without a value to enable it.
| Option | Used by | What it does |
|---|---|---|
-nebula-role client|worker|gateway|orchestrator | all roles | Select one or more comma-separated roles. Do not combine the client and worker roles. Use services as an alias for gateway and orchestrator. |
-nebula-scene <name> | all roles | Override GameScene. |
-nebula-gateway <address:port> | client, worker, orchestrator | Set the gateway address. A client connects immediately when you supply this option. |
-nebula-connect | client | Connect to the configured gateway at startup. NebulaTitleScreen stays hidden. |
-nebula-name <name> | client | Set the player's display name. |
-nebula-bot | client | Mark this headless client as a bot. Your game must provide its input behavior. A bot does not keep an anonymous identity between runs. |
-nebula-auth-token <jwt> | client | Present this OpenID Connect ID token to the gateway. See Authentication. |
-nebula-worker-id <id> | worker | Set the worker ID. The orchestrator normally supplies it. |
-nebula-worker-index <number> | worker | Set the worker index. The orchestrator normally supplies it. |
-nebula-port <port> | worker | Set the worker's listening port. Without this option, the worker uses the PORT environment variable, then WorkerBasePort + index. A PORT value that is not a port from 1 to 65535 is ignored with a warning. Other roles ignore PORT. |
-nebula-advertise <address|auto> | worker, gateway, orchestrator | Set the address advertised to other processes. Use auto to select the first private IPv4 address. |
-nebula-control-plane <url> | worker, gateway | Override ControlPlaneUrl. |
-nebula-gateway-id <id> | gateway | Set the gateway's persistent ID (default gw1). Give every gateway of a mesh a distinct one. |
-nebula-web true|false | gateway | Override WebClients. |
-nebula-web-port <port>, -nebula-webrtc-port <port> | gateway | Override WebPort and WebRtcPort. |
-nebula-web-root <folder> | gateway | Serve the web build from this folder. Without it, the gateway serves a Web folder next to its executable or next to its build folder. |
-nebula-web-tls off|acme | gateway, orchestrator | Serve the web port over HTTPS with a certificate from an ACME certificate authority, Let's Encrypt by default. The orchestrator passes it to the gateway it starts. See Serve HTTPS for hosted pages. |
-nebula-web-tls-dir <folder>, -nebula-acme-directory <url>, -nebula-acme-email <address> | gateway, orchestrator | Choose where the certificate and account key are kept, which ACME server issues the certificate, and the contact address it registers. |
-nebula-token <secret> | server roles | Override MeshToken. The standalone services also read NEBULA_MESH_TOKEN. With a token set, gateways and workers refuse peers that cannot present a credential derived from it. |
-nebula-auth-issuers <urls>, -nebula-auth-audience <id>, -nebula-auth-anonymous true|false | gateway, orchestrator | Override AuthIssuers, AuthAudience, and AuthAnonymous. The orchestrator passes them to the gateway it starts. See Authentication. |
-nebula-auth-forward-claims <names>, -nebula-auth-name-claim <name> | gateway, orchestrator | Override ForwardedClaims and NameClaim: the claims of a verified sign-in token the gateway passes to workers, and the claim that becomes the player's name. The orchestrator passes them to the gateway it starts. See Forward token claims to workers. |
-nebula-auth-key <secret> | gateway, orchestrator | Override AuthSigningKey, the key anonymous identity tokens and session tokens are signed with. The standalone gateway also reads NEBULA_AUTH_KEY. Every gateway of a mesh needs the same key. |
-nebula-encrypt-clients true|false, -nebula-require-encryption true|false | gateway, orchestrator | Override EncryptClients and RequireEncryption. The orchestrator passes them to the gateway it starts. See Encrypt client connections. |
-nebula-encryption-cert <file>, -nebula-encryption-key <file>, -nebula-encryption-store <file> | gateway, orchestrator | Choose the Privacy-Enhanced Mail (PEM) certificate and key files the gateway presents to clients, and where a generated self-signed certificate is kept. The standalone gateway also reads NEBULA_ENCRYPTION_CERT and NEBULA_ENCRYPTION_KEY as PEM text. |
-nebula-encrypt true|false, -nebula-gateway-fingerprint <hex> | client | Override ClientEncryption and GatewayFingerprint: encrypt the link to the gateway, and accept only the certificate with this fingerprint. |
-nebula-content-version <number> | Unity client, gateway | Set GameContentVersion. A client announces this number; a gateway checks it. A gateway value of 0 disables the check. See Replace gateways and workers. |
-nebula-min-content-version <number> | Unity gateway | Set the oldest accepted game content version. 0 requires an exact match with GameContentVersion. |
-nebula-single-session true|false | gateway, worker, orchestrator | Override SingleSessionPerPlayer. The orchestrator passes it to the gateway and workers it starts. |
-nebula-database <url> | orchestrator | Override DatabaseUrl. The standalone orchestrator also reads NEBULA_DATABASE_URL. |
-nebula-local-control-plane | server roles | Use the in-process control plane. |
-nebula-persistence-mode auto|database|remote|local|memory|off | worker, orchestrator | Override PersistenceMode. |
-nebula-reset-persistence | orchestrator | Delete every saved entity at startup. |
-nebula-persistence-file <path> | worker, orchestrator | Override PersistenceLocalFile. |
-nebula-persistence-checkpoint <seconds> | worker | Override PersistenceCheckpointSeconds. |
-nebula-scope-idle-retire <seconds> | orchestrator | Override ScopeIdleRetireSeconds. 0 turns scope retirement off. |
-nebula-scope-retire-with-entities true|false | orchestrator | Override ScopeRetireWithEntities. |
-nebula-workers <number> | orchestrator | Set the initial worker count. |
-nebula-min-workers <number>, -nebula-max-workers <number> | orchestrator | Override MinWorkers and MaxWorkers, the autoscaling band. |
-nebula-autoscale true|false | orchestrator | Override AutoScale. |
-nebula-idle-pool <seconds> | orchestrator | Override IdlePoolSeconds. |
-nebula-settings key=value,key=value | orchestrator | Add game-defined, mesh-wide settings to the control plane. |
-nebula-dashboard-port <port> | orchestrator | Set the dashboard port. |
-nebula-dashboard-bind <address|+> | orchestrator | Bind the dashboard to one address. Use + to bind all interfaces. |
-nebula-host process|hetzner|cloud | orchestrator | Select where workers run. |
-nebula-cloud-api <url>, -nebula-cloud-deployment-token <token> | orchestrator | With -nebula-host cloud, the resource API and the deployment-scoped token. The standalone orchestrator also reads NEBULA_CLOUD_API and NEBULA_CLOUD_DEPLOYMENT_TOKEN. See The cloud worker host. |
-nebula-spawn-gateway true|false | orchestrator | Override OrchestratorSpawnsGateway. |
-nebula-worker-exe <path> | orchestrator | Select the executable used to start workers and the gateway. |
-nebula-build-dir <path> | orchestrator | Serve worker build files from this directory at /build/. |
-nebula-ghost-band <meters> | worker | Override GhostBandMargin. |
-nebula-hysteresis <meters> | worker | Override HandoverHysteresis. |
-nebula-tick-rate <hz> | every role | Override TickRate. The orchestrator passes its rate to every process it starts. The NEBULA_TICK_RATE environment variable does the same for a process without the switch. |
-nebula-state-history <ticks> | worker | Override StateHistorySeconds, in ticks at the running rate. 0 turns state recording off. See Lag compensation. |
-nebula-interest-radius <meters> | gateway, worker | Override InterestRadius. See Interest management. |
-nebula-interest-cell <meters> | gateway, worker | Override InterestCellSize. |
-nebula-gateway-extension <file> | gateway | Override GatewayExtension. The orchestrator forwards it to the gateway it launches. See Extend the gateway. |
-nebula-gateway-extension-type <Namespace.Class> | gateway | Override GatewayExtensionType. |
-nebula-gateway-extension-options key=value;key=value | gateway | Override GatewayExtensionOptions. |
-nebula-ext-<key> <value> | gateway | Override one extension option; read inside the extension with context.Option(key). |
-nebula-reset false | orchestrator | Restore the stored control plane instead of starting empty. The default resets this temporary registry state. |
-nebula-verbose | all roles | Write debug-level logs. |
Hetzner deployments also use the other -nebula-cloud-* options (location, type, image, network, ssh key, firewall, and the provider token). Let nebula deploy supply them unless you run the orchestrator yourself. See Deploy to Hetzner Cloud for the supported values.
Unity's standard -batchmode, -nographics, and -logFile <path> options also apply.
A web build has no command line. It reads the same options from the page's query string, without the leading dash, for example ?nebula-name=Player&nebula-connect.
Configure one project in nebula.json
Run nebula init to create nebula.json at the Unity project root. The CLI reads this file for local and cloud defaults.
{
"nebula": "0.1.0",
"executable": "Nebula",
"mesh": {
"workers": 4,
"minWorkers": 1,
"maxWorkers": 4,
"idlePoolSeconds": 0,
"npcs": 0,
"dashboardPort": 7080,
"gatewayPort": 7000
},
"deploy": {
"target": "hetzner",
"meshName": "nebula-my-game",
"workers": 4,
"npcs": 0
}
}| Key | What it controls |
|---|---|
nebula | Records the CLI version that last wrote the file. nebula init updates it. |
executable | Sets the base name of builds produced by NebulaBuild, such as Nebula.exe or Nebula.x86_64. |
mesh.workers | Sets the default worker count for nebula start. |
mesh.minWorkers, mesh.maxWorkers | Set the default autoscaling band for nebula start. Leave them out and --workers fixes the count. --min / --max override them, and the mesh starts at the floor. |
mesh.idlePoolSeconds | Sets how long a retired worker stays parked in the idle pool. 0 uses the host's own answer. |
mesh.dashboardPort, mesh.gatewayPort | Set the ports used by a local mesh and by deployment firewalls. |
mesh.database | Select where the local orchestrator keeps the control plane and saved entities. Leave it out for sqlite:Library/Nebula/nebula.db. |
deploy.target | Selects the deployment target: hetzner or cloud (see Deploy to Nebula Cloud). |
deploy.meshName | Sets the label and name prefix used for cloud resources. |
deploy.database | Selects the deployed orchestrator's database (postgres://... or sqlite:<file on the VM>). Leave it out to use nebula config database, else SQLite on the orchestrator VM. |
deploy.workers | Sets the default worker count for nebula deploy. |
deploy.workerType, deploy.orchestratorType, deploy.location | Override the machine types and region stored in the CLI's machine config. |
The mesh.npcs and deploy.npcs keys seed a game setting named npcs. Nebula does not create non-player characters or assign meaning to this setting. Leave both values at 0 unless your game reads the setting.
Configure this computer
Run nebula config commands to store machine-specific paths and credentials in ~/.nebula-cli/config.json:
nebula config source
nebula config unity
nebula config hetzner
nebula config database
nebula config shownebula config show masks the saved Hetzner token and the database password. On Unix, the CLI creates the file with permissions 0600. Set HCLOUD_TOKEN to override the saved token and NEBULA_DATABASE_URL to override the saved database URL.
Set NEBULA_CLI_HOME to move the entire ~/.nebula-cli directory. The directory also contains the CLI binary, a downloaded SDK checkout when you have not configured a source checkout, and temporary project copies used during builds.
Cohesion hints
Keep a set of entities on one worker, move them between workers as a unit, and pause rebalancing of a container for a bounded time.
Pass settings and secrets to workers
Give every worker your game's own environment variables, such as service URLs, API keys, and feature flags, locally and in deployments.