Universe requires two open ports per node — one for Hazelcast cluster communication and one for the Ktor REST API — plus a dynamic range of ports for the instances it manages. Understanding how ports are allocated and how nodes reach each other is essential for multi-node and cross-datacenter deployments.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/universeclouddev/Universe/llms.txt
Use this file to discover all available pages before exploring further.
Default Ports
| Service | Default Port | Configurable via |
|---|---|---|
| Hazelcast cluster bus | 6000 | port in config.json |
| Ktor REST API | 7000 | apiPort in config.json |
| Instance port range | 25565 – 25570 (example) | availablePorts in each configuration/*.json |
./config.json on every node:
Port Allocation Algorithm
When Universe starts an instance it must assign a port from the range defined in the instance’s configuration. ThePortAllocator checks three sources in order before assigning any port to ensure there are no conflicts, even when multiple configurations share overlapping ranges or when external services already occupy ports on the machine.
Local in-memory allocations
A
ConcurrentHashMap tracks every port this JVM has already assigned. If a port is in that set it is skipped immediately, without any network or OS call.Cluster-wide active instances via Hazelcast
The allocator queries the Hazelcast
IMap for all instances whose state is ONLINE or CREATING across every node in the cluster, then excludes their allocatedPort values. This prevents two Wrapper nodes from assigning the same port to different instances even if they share a port range.OS-level bind and connect probe
For each remaining candidate port the allocator attempts two checks:
ServerSocketbind — if the bind fails, something else owns the port.- TCP connect probe (
localhost:port, 100 ms timeout) — if the connection succeeds, a service is already listening even if the bind appeared to succeed (e.g., due to socket reuse options).
release(port) removes it from the in-memory set so the port can be reused by a future instance.
Hazelcast Cluster Formation
Master and Wrapper nodes form a Hazelcast cluster over TCP. Every node needs to know the Master’s Hazelcast address so it can join the cluster on startup.masterAddress can be set to the service name (universe-master). On bare-metal or VM deployments, use the Master’s IP address. Wrapper nodes do not need a publicly reachable IP themselves — they initiate the outbound connection to the Master.
Cross-Node Connectivity
Instances advertise ahostAddress that other services (e.g., the Velocity proxy plugin) use to connect. The address must be reachable from whatever client will be connecting, which may differ from the local machine’s loopback or LAN address.
Default: hostAddress
Set
hostAddress in ./configuration/<name>.json to the IP that remote clients should use. Works for single-datacenter setups where all nodes share a LAN.Tailscale Mesh
Install the Tailscale extension and use the
%TAILSCALE_IP% variable. Universe replaces it with the node’s Tailscale IP at instance creation time, giving each instance a stable encrypted-mesh address.Kubernetes Headless Services
The
runtime-k8s extension exposes %SERVICE_DNS% which resolves to universe-<id>.<namespace>.svc.cluster.local. Use this for in-cluster pod-to-pod connectivity.Public IP / NodePort
For Kubernetes nodes exposed outside the cluster, set
hostAddress to the node’s public IP and use a NodePort service so external clients can reach allocated ports.Firewall Requirements
Open the following ports depending on the role of each machine:Master node
Master node
| Port | Protocol | Direction | Purpose |
|---|---|---|---|
6000 (or custom port) | TCP | Inbound from Wrappers | Hazelcast cluster bus |
7000 (or custom apiPort) | TCP | Inbound from clients / Wrappers | Ktor REST API |
Wrapper nodes
Wrapper nodes
| Port | Protocol | Direction | Purpose |
|---|---|---|---|
6000 outbound to Master | TCP | Outbound | Join Hazelcast cluster |
Instance range (e.g., 25565–25570) | TCP | Inbound from proxy/clients | Instance ports |
Instance ports
Instance ports
The port range used by instances (defined per configuration in
availablePorts) must be open inbound on the Wrapper node that runs those instances. If the Velocity or BungeeCord plugin connects to instances, the proxy machines need outbound access to those ports on every Wrapper.Proxy Auto-Connect Strategies
The Universe Velocity and BungeeCord plugins poll the Master REST API for active instances and register them as backend servers automatically. When a player joins the proxy, the plugin selects a backend server using one of three strategies.| Strategy | Behaviour |
|---|---|
LEAST_POPULATED | Send the player to the instance with the fewest current players — distributes load evenly |
MOST_POPULATED | Send the player to the instance with the most current players — useful for minigame lobbies that should fill before opening a new one |
RANDOM | Pick a random instance from the available pool |
plugins/Universe/config.yml on the proxy server:
auto-connect: false to disable automatic player routing and handle server selection in your own plugin code via the UniverseAPI.