Skip to content

Bays & the Docking Protocol

Bays are processes that use the docking protocol instead of binding to a port. Multiple client WebSocket connections are multiplexed over a single Unix socket between mothership and the bay. Ideal for:

  • Real-time apps (chat, notifications, Turbo Streams)
  • Reducing connection overhead
  • Processes that don’t need their own HTTP server
[[bays.websocket]]
name = "orbitcast"
command = "./orbitcast"
routes = [{ bind = "ws", pattern = "/cable" }]
config = { database_url = "postgres://localhost/myapp", turbo_streams = "true", turbo_streams_secret = "$TURBO_SECRET" }
Field Type Default Description
name string required Unique identifier (ASCII only, no spaces)
command string required Command to execute
args string[] [] Command arguments
cwd string inherited Working directory for process launch
routes array [] WebSocket routes
depends_on string[] [] Ships/bays to wait for
env table {} Environment variables
config table {} Config passed via the docking protocol
critical bool true Crash kills the entire fleet
tags string[] [] Tags for filtering

Unlike ship env, the config table is delivered to the bay through the docking protocol itself (in the Moored message), so the bay receives structured configuration after it connects. Values support $ENV expansion.

Bays communicate with mothership over a Unix socket using a binary protocol:

Message Direction Purpose
Dock Bay → Mothership Bay ready, sends version
Moored Mothership → Bay Docking confirmed, sends config
Boarding Mothership → Bay New WebSocket client connected
Disembark Mothership → Bay Client disconnected
Cargo Bidirectional WebSocket data payload

Mothership provides these environment variables to every bay process:

Variable Meaning
MS_PID Mothership process ID
MS_SHIP Bay name
MS_SOCKET_DIR Socket directory
MS_SOCKET_PATH Full socket path
MS_BAY_TYPE Bay type (e.g. websocket)

Ship WebSocket proxying works fine for both TCP and Unix-socket backends — a bay is not required to serve WebSockets. Reach for a bay when you want docking-protocol multiplexing (one socket, many clients) rather than direct backend proxying, or when the process has no HTTP server of its own.