﻿---
title: Add an OTel Collector in Fleet
description: Add an OpenTelemetry Collector to Fleet using the Add collector flow.
url: https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/8127/reference/fleet/add-otel-collector
products:
  - Elastic Agent
  - Fleet
applies_to:
  - Elastic Cloud Serverless: Preview
  - Elastic Stack: Preview since 9.4
---

# Add an OTel Collector in Fleet
Add an OpenTelemetry (OTel) Collector to Fleet for centralized monitoring using the **Add collector** flow. Fleet generates an OTel Collector configuration with the OpAMP extension wired to Fleet Server, an OTLP receiver, OTLP-to-Elasticsearch pipelines, and internal telemetry configuration. You then apply the configuration to your collector.

## Before you begin

You'll need:
- An Elastic Stack deployment version 9.4 or later or an Elastic Cloud Serverless Observability project
- A Kibana user with the **Admin** role. For more information, refer to [User roles and privileges](https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/8127/deploy-manage/users-roles/cloud-organization/user-roles).
- An OTel Collector with OpAMP extension support. For supported distributions and versions, refer to [Monitor OpenTelemetry Collectors in Fleet](https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/8127/reference/fleet/monitor-otel-collectors).
- A running [Fleet Server](https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/8127/reference/fleet/fleet-server)
  <note>
  If you're using an Elastic Cloud Hosted deployment or a Serverless Observability project, Fleet Server is already available. For self-managed deployments, refer to [Deploy on-premises and self-managed](https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/8127/reference/fleet/add-fleet-server-on-prem).
  </note>


## Add the collector through the Fleet UI

<stepper>
  <step title="Start adding a collector">
    1. In Kibana, enter **Fleet** in the [global search field](https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/8127/explore-analyze/find-and-organize/find-apps-and-objects), then select **Fleet / Agents**.
    2. Click **Add**, then select **Collector (OpAMP)** from the list.
    A flyout opens where you can enter metadata for your OTel Collector and preview the generated configuration.
  </step>

  <step title="Enter collector metadata">
    Provide values for the fields in the flyout. Fleet uses them to populate the OpAMP identity attributes and internal telemetry resource attributes in the generated configuration.

    | Field                            | Required | Description                                                                                                                                                                                                                                        |
    |----------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
    | **Collector group display name** | Yes      | Human-readable label for this group of collectors (for example, `Production West`). Defaults to `OTel Collector Group`. Sets `elastic.collector.group_name`.                                                                                       |
    | **Collector group**              | Yes      | Identifier used for filtering collectors in the Fleet UI. Auto-derived from the group display name as a slug. If you override the value, use only lowercase letters, numbers, and hyphens. Sets `elastic.collector.group` and `service.namespace`. |
    | **Service name**                 | Yes      | Identifier for the collector group in Elasticsearch. Auto-derived from the group display name as a slug. If you override the value, use only lowercase letters, numbers, and hyphens. Sets `service.name`.                                         |
    | **Collector display name**       | Yes      | Per-instance identity that distinguishes this collector within the group. Defaults to `${env:HOSTNAME}`. Sets `elastic.display.name` and `service.instance.id`.                                                                                    |
    | **Config name**                  | No       | A short name for this collector configuration (for example, `webserver-logs`). Appears as the configuration label in the Fleet UI. Sets `config.name`.                                                                                             |
    | **Config description**           | No       | A human-readable summary of what the collector does. Appears as a comment header in the effective configuration view. Sets `config.description`.                                                                                                   |
    | **Tags**                         | No       | Comma-separated labels (for example, `prod,west-region,k8s`). Tags appear in the Fleet UI tag filter and as resource attributes on self-emitted metrics and logs.                                                                                  |
    | **Environment**                  | No       | Label for the deployment environment (for example, `production` or `staging`). Sets `deployment.environment.name`.                                                                                                                                 |
    A generated configuration preview appears when all required fields contain valid values.
    <note>
      If you override the **Collector group** or **Service name** fields, they stop auto-updating from the group display name.
    </note>
  </step>

  <step title="Supply an {{es}} API key">
    <note>
      This applies to the `elasticsearch/otel` exporter included in the generated configuration. If your collector already exports to Elasticsearch with a valid API key, skip this step.
    </note>
    Choose how to provide an Elasticsearch API key for the `elasticsearch/otel` exporter:
    - **Create one in the flyout**: Click **Create API key**. Fleet creates an API key with default privileges and substitutes it for `${API_KEY}` in the generated configuration.
    - **Use an existing key**: Skip this action in the flyout, and replace `${API_KEY}` manually after copying the configuration in the next step. The key must have `create_index`, `write`, and `auto_configure` index privileges on `metrics-*`, `logs-*`, and `traces-*` data streams.
    <applies-to>Elastic Stack: Preview since 9.5</applies-to> <applies-to>Elastic Cloud Serverless: Preview</applies-to> If your deployment sends data through the [Elastic Cloud Managed OTLP Endpoint](https://docs-v3-preview.elastic.dev/elastic/opentelemetry/tree/main/reference/managed-inputs/managed-otlp-endpoint), this step asks for a managed OTLP API key instead. Replace `${API_KEY}` in the `Authorization` header rather than the `api_key` field, and note that the generated configuration exports through an `otlp/managed` exporter instead of `elasticsearch/otel`.
  </step>

  <step title="Apply the configuration">
    1. Copy the YAML configuration displayed in the flyout, or click **Download config** to save it as a YAML file. The snippet wires the OpAMP extension to Fleet Server, sets up an OTLP receiver and OTLP-to-Elasticsearch pipelines, and adds internal telemetry configuration.
       <note>
       If you already have a working OTel Collector with an Elasticsearch exporter, merge the generated configuration into your existing setup instead of replacing the whole file. Remove the `elasticsearch/otel` exporter block and adjust the pipelines to use your existing exporter.
       </note>
       <dropdown title="Generated OTel Collector configuration">
       ```yaml
       extensions:
       opamp:
       server:
       http:
       endpoint: "https://<fleet-server-host-url>/v1/opamp" 
       headers:
       Authorization: "ApiKey <fleet-enrollment-api-key>" 
       tls:
       insecure_skip_verify: true 
       instance_uid: "<instance-uid>" 
       agent_description:
       non_identifying_attributes: 
       elastic.collector.group_name: "OTel Collector Group"
       elastic.collector.group: "otel-collector-group"
       elastic.display.name: "${env:HOSTNAME}"

       receivers:
       otlp:
       protocols:
       grpc:
       endpoint: "0.0.0.0:4317"

       exporters:
       elasticsearch/otel:
       endpoints:
       - "https://<elasticsearch-host-url>" 
       api_key: "${API_KEY}" 
       mapping:
       mode: otel
       otlp:
       endpoint: "http://localhost:4317"
       tls:
       insecure: true

       service:
       extensions: [opamp]
       pipelines:
       logs:
       receivers: [otlp]
       exporters: [elasticsearch/otel]
       metrics:
       receivers: [otlp]
       exporters: [elasticsearch/otel]
       traces:
       receivers: [otlp]
       exporters: [elasticsearch/otel]
       telemetry:
       resource:
       elastic.collector.group_name: "OTel Collector Group"
       elastic.collector.group: "otel-collector-group"
       service.namespace: "otel-collector-group"
       service.name: "otel-collector-group"
       service.instance.id: "${env:HOSTNAME}"
       metrics:
       readers:
       - periodic:
       exporter:
       otlp:
       protocol: grpc
       endpoint: "http://localhost:4317"
       logs:
       processors:
       - batch:
       exporter:
       otlp:
       protocol: grpc
       endpoint: "http://localhost:4317"
       traces:
       processors:
       - batch:
       exporter:
       otlp:
       protocol: grpc
       endpoint: "http://localhost:4317"
       ```
       </dropdown>
    2. Paste or merge the configuration into your OTel Collector configuration file (for example, `otel.yaml`).
    3. Make sure every environment-variable placeholder in the configuration resolves at runtime:
       - `${API_KEY}`: replace it with your encoded Elasticsearch API key value, or set the `API_KEY` environment variable before starting or restarting the collector.
    - `${env:HOSTNAME}`: make sure `HOSTNAME` is set in the collector's runtime environment, or replace the placeholder with a static identifier.
    4. Save your configuration.
  </step>

  <step title="Start the collector">
    Run the appropriate command for your collector type, pointing to the configuration file you saved in the previous step:
    <tab-set>
      <tab-item title="Elastic Agent">
        ```shell
        ./otelcol --config ./otel-opamp.yaml
        ```
      </tab-item>

      <tab-item title="OTel Contrib Collector">
        ```shell
        ./otelcol-contrib --config ./otel-opamp.yaml
        ```
      </tab-item>
    </tab-set>
    <applies-to>Elastic Stack: Preview since 9.5</applies-to> <applies-to>Elastic Cloud Serverless: Preview</applies-to> The flyout shows the same commands. Select **Elastic Agent** or **OTel Contrib Collector** and the command updates to match your choice.
  </step>

  <step title="Verify the collector connection">
    1. Confirm the collector started without errors in its output.
    2. Return to the Fleet UI. The flyout waits for the collector to connect, then confirms how many collectors connected.
    3. Your OTel Collector now appears in the **Agents** list. To go straight there, click **View connected collectors**.
  </step>
</stepper>

<important>
  The generated configuration uses `tls.insecure_skip_verify: true` for the Fleet Server connection. Before deploying to production, adjust the configuration to use a CA file as described in [Configure TLS for Fleet Server connection](#configure-tls-for-fleet-server-connection).
</important>

<note>
  On Serverless Observability projects and Elastic Cloud Hosted deployments, you can replace the `elasticsearch/otel` exporter with the [Elastic Cloud Managed OTLP Endpoint](https://docs-v3-preview.elastic.dev/elastic/opentelemetry/tree/main/reference/managed-inputs/managed-otlp-endpoint), which accepts OTLP data directly and uses an APM-scoped API key. For more details, refer to [Elastic Cloud Managed OTLP Endpoint (mOTLP)](https://docs-v3-preview.elastic.dev/elastic/opentelemetry/tree/main/reference/managed-inputs/managed-otlp-endpoint).
</note>


## Configure TLS for Fleet Server connection

If your Fleet Server uses a self-signed certificate or a certificate from a non-public Certificate Authority (CA), you need to configure the OpAMP extension to trust it.

### Use a custom CA certificate

When Fleet Server uses a certificate signed by a private CA, provide the CA certificate to your OTel Collector:
```yaml
extensions:
  opamp:
    server:
      http:
        endpoint: https://fleet-server:8220/v1/opamp
        tls:
          ca_file: /path/to/ca.crt 
        headers:
          Authorization: ApiKey <fleet-enrollment-api-key>
    instance_uid: <instance-uid>

service:
  extensions: [opamp]
```


### Skip certificate verification (testing only)

For testing purposes only, you can skip TLS certificate verification:
```yaml
extensions:
  opamp:
    server:
      http:
        endpoint: https://fleet-server:8220/v1/opamp
        tls:
          insecure_skip_verify: true 
        headers:
          Authorization: ApiKey <fleet-enrollment-api-key>
    instance_uid: <instance-uid>

service:
  extensions: [opamp]
```

<warning>
  Using `insecure_skip_verify: true` skips TLS certificate verification and makes your connection vulnerable to man-in-the-middle attacks. Only use this for testing in isolated environments, never in production.
</warning>


## Related pages

- [Monitor OpenTelemetry Collectors in Fleet](https://docs-v3-preview.elastic.dev/elastic/docs-content/pull/8127/reference/fleet/monitor-otel-collectors)
- [Troubleshoot OTel Collectors in Fleet](/elastic/docs-content/pull/8127/troubleshoot/ingest/fleet/common-problems#opentelemetry-collectors-in-fleet)