mothership-0.0.4 has been yanked.
Mothership
Process supervisor with HTTP exposure. Launches your fleet, routes traffic, runs WASM plugins.
Features
- Fleet Management: Launch and monitor processes with dependency ordering
- Named Binds: Multiple listeners (http, https, ws) routed to ships
- Health Checks: HTTP-based monitoring with circuit breakers
- Crash Loop Protection: Exponential backoff for failing ships
- TUI Dashboard: Real-time fleet status with logs (
--tui) - WASM Plugins: Request/response processing with sandboxing
- Prometheus Metrics: Ship status, restarts, request counts at
/metrics - Tag Filtering:
--only webor--except workersfor selective launching - Base Templates: Reduce config duplication
- Graceful Shutdown: Dependency-aware termination
Installation
Or from source:
Quick Start
# Initialize a new manifest
# Validate configuration
# Run the fleet
# Run with TUI dashboard
Configuration
Create ship-manifest.toml:
# Global configuration
[]
= 9090
# Named binds - external listeners
[]
= "0.0.0.0:80"
= "0.0.0.0:443"
= "0.0.0.0:8080"
# Web ships
[[]]
= "app"
= "ruby"
= ["app.rb"]
= "tcp://127.0.0.1:3000"
= "/health"
= [
{ = "http", = "/.*" },
{ = "https", = "/.*" },
]
[[]]
= "cable"
= "anycable-go"
= "tcp://127.0.0.1:8081"
= [
{ = "ws", = "/cable" },
]
# Background workers
[[]]
= "sidekiq"
= "bundle"
= ["exec", "sidekiq"]
= false # Won't kill fleet on crash
# One-shot jobs
[[]]
= "migrate"
= "rails"
= ["db:migrate"]
= true
[[]]
= "main-app"
= ["migrate"] # Wait for migration
# WASM modules (optional)
[[]]
= "rate_limiter"
= "./modules/rate_limiter.wasm"
= ["/api/.*"]
= "request"
Ship Configuration
| Field | Type | Default | Description |
|---|---|---|---|
name |
string | required | Unique ship identifier |
command |
string | required | Command to execute |
args |
string[] | [] |
Command arguments |
bind |
string | - | Internal bind address (tcp://host:port or unix:///path) |
healthcheck |
string | - | Health check endpoint path |
routes |
array | [] |
HTTP routes (see below) |
depends_on |
string[] | [] |
Ships to wait for before starting |
env |
table | {} |
Environment variables |
critical |
bool | true |
Crash kills entire fleet |
oneshot |
bool | false |
Run once and exit |
tags |
string[] | [] |
Tags for filtering (--only, --except) |
comment |
string | - | Description (for documentation) |
Route Configuration
Routes map mothership binds to ships. Three formats supported:
# Object format (explicit)
= [
{ = "http", = "/api/.*" },
{ = "ws", = "/cable" },
]
# Shorthand format
= ["http:/api/.*", "ws:/cable"]
# Legacy format (defaults to "http" bind)
= ["/api/.*", "/health"]
Bind Formats
# TCP with explicit prefix
= "tcp://127.0.0.1:3000"
# TCP without prefix
= "0.0.0.0:8080"
# Port only (defaults to 127.0.0.1)
= "3000"
# Unix socket
= "unix:///tmp/app.sock"
Commands
# Run fleet (default)
# Run with TUI
# Filter by tags
# Validate manifest
# Initialize new manifest
Base Templates
Reduce duplication with base templates:
[]
= { = "production" }
= true
= ["ruby"]
[]
= "request"
= ["security"]
# Ships inherit from base.ship
[[]]
= "app"
= "ruby"
= ["web"] # Combined: ["ruby", "web"]
# Inherits: env, critical from base
TUI Dashboard
The TUI shows real-time fleet status:
- Overview Tab: Ship status, group, PID, health, routes
- Logs Tab: Per-ship stdout/stderr with scroll
- Modules Tab: WASM module status
Controls:
Tab- Switch tabs↑/↓- Navigate shipsPgUp/PgDn- Scroll logsq- Quit
WASM Modules
Modules process requests/responses at the proxy layer:
[[]]
= "auth"
= "./modules/auth.wasm"
= ["/admin/.*"]
= "request" # or "response"
[[]]
= "cache"
= "./modules/cache.wasm"
= ["/api/.*"]
= "response"
= { = "3600" }
Modules can:
- Block requests (return custom status/body)
- Modify request path/headers
- Modify response headers
Environment Variables
Ships inherit all environment variables from the mothership process. Pass secrets at runtime:
MASTER_KEY=secret DATABASE_URL=postgres://...
Ship-specific env vars override inherited values:
[[]]
= "app"
= "ruby"
= { = "production" } # adds to inherited env
Shell expansion is supported:
= {
DATABASE_URL = "${DATABASE_URL}",
= "${git rev-parse HEAD}",
}
Metrics
Enable Prometheus metrics:
[]
= 9090
Scrape http://127.0.0.1:9090/metrics:
mothership_ship_status{ship="app",group="web"} 1
mothership_ship_healthy{ship="app",group="web"} 1
mothership_ship_restarts_total{ship="app",group="web"} 0
mothership_requests_total{route="/api"} 1234
mothership_fleet_ships_total 3
Also serves /health for liveness probes.
License
MIT