What you can self-host
Drone agent
The agent that runs on your SBC. Installs with one command and pairs
over the LAN by default.
Mission Control + Convex
The web GCS plus a self-hosted Convex backend for auth, fleet data,
and cloud commands.
MQTT bridge
Mosquitto plus the bridge that forwards live telemetry to Convex.
Video relay
RTSP-to-WebSocket video so a browser can play the drone’s stream.
Local-first by default
You do not need any cloud infrastructure to fly. The default path is local, over your LAN:- The drone-to-ground data link is the WFB radio, which binds on first boot with no manual setup.
- Mission Control reaches an agent directly by hostname or IP. Paste the agent’s address into the Add-a-Node card and the GCS pairs with it over the LAN. The pairing key is stored in the browser. No Convex round-trip is involved.
server.mode to local and nothing reaches out to a backend.
On the LAN, Mission Control connects straight to the agent over plain
HTTP. Cloud relay only activates when the GCS is served over HTTPS. See
configuration for the agent’s
server block.When you want the cloud relay
The cloud relay is the opt-in path for reaching a drone across networks (remote sites, mobile data, anywhere the GCS and the agent are not on the same LAN). It is additive: each layer is optional and you only run what you need.| Layer | What it adds | Update rate |
|---|---|---|
| Convex backend | Auth, fleet management, cloud commands | 5s poll baseline |
| MQTT relay | Real-time telemetry through Mosquitto | 2Hz and up |
| Video relay | Live video in the browser | streaming |
ados/{deviceId}/status, ados/{deviceId}/telemetry) and forwards
them to Convex so the GCS can display them. The video relay remuxes the
agent’s RTSP stream into fragmented MP4 over WebSocket for browser
playback, with no transcoding.
To put an agent on a self-hosted backend, set its server.mode to
self_hosted and point server.self_hosted.url at your Convex site
origin. The agent heartbeat and pairing both target that origin.
Two routes to deploy
All-in-one stack
One Docker Compose at
tools/selfhost/ brings up the Convex backend
and dashboard, the web GCS, Mosquitto, the MQTT bridge, and the
video relay on a single host. Start here if you want everything.Per-tool compose
Run just the layers you need. The MQTT bridge and the video relay
each ship their own compose file under
tools/mqtt-bridge/deploy/ and tools/video-relay/deploy/, so you
can add a relay layer behind an existing Convex deployment.Convex has two origins
Whichever route you take, the one wiring detail that trips people up is that a self-hosted Convex backend exposes two origins that are not interchangeable::3210is the client API. The GCS browser bundle talks to this (NEXT_PUBLIC_CONVEX_URL), andconvex deploypushes functions here.:3211is the site and HTTP-actions origin. The drone agent heartbeat and the MQTT bridge POST here (CONVEX_URLresolves to${CONVEX_URL}/agent/status). The agent’sserver.self_hosted.urlandpairing.convex_urlpoint here too.
Resource footprint
A small deployment of one to five drones runs comfortably on a single 4-core / 8 GB Linux box that hosts Convex, Mosquitto, the bridge, and the relay together. The Convex backend wants the most headroom (its SQLite store grows with your data); the MQTT layers are light; the video relay scales with the number of concurrent streams (roughly one CPU core per stream).Where to go next
Drone agent
Install the agent and point it at your backend.
Mission Control + Convex
Stand up the GCS and the backend it talks to.
All-in-one stack
The one-host Docker Compose runbook.
Troubleshooting and ports
The port table and the common failure modes.