Skip to content

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.

  1. 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.

  2. 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-contrib and opampsupervisor from upstream OTel releases (or from the LinkMesh mirror if your server has staged them for air-gapped use), writes /etc/otelcol-supervisor/supervisor.yaml, installs opamp-supervisor.service, and starts it.

  3. 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

  1. Install both binaries. Upstream OTel publishes them under separate release tags — collector here, supervisor under cmd/opampsupervisor:

    Terminal window
    OTEL_VERSION=0.153.0
    SUPERVISOR_VERSION=0.135.0
    ARCH=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/opampsupervisor
    sudo mkdir -p /etc/otelcol-supervisor /var/lib/otelcol-supervisor
  2. Get an enrollment token the same way as Option A step 1.

  3. Write /etc/otelcol-supervisor/supervisor.yaml:

    server:
    endpoint: "wss://linkmesh.example.com/v1/opamp"
    headers:
    Authorization: "Bearer <YOUR_ENROLLMENT_TOKEN>"
    capabilities:
    accepts_remote_config: true
    reports_effective_config: true
    reports_health: true
    reports_remote_config: true
    reports_own_metrics: true
    agent:
    executable: /usr/local/bin/otelcol-contrib
    description:
    non_identifying_attributes:
    linkmesh.environment: "production"
    storage:
    directory: /var/lib/otelcol-supervisor

    The 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.

  4. 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.target
    Wants=network-online.target
    [Service]
    Type=simple
    ExecStart=/usr/local/bin/opampsupervisor --config /etc/otelcol-supervisor/supervisor.yaml
    Restart=always
    RestartSec=5
    [Install]
    WantedBy=multi-user.target
    UNIT
    sudo systemctl daemon-reload
    sudo systemctl enable --now opamp-supervisor
  5. 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 registered and config_applied on 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 — your supervisor.yaml is using ws:// instead of wss://, 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 (try nc -vz <server> 443), and that agent.executable in supervisor.yaml points at an existing otelcol-contrib binary. The supervisor logs the path on startup.
  • agent::executable does not exist — fix the agent.executable path; the supervisor refuses to start without a valid collector binary.
  • More: Enrollment troubleshooting.