Nimbusv1.0.0

Bridge Plugin

Velocity proxy plugin that connects to the Nimbus cloud system with in-game commands, player routing, permission integration, and proxy sync.

The Nimbus Bridge is a Velocity proxy plugin that connects the proxy to the Nimbus cloud system. It provides in-game cloud management commands, automatic player routing, permission integration, and proxy synchronization features.

Installation

The bridge is automatically deployed to every proxy service at runtime. On each service prepare, ServiceFactory.resolveModulePlugins() copies nimbus-bridge.jar into the proxy's plugins/ directory with REPLACE_EXISTING — so deletions self-heal on next start and updates roll out automatically. Templates are user-owned; the bridge JAR is never written into templates/global_proxy/plugins/.

If a proxy service's plugins/nimbus-bridge.jar is missing, it's redeployed on the next service start.

Configuration

The bridge reads its API connection from plugins/nimbus-bridge/bridge.json:

JSON
{
  "api_url": "http://127.0.0.1:8080",
  "token": "your-api-token"
}

This file is auto-generated by Nimbus Core during deployment. The values come from your config/nimbus.toml API configuration.

Alternatively, the bridge auto-discovers its connection from JVM system properties and environment variables (set by Nimbus when launching the proxy process):

SourceKeyDescription
Env varNIMBUS_API_TOKENBearer token (preferred, hidden from ps)
System propertynimbus.api.urlAPI base URL
System propertynimbus.api.tokenBearer token (fallback)

The bridge checks for the environment variable first, then falls back to the system property. If either is set, bridge.json is not read.

Commands

All commands require the base permission nimbus.cloud. The /cloud command is also available as /nimbus.

Dynamic command discovery — most /cloud subcommands are not implemented in the Bridge itself. On startup (and on controller reconnect), the Bridge calls GET /api/commands to fetch all Controller commands that have a non-empty permission field. Each discovered command is forwarded automatically via POST /api/commands/{name}/execute. This means new Controller commands appear in-game without Bridge updates, and the response formatting is handled by the Controller's CommandOutput interface.

Only maintenance (Velocity-local login gate) and events (local WebSocket subscriber list) are implemented directly in the Bridge.

Service management

CommandPermissionDescription
/cloud list [group]nimbus.cloud.listList running services, optionally filtered by group
/cloud info <service>nimbus.cloud.infoShow detailed info for a service
/cloud start <group>nimbus.cloud.startStart a new instance of a group
/cloud stop <service>nimbus.cloud.stopStop a running service
/cloud restart <service>nimbus.cloud.restartRestart a service
/cloud exec <service> <command>nimbus.cloud.execExecute a console command on a service

Player management

CommandPermissionDescription
/cloud playersnimbus.cloud.playersList all online players and their current servers
/cloud send <player> <service>nimbus.cloud.sendTransfer a player to another service
/cloud broadcast [--group <g>] <msg>nimbus.cloud.broadcastBroadcast a message to all players or a specific group

Network management

CommandPermissionDescription
/cloud statusnimbus.cloud.statusNetwork overview (services, players, memory)
/cloud groupsnimbus.cloud.groupsList all configured groups
/cloud setstate <service> <state>nimbus.cloud.setstateSet a service's custom state
/cloud reloadnimbus.cloud.reloadReload Nimbus configuration

Permission management

CommandPermissionDescription
/cloud perms group listnimbus.cloud.permsList permission groups
/cloud perms group info <group>nimbus.cloud.permsShow group details
/cloud perms group create <name>nimbus.cloud.permsCreate a permission group
/cloud perms group delete <name>nimbus.cloud.permsDelete a permission group
/cloud perms group addperm <group> <perm>nimbus.cloud.permsAdd permission to group
/cloud perms group removeperm <group> <perm>nimbus.cloud.permsRemove permission from group
/cloud perms group setdefault <group> <true/false>nimbus.cloud.permsSet as default group
/cloud perms group addparent <group> <parent>nimbus.cloud.permsAdd parent (inheritance)
/cloud perms group removeparent <group> <parent>nimbus.cloud.permsRemove parent
/cloud perms group setprefix <group> <prefix>nimbus.cloud.permsSet group prefix
/cloud perms group setsuffix <group> <suffix>nimbus.cloud.permsSet group suffix
/cloud perms group setpriority <group> <n>nimbus.cloud.permsSet group priority
/cloud perms user listnimbus.cloud.permsList users with groups
/cloud perms user info <player>nimbus.cloud.permsShow player's groups
/cloud perms user addgroup <player> <group>nimbus.cloud.permsAdd player to group
/cloud perms user removegroup <player> <group>nimbus.cloud.permsRemove player from group

Maintenance management

CommandPermissionDescription
/cloud maintenance statusnimbus.cloud.maintenanceShow maintenance status (global + groups)
/cloud maintenance onnimbus.cloud.maintenanceEnable global maintenance
/cloud maintenance offnimbus.cloud.maintenanceDisable global maintenance
/cloud maintenance on <group>nimbus.cloud.maintenanceEnable maintenance for a group
/cloud maintenance off <group>nimbus.cloud.maintenanceDisable maintenance for a group
/cloud maintenance listnimbus.cloud.maintenanceShow whitelisted players
/cloud maintenance add <player>nimbus.cloud.maintenanceAdd player to maintenance whitelist
/cloud maintenance remove <player>nimbus.cloud.maintenanceRemove player from whitelist

Hub command

CommandAliasesDescription
/hub/lobby, /lSend the player to a lobby server

The hub command finds the lobby server with the fewest players (least-players load balancing) and connects the player. If the player is already on any lobby, they're told they're already there.

Connection handling

The bridge manages player connections automatically:

Initial connection

When a player joins the proxy, the bridge detects the connection type via Velocity's internal ConnectionType (set during the FML handshake). Connection types are:

TypeDescription
VANILLAStandard Minecraft client (including Fabric+Sodium — Fabric appears as vanilla)
LEGACY_FORGEForge client using the legacy FML handshake (1.12.2 and older)
MODERN_FORGEForge/NeoForge client using the modern FML handshake (1.13+)

Modded clients (LEGACY_FORGE or MODERN_FORGE) are routed using mod list matching:

  1. Filter modded groups by protocol version (client protocol must match the group's MC version)
  2. Filter by connection type compatibility (LEGACY_FORGE only matches Forge; MODERN_FORGE matches Forge or NeoForge)
  3. Read the client's mod list via player.getModInfo() and compute a match score against each group's server mod list: |clientMods ∩ serverMods| / |serverMods|
  4. The group with the highest score (minimum 0.5) wins — the client is sent to the least-loaded instance of that group
  5. If no group scores above 0.5 but exactly one group matches protocol + type, route there (fallback for older Forge versions that don't report mod lists)
  6. If no match is found, fall back to lobby

Vanilla clients are routed to the lobby with the fewest players. If no suitable server is available, the player is disconnected with an error message.

The modded groups cache (including mod IDs from ModScanner) is fetched from GET /api/groups on startup and refreshed on controller reconnect.

Kicked from server

When a modded client is kicked from a modded server:

  1. The bridge tries to find an alternate modded group at the same protocol version
  2. If an alternate exists, the client is redirected there
  3. If no alternate is found, the client is disconnected (not sent to a vanilla lobby where they'd get kicked again)

When a vanilla client is kicked from a non-lobby server:

  1. The bridge attempts to redirect them to the lobby with the fewest players
  2. If a lobby is available, the player is sent there with a message
  3. If no lobby is available, the player is disconnected

When kicked from a lobby server (e.g. during a restart), the bridge redirects the player to a different lobby. If no other lobby is available, the player is disconnected with the kick reason.

Permission integration

The bridge integrates with Nimbus's permission system by providing a custom Velocity PermissionProvider:

  1. On login -- Fetches the player's permissions from the Nimbus API
  2. On permission check -- Resolves permissions including wildcard matching
  3. On disconnect -- Invalidates the permission cache
  4. On permission update -- WebSocket events trigger real-time cache refresh

Permission changes (via /cloud perms or the API) are pushed to all proxies instantly. No restart or rejoin required.

Proxy synchronization

The bridge handles real-time synchronization of:

Tab list

  • Applies header/footer from config/modules/syncproxy/tablist.toml to all players
  • Formats player display names using the configured player_format
  • Supports per-player overrides via the SDK's Nimbus.setTabName()
  • Refreshes periodically (default: every 5 seconds)
  • Placeholders: {player}, {prefix}, {suffix}, {server}, {group}, {online}, {max}

MOTD

  • Intercepts proxy ping events and applies the configured MOTD
  • Supports MiniMessage formatting
  • Configurable max_players and player_count_offset
  • Placeholders: {online}, {max}

Chat format

  • Formats chat messages using the configured format (when enabled = true)
  • Supports prefix/suffix from permission groups
  • Supports MiniMessage and legacy & color codes

Maintenance mode

  • Global maintenance: Overrides the MOTD with a maintenance message, sets the version protocol to show a red "x" in the server list, and disconnects non-whitelisted players on join
  • Group maintenance: Blocks players from connecting to servers of a specific group (e.g. during template updates), redirects them back to the lobby
  • Players with nimbus.maintenance.bypass permission or on the whitelist can bypass both
  • Configuration is part of config/modules/syncproxy/motd.toml under the [maintenance] section

Real-time updates

All proxy sync settings are updated in real-time via WebSocket events:

  • TABLIST_UPDATED -- Tab config changed
  • MOTD_UPDATED -- MOTD config changed
  • CHAT_FORMAT_UPDATED -- Chat format changed
  • PLAYER_TAB_UPDATED -- Per-player tab override changed
  • MAINTENANCE_ENABLED -- Maintenance enabled (global or group)
  • MAINTENANCE_DISABLED -- Maintenance disabled (global or group)
  • PERMISSION_GROUP_UPDATED -- Permission group changed (re-fetch display info)
  • PLAYER_PERMISSIONS_UPDATED -- Player permissions changed

Architecture

Directory Structure
NimbusBridgePlugin (entry point)
├── CloudCommand          Dynamic forwarding via /api/commands; maintenance + events are Bridge-local
├── HubCommand            Uses ProxyServer to find lobby
├── ConnectionListener    Handles initial connect + kick fallback + maintenance blocking
├── MaintenanceHandler    Proxy-side maintenance state cache (synced via API + events)
├── PermissionListener    Injects NimbusPermissionProvider
├── ProxySyncListener     Tab list + MOTD + chat sync + maintenance MOTD override
└── Shared clients:
    ├── NimbusApiClient   HTTP client (bridge-specific, returns Result)
    ├── NimbusClient      SDK HTTP client (shared with CloudCommand)
    └── NimbusEventStream WebSocket event stream (shared across features)

The bridge uses a single shared NimbusEventStream connection for all features (permissions, proxy sync, cloud command). This minimizes WebSocket connections to the Nimbus API.

Next steps