Onboard an OpenTelemetry Collector via OpAMP
This is the Standards onboarding path for the OpenTelemetry Collector:
two upstream OTel binaries run on the host — opampsupervisor (handles the
OpAMP connection to LinkMesh and writes the collector config it receives)
and otelcol-contrib (the data plane the supervisor manages). No LinkMesh
agent or other LinkMesh-specific code on the host.
Prerequisites
- A reachable LinkMesh server (you know its public base URL, e.g.
https://linkmesh.example.com). - A Linux host where you can install binaries and edit a config file.
- The OpAMP endpoint reachable from the host over WebSocket — same host/port as the web UI, path
/v1/opamp.
Option A — One-line install script
LinkMesh ships an installer that downloads both binaries, writes the supervisor config, and starts the systemd unit. This is what the Add Collector → OpAMP wizard hands you in the UI.
-
Get an enrollment token. UI: Collectors → + Add Collector → OpAMP, or Settings → Enrollment Tokens → Create Token. Tokens are single-use and expire — mint a fresh one if it lapses.
-
Run the installer on the host:
Terminal window curl -fsSL https://linkmesh.example.com/api/v1/downloads/install-opamp.sh | \sudo sh -s -- --token <YOUR_ENROLLMENT_TOKEN>The script fetches
otelcol-contribandopampsupervisorfrom upstream OTel releases (or from the LinkMesh mirror if your server has staged them for air-gapped use), writes/etc/otelcol-supervisor/supervisor.yaml, installsopamp-supervisor.service, and starts it. -
Verify in the LinkMesh UI — Collectors shows the host with management mode OpAMP, status Connected within ~30 s.
That’s the whole path for most operators. The manual install below is for hosts where you want explicit control over each step.
Option B — Manual install
-
Install both binaries. Upstream OTel publishes them under separate release tags — collector here, supervisor under
cmd/opampsupervisor:Terminal window OTEL_VERSION=0.153.0SUPERVISOR_VERSION=0.135.0ARCH=amd64 # or arm64# otelcol-contrib (tarball)curl -fsSL \"https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v${OTEL_VERSION}/otelcol-contrib_${OTEL_VERSION}_linux_${ARCH}.tar.gz" \| sudo tar -xz -C /usr/local/bin otelcol-contrib# opampsupervisor (raw binary, no tarball)sudo curl -fsSL -o /usr/local/bin/opampsupervisor \"https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/cmd%2Fopampsupervisor%2Fv${SUPERVISOR_VERSION}/opampsupervisor_${SUPERVISOR_VERSION}_linux_${ARCH}"sudo chmod 755 /usr/local/bin/opampsupervisorsudo mkdir -p /etc/otelcol-supervisor /var/lib/otelcol-supervisor -
Get an enrollment token the same way as Option A step 1.
-
Write
/etc/otelcol-supervisor/supervisor.yaml:server:endpoint: "wss://linkmesh.example.com/v1/opamp"headers:Authorization: "Bearer <YOUR_ENROLLMENT_TOKEN>"capabilities:accepts_remote_config: truereports_effective_config: truereports_health: truereports_remote_config: truereports_own_metrics: trueagent:executable: /usr/local/bin/otelcol-contribdescription:non_identifying_attributes:linkmesh.environment: "production"storage:directory: /var/lib/otelcol-supervisorThe LinkMesh UI can render this exact file pre-filled with your token: on the collector’s detail page, the enrollment banner’s otelcol-contrib tab fetches it from
/api/v1/downloads/opamp-bootstrap-config.yaml. Copy from there to avoid typos. -
Install a systemd unit for the supervisor (it spawns the collector as a subprocess — you don’t need a separate
otelcol-contrib.service):Terminal window sudo tee /etc/systemd/system/opamp-supervisor.service > /dev/null <<'UNIT'[Unit]Description=OpenTelemetry OpAMP Supervisor (LinkMesh-managed otelcol-contrib)After=network-online.targetWants=network-online.target[Service]Type=simpleExecStart=/usr/local/bin/opampsupervisor --config /etc/otelcol-supervisor/supervisor.yamlRestart=alwaysRestartSec=5[Install]WantedBy=multi-user.targetUNITsudo systemctl daemon-reloadsudo systemctl enable --now opamp-supervisor -
Watch the handshake:
Terminal window sudo journalctl -u opamp-supervisor -f
Verify in the UI
- Collectors — the host appears with management mode OpAMP, status Connected within ~30 s.
- Its Events tab shows
registeredandconfig_appliedon first connect.
Throughput shows up on the topology canvas automatically: after the
handshake LinkMesh offers the collector an own_metrics destination (a
per-collector OTLP bearer token) over OpAMP, and the collector starts
pushing its internal metrics to /v1/metrics.
How the two binaries fit together
┌──────────────────┐ OpAMP (WS/HTTP) ┌──────────────┐ │ opampsupervisor │ ◄──────────────────► │ LinkMesh │ │ (talks OpAMP) │ │ server │ └────────┬─────────┘ └──────────────┘ │ writes config, manages process ▼ ┌──────────────────┐ │ otelcol-contrib │ │ (data plane) │ └──────────────────┘The supervisor receives RemoteConfig pushes from LinkMesh, writes the
collector’s effective config.yaml into its storage directory, and
restarts the collector subprocess to pick it up. The collector itself
never talks OpAMP directly — the supervisor is its bridge.
Troubleshooting
- 401 on the WebSocket upgrade — the token is wrong, expired, or already used. Mint a fresh one.
websocket: bad handshake— yoursupervisor.yamlis usingws://instead ofwss://, or the request is hitting an HTTP/2 listener in front of LinkMesh. See Run behind a reverse proxy for the nginx WebSocket + HTTPS configuration.- Supervisor starts but never appears in the UI — confirm the host can
reach
wss://<server>/v1/opamp(trync -vz <server> 443), and thatagent.executableinsupervisor.yamlpoints at an existingotelcol-contribbinary. The supervisor logs the path on startup. agent::executable does not exist— fix theagent.executablepath; the supervisor refuses to start without a valid collector binary.- More: Enrollment troubleshooting.