Nebula

Configure Nebula

Set project defaults in NebulaConfig and nebula.json, then override them for individual processes or CLI runs.

Use these configuration layers:

  1. Edit NebulaConfig in Unity to configure the runtime.
  2. Edit nebula.json to configure the CLI for one project.
  3. Run nebula config to store machine-specific paths and credentials.
  4. 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

FieldDefaultWhat to set
GameSceneArenaSelect the scene that contains your containers and gameplay.
NetworkPrefabsemptyAdd every prefab that Nebula can spawn. The list index becomes the prefab ID sent over the network.
WorldManifestnoneAssign a baked manifest when you partition a large world. Leave it empty for a single scene or a RuntimeWorld.
RuntimeWorldnoneAssign a WorldDefinition for a procedural world whose containers are registered at runtime. Leave WorldManifest empty.
ClientLoadRadiusCells1Choose how many cells clients load around their pawn. A value of 1 loads a 3 × 3 × 3 group of cells.
WorkerLoadRingCells1Choose how many neighboring cell rings a worker loads around its leased cells.
OriginShiftThresholdCells4Move the floating origin after the client pawn or worker lease center crosses this many cells.
SceneEntityGraceSeconds2Wait 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.

FieldDefaultWhat to set
EditorRunModeMeshMesh 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.
EditorPersistenceDevSaveFileDevSaveFile keeps the dev server's saved entities in Library/Nebula/DevSaves/world.bin between Play sessions. InMemory starts every Play from an empty world.
EditorPortOffset50Add 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.

FieldDefaultMeaning
ServerBuildDevelopmentonA development build: slower, with the profiler and script debugging. Turn it off for a release server.
ServerBuildScriptingBackendMonoMono 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

FieldDefaultWhat to set
GatewayAddress, GatewayPort127.0.0.1, 7000Set the address and port clients use to reach the gateway.
WorkerBasePort7100Set 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.
WorkerAdvertiseAddress127.0.0.1Set the address workers advertise to peers and the gateway.
WebClientstrueLet the standalone gateway accept clients from a Unity Web build over WebRTC. See Build for the web.
WebPort0Set 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.
WebRtcPort0Set the gateway's UDP port for WebRTC traffic. 0 uses GatewayPort + 1.
ControlPlaneUrlhttp://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.
MeshTokenemptySet 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.
UseLocalControlPlanefalseEnable the in-process control plane only when all server roles run in one process, such as in a test.
DatabaseUrlemptySelect 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.
WorkerCount4Set the number of workers to start with.
WorkerHostprocessUse 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.
OrchestratorSpawnsGatewaytrueLet the orchestrator start one gateway (gw1) as a child process. Turn it off when whoever runs the gateway fleet starts every gateway.
DashboardPort7080Set 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.

FieldDefaultCommand linenebula.jsonWhat to set
MinWorkers1-nebula-min-workers <n>mesh.minWorkersSet the fewest workers autoscaling leaves running. 0 allows scaling to zero: the first player then waits for a worker to boot.
MaxWorkers32-nebula-max-workers <n>mesh.maxWorkersSet the most workers the orchestrator will ever run.
AutoScaletrue-nebula-autoscale true|false—Turn autoscaling off to keep WorkerCount workers running whatever the load.
ScaleOutUtilization0.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).
ScaleInUtilization0.3——Shrink when the mesh's mean utilization stays under this fraction and the survivors would stay under ScaleOutUtilization.
ScaleHoldSeconds30——Choose how long a condition must hold before a worker is added or retired. Only one change happens per hold.
ScaleWindowSeconds20——Set the length of the rolling per-worker tick-time window whose 90th percentile is the scaling signal.
ScaleMinGain0.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.
SeamGraceMeters10 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.
IdlePoolSeconds0-nebula-idle-pool <seconds>mesh.idlePoolSecondsKeep 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

FieldDefaultWhat to set
WorkerHeartbeatSeconds1Choose how often each worker reports that it is alive.
WorkerTimeoutSeconds5Choose how long the orchestrator waits before it treats a silent worker as dead.
TickRate60Set 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.
WorkerCatchUpBudgetMs40Limit 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.
ServerFrameRate0Set 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.
WorkerPollBeforeTicktruePoll 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.
FlushRpcsImmediatelytrueSend 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.
DeadWorkerReplaceDelaySeconds8Wait this long before starting a replacement for a dead worker.
WorkerDrainTimeoutSeconds10Give a retiring worker this long to transfer its entities before stopping it.
SessionReclaimSeconds30Keep 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.
SingleSessionPerPlayertrueGateways 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.
GatewayDrainReconnectSeconds10Tell the clients of a draining gateway that they have this long to reconnect before it closes their links.
GatewayShutdownDrainSeconds0.5 sWhen 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.
GhostBandMargin4 mCreate a ghost copy when an entity comes within this distance of a neighboring container.
HandoverHysteresis0.35 mRequire an entity to move this far into a new container before transferring authority.
GhostLingerSeconds2Keep a ghost copy for this long after it leaves the ghost band.
ScopeRenderingLayers0A 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.
PortalProxyLayer31The 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.
StateHistorySeconds0.533Seconds 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.

FieldDefaultWhat it does
PersistenceModeautoSelect the store: auto (the orchestrator's database, a worker's remote store, or local when UseLocalControlPlane is on), database, remote, local, memory, or off.
PersistenceLocalFileemptySet the file the local store writes to. Empty uses <persistentDataPath>/nebula-persistence.bin.
PersistenceCheckpointSeconds5Choose how often an authoritative persistent entity is checkpointed. A change or a move saves sooner.
PersistenceRestoreGraceSeconds3Wait this long after gaining a container lease before restoring that container's saved entities.
ScopeIdleRetireSeconds300Retire 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.
ScopeRetireWithEntitiesfalseRetire 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.

FieldDefaultWhat it does
InterestRadius120 mHow far a client hears about an entity. A prefab's RelevanceRadius overrides it per entity.
InterestExitMargin16 mExtra distance past InterestRadius an entity must cross before it leaves a client's set.
InterestLingerSeconds1 sHow long an entity must stay past the exit radius before the client is told to despawn it.
InterestCellSize64 mEdge length of one interest region. Snapped to an integer divisor of the world's cell size when a world definition exists.
InterestPlanartrueRegions are infinite columns; height does not affect the region key. Turn off for a volumetric or space game.
InterestEvalHz4How often each client's interest set is re-evaluated per second.
InterestSubscribeMargin32 mExtra distance of regions a gateway subscribes beyond a focus, ahead of a client's exact filter needing them.
InterestRegionLingerSeconds3 sHow long a region stays subscribed after the last client needed it.
InterestLinkLingerSeconds10 sHow long a gateway keeps a worker connection after the last reason to hold it is gone.
InterestResyncSeconds30 sHow often a gateway resends its whole subscription as an audit.
InterestMaxRadius1024 mCeiling 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.
InterestMaxFoci8Most foci one client may have at once.
InterestHintMaxDistance60 mHow far a client's focus hint may sit from its pawn before it is clamped.
InterestHintMaxHz5Most focus hints accepted from one client per second.
InterestMaxExplicitPerClient16Most entities one client's policy may subscribe to by ID.
InterestFarMaxEntities64Most entities one client holds in the far tier at once, nearest first. 0 turns the far tier off.
InterestMaxFocusSpeed12 m/sThe fastest a player is expected to travel, used to check InterestSubscribeMargin.
InterestMaxTravelPerUpdate4 mSend 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.
InterestFocusLeadSeconds0.5 sAdd a focus this many seconds of travel ahead of a fast pawn, when that is further than InterestExitMargin. 0 turns it off.
PartitionWarnEntities2000A worker warns when one container holds more entities than this. 0 disables the warning.
PartitionWarnFilterMs2 msA 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.
  • ClientLoadRadiusCells is raised to cover InterestRadius + InterestExitMargin. The effective streaming radius, NearCells, also includes movement during removal delays. The runtime allocator uses NearCells + ChunkedWorldServerRingMargin (NearCells + 1 by default).
  • InterestMaxRadius is at least InterestRadius. Zero does not disable this limit.

Gateway extension

See Extend the gateway to build and load the class library.

FieldDefaultWhat to set
GatewayExtensionemptyYour 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.
GatewayExtensionTypeemptyWhich class to load, only needed when the assembly defines more than one IGatewayExtension.
GatewayExtensionOptionsemptyOptions 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.

FieldDefaultWhat to set
ChunkedWorldfalseTurn 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.
ChunkPlanartrueChunks are columns: the grid has one layer at y = 0 and RuntimeWorld.CellSize.y is the column height. Turn off for a volumetric world.
ChunkRetireSeconds30Seconds a chunk nobody needs stays leased before the worker retires it. Its persistent contents are checkpointed and restored when the chunk is requested again.
ChunkedWorldServerRingMargin1Chunks 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

FieldDefaultWhat to set
InterestNearRadius30 mForward 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.
InterestFarRadius80 mUse the middle update rate between the near and far distances.
InterestMidDivisor4Forward 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).
InterestFarDivisor12Forward 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, InterestBackgroundTiersOverride offGive 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.
InterpolationDelaySeconds0.05Render 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.
AdaptiveInterpolationDelaytrueSize 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.
InterpolationJitterPercentile95The percentile of packet lateness the adaptive delay covers, from 50 to 100. A higher value buffers more and extrapolates less often.
MaxStreamLagSeconds0.2The most the measured lateness may add to the render delay.
SlowUpdateMaxDelaySeconds0.5Draw 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.
InputLeadMarginSeconds0.033Add this much, rounded up to whole ticks, to half the measured round-trip time when scheduling input.
InputLeadTargetSeconds0.05Keep client input this far ahead, rounded up to whole ticks, when it arrives at the worker.
InputLeadMaxAdjustSeconds0.5Limit 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.

FieldDefaultWhat to set
ReconnectFirstDelaySeconds1 sWait this long after a drop before the first reconnection attempt.
ReconnectBackoffFactor2Make each later attempt wait this many times longer than the one before. Use 1 for a fixed delay.
ReconnectMaxDelaySeconds2 sNever wait longer than this between two attempts. With the defaults, the client retries after 1 s, then every 2 s.
ReconnectGiveUpSeconds0Stop 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.
ClientDisconnectTimeoutSeconds8 sTreat 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.
ClientPingIntervalSeconds0.5 sSend the transport's keep-alive ping this often. Keep it well below the disconnect timeout.
ClientStallSeconds2 sRaise 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.

OptionUsed byWhat it does
-nebula-role client|worker|gateway|orchestratorall rolesSelect 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 rolesOverride GameScene.
-nebula-gateway <address:port>client, worker, orchestratorSet the gateway address. A client connects immediately when you supply this option.
-nebula-connectclientConnect to the configured gateway at startup. NebulaTitleScreen stays hidden.
-nebula-name <name>clientSet the player's display name.
-nebula-botclientMark 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>clientPresent this OpenID Connect ID token to the gateway. See Authentication.
-nebula-worker-id <id>workerSet the worker ID. The orchestrator normally supplies it.
-nebula-worker-index <number>workerSet the worker index. The orchestrator normally supplies it.
-nebula-port <port>workerSet 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, orchestratorSet the address advertised to other processes. Use auto to select the first private IPv4 address.
-nebula-control-plane <url>worker, gatewayOverride ControlPlaneUrl.
-nebula-gateway-id <id>gatewaySet the gateway's persistent ID (default gw1). Give every gateway of a mesh a distinct one.
-nebula-web true|falsegatewayOverride WebClients.
-nebula-web-port <port>, -nebula-webrtc-port <port>gatewayOverride WebPort and WebRtcPort.
-nebula-web-root <folder>gatewayServe 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|acmegateway, orchestratorServe 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, orchestratorChoose where the certificate and account key are kept, which ACME server issues the certificate, and the contact address it registers.
-nebula-token <secret>server rolesOverride 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|falsegateway, orchestratorOverride 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, orchestratorOverride 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, orchestratorOverride 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|falsegateway, orchestratorOverride 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, orchestratorChoose 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>clientOverride ClientEncryption and GatewayFingerprint: encrypt the link to the gateway, and accept only the certificate with this fingerprint.
-nebula-content-version <number>Unity client, gatewaySet 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 gatewaySet the oldest accepted game content version. 0 requires an exact match with GameContentVersion.
-nebula-single-session true|falsegateway, worker, orchestratorOverride SingleSessionPerPlayer. The orchestrator passes it to the gateway and workers it starts.
-nebula-database <url>orchestratorOverride DatabaseUrl. The standalone orchestrator also reads NEBULA_DATABASE_URL.
-nebula-local-control-planeserver rolesUse the in-process control plane.
-nebula-persistence-mode auto|database|remote|local|memory|offworker, orchestratorOverride PersistenceMode.
-nebula-reset-persistenceorchestratorDelete every saved entity at startup.
-nebula-persistence-file <path>worker, orchestratorOverride PersistenceLocalFile.
-nebula-persistence-checkpoint <seconds>workerOverride PersistenceCheckpointSeconds.
-nebula-scope-idle-retire <seconds>orchestratorOverride ScopeIdleRetireSeconds. 0 turns scope retirement off.
-nebula-scope-retire-with-entities true|falseorchestratorOverride ScopeRetireWithEntities.
-nebula-workers <number>orchestratorSet the initial worker count.
-nebula-min-workers <number>, -nebula-max-workers <number>orchestratorOverride MinWorkers and MaxWorkers, the autoscaling band.
-nebula-autoscale true|falseorchestratorOverride AutoScale.
-nebula-idle-pool <seconds>orchestratorOverride IdlePoolSeconds.
-nebula-settings key=value,key=valueorchestratorAdd game-defined, mesh-wide settings to the control plane.
-nebula-dashboard-port <port>orchestratorSet the dashboard port.
-nebula-dashboard-bind <address|+>orchestratorBind the dashboard to one address. Use + to bind all interfaces.
-nebula-host process|hetzner|cloudorchestratorSelect where workers run.
-nebula-cloud-api <url>, -nebula-cloud-deployment-token <token>orchestratorWith -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|falseorchestratorOverride OrchestratorSpawnsGateway.
-nebula-worker-exe <path>orchestratorSelect the executable used to start workers and the gateway.
-nebula-build-dir <path>orchestratorServe worker build files from this directory at /build/.
-nebula-ghost-band <meters>workerOverride GhostBandMargin.
-nebula-hysteresis <meters>workerOverride HandoverHysteresis.
-nebula-tick-rate <hz>every roleOverride 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>workerOverride StateHistorySeconds, in ticks at the running rate. 0 turns state recording off. See Lag compensation.
-nebula-interest-radius <meters>gateway, workerOverride InterestRadius. See Interest management.
-nebula-interest-cell <meters>gateway, workerOverride InterestCellSize.
-nebula-gateway-extension <file>gatewayOverride GatewayExtension. The orchestrator forwards it to the gateway it launches. See Extend the gateway.
-nebula-gateway-extension-type <Namespace.Class>gatewayOverride GatewayExtensionType.
-nebula-gateway-extension-options key=value;key=valuegatewayOverride GatewayExtensionOptions.
-nebula-ext-<key> <value>gatewayOverride one extension option; read inside the extension with context.Option(key).
-nebula-reset falseorchestratorRestore the stored control plane instead of starting empty. The default resets this temporary registry state.
-nebula-verboseall rolesWrite 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.json
{
  "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
  }
}
KeyWhat it controls
nebulaRecords the CLI version that last wrote the file. nebula init updates it.
executableSets the base name of builds produced by NebulaBuild, such as Nebula.exe or Nebula.x86_64.
mesh.workersSets the default worker count for nebula start.
mesh.minWorkers, mesh.maxWorkersSet 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.idlePoolSecondsSets how long a retired worker stays parked in the idle pool. 0 uses the host's own answer.
mesh.dashboardPort, mesh.gatewayPortSet the ports used by a local mesh and by deployment firewalls.
mesh.databaseSelect where the local orchestrator keeps the control plane and saved entities. Leave it out for sqlite:Library/Nebula/nebula.db.
deploy.targetSelects the deployment target: hetzner or cloud (see Deploy to Nebula Cloud).
deploy.meshNameSets the label and name prefix used for cloud resources.
deploy.databaseSelects 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.workersSets the default worker count for nebula deploy.
deploy.workerType, deploy.orchestratorType, deploy.locationOverride 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 show

nebula 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.

On this page