Skip to content

Running Edge Nodes

An edge node pairs MistServer with Helmsman to connect your hardware to the FrameWorks control plane.

Terminal window
# Install the latest release
curl -sSfL https://github.com/Livepeer-FrameWorks/monorepo/releases/latest/download/install.sh | sh
# Verify
frameworks version

If you have a logged-in FrameWorks account, edge deploy handles the entire pipeline end-to-end via Bridge — private edge cluster creation, Foghorn assignment, enrollment token issuance, preflight, tuning, template generation, stack boot, and HTTPS verification:

Terminal window
# Mode A — logged-in tenant (Bridge auto-creates an edge cluster + token)
frameworks login
frameworks edge deploy --ssh ubuntu@edge-1 --email [email protected]
# Mode B — pre-existing enrollment token (no login required)
frameworks edge deploy --ssh ubuntu@edge-1 --enrollment-token enroll_xxx

When it finishes, edge deploy prints a result block (cluster, enrollment, stack, https, node, domain) and suggests edge status and edge doctor as next steps.

The rest of this page walks through the same workflow as individual commands when you need finer control.

Terminal window
frameworks edge preflight --domain stream.yourdomain.com

On Linux Docker targets, this checks:

  • Docker and Docker Compose installed
  • Ports 80/443 available for HTTPS
  • DNS resolves (compare to this server’s public IP)
  • Kernel parameters (sysctl) are sane
  • /dev/shm is mounted
  • File descriptor limits won’t choke under load

Native Linux and macOS deployments use the same command surface, but the preflight checks are OS-aware: Linux checks systemd/sysctls//dev/shm, while macOS checks launchd and skips Linux-only kernel checks.

Note: if you plan to use direct ingest or non-HTTP protocols, open the MistServer ports you need:

  • 1935/tcp (RTMP/E-RTMP ingest)
  • 8889/udp (SRT ingest)
  • 5554/tcp (RTSP)
  • 18203/udp (WebRTC)
  • 4200/tcp (DTSC replication)
  • 8080/tcp (MistServer HTTP)
  • 4242/tcp (Mist controller; keep internal)
Terminal window
# Preview what will change
frameworks edge tune
# Apply the changes (requires root)
sudo frameworks edge tune --write

This configures:

  • TCP buffer sizes and backlog tuning
  • Local port range for high connection counts
  • File descriptor limits
Terminal window
frameworks edge init --dir /opt/frameworks-edge \
--enrollment-token enroll_xxx \

When using --enrollment-token, the CLI sends the token to Bridge’s public bootstrapEdge mutation. Bridge resolves the cluster, finds its Foghorn, and proxies the pre-registration. The response carries the assigned domain, node ID, cluster slug, the runtime Foghorn address, and the internal CA bundle for gRPC trust bootstrap. The operator only ever needs the token and the SSH target; Foghorn discovery happens server-side.

If you already have a domain and don’t need auto-assignment, use --domain instead. This manual path still needs a reachable Foghorn address from the active CLI context or --foghorn-addr; the Bridge token path is the normal self-hosted flow because it resolves Foghorn server-side.

Terminal window
frameworks edge init --dir /opt/frameworks-edge \
--domain stream.yourdomain.com \

This creates:

  • Edge environment files - Configuration, write-once enrollment token, and the MistServer API secret
  • Edge compose file - The single frameworks-edge container (MistServer, Helmsman, and Caddy run inside it under s6)

The bootstrap Caddy config is baked into the edge image; production TLS and viewer routing are activated from ConfigSeed after enrollment. (Native mode renders the bootstrap Caddyfile on the host instead.)

The edge environment file contains the required settings:

Terminal window
NODE_ID=edge-us-sea-1
EDGE_PUBLIC_URL=https://stream.yourdomain.com/view
FOGHORN_CONTROL_ADDR=foghorn.<media-cluster>.example.com:18029
GRPC_TLS_CA_PATH=
EDGE_DOMAIN=stream.yourdomain.com
DEPLOY_MODE=container

The enrollment token lives in its own file, .edge-enroll.env, so rotating or re-issuing a token never changes .edge.env (which would restart an enrolled node):

Terminal window
# In .edge-enroll.env
EDGE_ENROLLMENT_TOKEN=your-enrollment-token

NODE_ID must be stable and unique per node. EDGE_PUBLIC_URL should include the /view path. FOGHORN_CONTROL_ADDR is the Foghorn gRPC endpoint Helmsman needs at boot — the HTTP balancer base, TLS bundle, telemetry, and SiteConfig arrive over the live gRPC ConfigSeed stream once Helmsman connects.

When using --enrollment-token with edge init, the CLI populates NODE_ID, EDGE_DOMAIN, and FOGHORN_CONTROL_ADDR from the PreRegisterEdge response. Managed clusters use Foghorn’s external gRPC listener, for example foghorn.<media-cluster>.example.com:18029, and validate it with the public ACME certificate. GRPC_TLS_CA_PATH is only set for internal-CA Foghorn addresses such as foghorn.internal:18019.

Optional Helmsman overrides (add only if needed, in .edge.env):

Terminal window
HELMSMAN_CAP_INGEST=true
HELMSMAN_CAP_EDGE=true
HELMSMAN_CAP_STORAGE=true
HELMSMAN_CAP_PROCESSING=true
HELMSMAN_MAX_TRANSCODES=0
# Hot-storage location. Container mode already persists /data/storage on the
# edge_storage named volume — do NOT override it there, or DVR/clip data
# lands outside the volume. Native mode defaults to
# /var/lib/frameworks/edge-storage.
#HELMSMAN_STORAGE_LOCAL_PATH=/var/lib/frameworks/edge-storage
Terminal window
frameworks edge enroll --dir /opt/frameworks-edge

In container mode, this starts the single frameworks-edge container and enrolls the node if EDGE_ENROLLMENT_TOKEN is set in .edge-enroll.env.

Check status:

Terminal window
frameworks edge status --dir /opt/frameworks-edge

You should see:

  • edge - Up (healthy) — the single container running MistServer, Helmsman, and Caddy under s6 (native mode lists the three services individually)
  • HTTPS - /health responds on the configured edge domain

The media server. Handles:

  • RTMP/E-RTMP/SRT/WHIP ingest
  • HLS, LL-HLS, DASH, WebRTC/WHEP, MP4/WebM, WebSocket, and direct playback protocols when exposed
  • Recording (if enabled)

Web UI: http://localhost:4242 (internal, not exposed by default). If you proxy it, add auth/IP restrictions so you don’t expose the controller API.

The sidecar. Does:

  • Forwards MistServer triggers to Foghorn for validation/routing
  • Collects client and node metrics for Foghorn
  • Reports node capacity and storage details

Health check: Helmsman’s HTTP API binds loopback (it carries local-only management endpoints). On Linux — native or container mode with host networking — curl http://localhost:18007/health works from the host; on macOS container mode use docker exec frameworks-edge curl -s http://localhost:18007/health (the port is not published).

Reverse proxy. Provides:

  • Bootstrap HTTPS during first start
  • Viewer routing after Helmsman receives and applies ConfigSeed
  • Terminates TLS

The generated Caddyfile starts in bootstrap mode with internal TLS and a 503 response. Once Helmsman connects, Foghorn sends SiteConfig and TLS material over ConfigSeed, and Helmsman rewrites/reloads Caddy for live viewer traffic.

Terminal window
# All services (caddy/mistserver/helmsman run inside the single edge
# container; their lines are interleaved on its stdout)
frameworks edge logs --dir /opt/frameworks-edge
# Service-name arguments map to the same edge container
frameworks edge logs helmsman --dir /opt/frameworks-edge --follow
# Or use docker directly
docker compose -f docker-compose.edge.yml logs -f edge

“DNS does not resolve to this host”

Your DNS record doesn’t point to this server’s public IP.

Terminal window
dig +short stream.yourdomain.com
curl ifconfig.me

“Port 443 in use”

Terminal window
sudo lsof -i :443
sudo systemctl stop nginx

“Certificate failed”

In token-provisioned deployments, public TLS material is delivered by ConfigSeed after Helmsman enrolls. If the node is still serving the bootstrap internal certificate, check Helmsman enrollment and ConfigSeed logs first.

Terminal window
frameworks edge cert --dir /opt/frameworks-edge
frameworks edge cert --dir /opt/frameworks-edge --reload

“Helmsman can’t reach Foghorn”

Network issue or firewall blocking outbound gRPC. The dial target is whatever FOGHORN_CONTROL_ADDR is set to in .edge.env; check the helmsman log for the exact failure:

Terminal window
frameworks edge logs helmsman --tail 100
frameworks edge status --dir /opt/frameworks-edge

Your edge node is running. Next: Connect to the network.