# Getting Started with Bindplane

How to get up and running with Bindplane

## What is Bindplane?

Bindplane is an OpenTelemetry-native telemetry pipeline designed to collect, refine, and export metrics, logs, and traces from any source to any destination.

With Bindplane, you can reduce costs and simplify telemetry collector management at an Enterprise scale, easily managing thousands of collectors and petabytes of data in a highly available multi-node configuration.

Bindplane uses the [Bindplane Distro for OpenTelemetry (BDOT) Collector](https://github.com/observIQ/bindplane-otel-collector) to standardize telemetry management with [Open Agent Management Protocol (OpAMP)](https://opentelemetry.io/docs/specs/opamp/). You can also create custom distributions of OpenTelemetry Collector and manage them with Bindplane.

## Quickstart

You can get started with Bindplane in one of two ways:

* **Cloud**: Securely hosted and managed by Bindplane.
* **Self-hosted**: host Bindplane in your own infrastructure; available for [Enterprise](https://bindplane.com/pricing) and [Google Editions](https://bindplane.com/google).

### Get Started with Cloud

We recommend using Bindplane Cloud as the fastest and easiest way to build out your telemetry pipelines. Visit the [pricing page](https://bindplane.com/pricing) to compare our plans, which range from Free to Enterprise.

To get started, [sign up](https://app.bindplane.com/signup) for free and follow the [Access Bindplane UI](/readme/access-bindplane-ui) guide.

### Get Started with Self-Hosted

For self-hosted Enterprise needs, you can manage Bindplane in your own infrastructure. Bindplane can run as a lightweight web server with no dependencies.

To get started, follow the deployment guide for your desired platform:

* [Virtual Machine](/deployment/virtual-machine/bindplane/install-bindplane-server)
* [Docker](/deployment/docker/server/install-bindplane-in-docker-compose)
* [Kubernetes](/deployment/kubernetes/server/installation)
* [Google Marketplace](/deployment/google-marketplace)

If you require TLS, are using a proxy, or require authentication, check out the [Configuration](/configuration/bindplane) page.

## Features

* Deploy and manage the lifecycle of telemetry collectors, starting with the [BDOT Collector](https://github.com/observIQ/bindplane-otel-collector)
* Build, deploy, and manage telemetry configurations for different [Sources](/integrations/sources) and deploy them to your collectors
* Export metric, log, and trace data to one or many [Destinations](/integrations/destinations)
* Utilize flow controls to adjust the flow of your data in real-time

<figure><img src="/files/5y4tNbqpczkCQfoiL6FK" alt="Bindplane docs - Getting Started with Bindplane - image 1"><figcaption></figcaption></figure>

## Architecture

Bindplane is composed of the following components:

* GraphQL Server: provides configuration and collector details via GraphQL
* REST Server: Bindplane CLI and UI make requests to the server via REST
* WebSocket Server: Collectors connect to receive configuration updates via [OpAMP](https://github.com/open-telemetry/opamp-spec)
* Store: pluggable storage manages configuration and Collector state
* Manager: dispatches configuration changes to Collectors

<figure><img src="/files/RnYmFTboiyd70Xc4i2fB" alt="Bindplane docs - Getting Started with Bindplane - image 2"><figcaption></figcaption></figure>


# Access Bindplane UI

Everything you need to know about navigating Bindplane's features

Create a Bindplane Cloud account at [`app.bindplane.com`](https://app.bindplane.com/login) .

{% hint style="info" %}
**NOTE**

For self-hosted Bindplane, the UI can be accessed with your browser on port `3001`. The URL will be `http://<IP_ADDRESS>:3001`, with IP Address being that of the Bindplane Server. To log in, use the credentials you specified when running the `init` command.
{% endhint %}

<figure><img src="/files/xPkvbb8BeqxE6tPNO66r" alt="Bindplane docs - Access Bindplane UI - image 1"><figcaption></figcaption></figure>

### Overview of the UI

You'll find the following pages once you've accessed the Bindplane UI.

#### Overview

The Overview page summarizes the flow and consumption of your configurations and destinations. It's used to quickly understand your overall throughput for metrics, logs, and traces.

The ability to sort to the "Top Three" will let you see the Configurations and Destinations with the most consumption at a glance.

#### Agents

This is the first stop to view your collectors quickly. From this page, you can navigate to view collector configuration, status, or errors directly by clicking on the collector name. Alternatively, you can see which configuration resources are deployed to these collectors in the "Configuration" column. Quickly narrow your view with the search bar and suggested filters.

#### Fleets

This page gives you a high-level overview of all your fleets. From here, you can navigate directly to a fleet’s details by clicking its name, where you can view its assigned configuration, agent membership, and agent health breakdown. You can also quickly narrow your view using the search bar and suggested filters.

#### Configurations

Here is the entry point to view all your current configurations. From here, you can select a configuration to edit or create a new configuration with the button on the top right.

#### Library

The library page is where you'll find all your reusable resources. Here, any sources, processors, connectors, and destinations that have been saved to the library can be viewed, edited, and deleted.

Now that you've accessed the UI, let's help you install your first collector.


# Install Your First Collector

Installing an OpenTelemetry Collector with Bindplane

Bindplane is built around OpenTelemetry and uses the Bindplane Collector distribution for OpenTelemetry. To learn more, check out the [GitHub](https://github.com/observIQ/bindplane-otel-collector) page.

### Installation

1. Navigate to the **Agents** tab and select the **Install Your First Agent** button inside the Agents table.

<figure><img src="/files/xPkvbb8BeqxE6tPNO66r" alt="Bindplane docs - Install Your First Collector - image 1"><figcaption></figcaption></figure>

2. Our Collector Installation wizard will walk you through installing a collector. The first step is to select the platform you'll be installing a collector on. When you've completed the form click the **Next** button.

{% hint style="info" %}
**NOTE**

Installation for containerized collectors on Kubernetes and Openshift first requires you to specify the assigned configuration for the collector. If that's the case you must first create a configuration for that platform.
{% endhint %}

<figure><img src="/files/rVUepPWeEbrjS34Goaed" alt="Bindplane docs - Install Your First Collector - image 2"><figcaption></figcaption></figure>

3. Now it's time to install your collector. Installation differs depending on the platform specified. In the case of Windows, macOS, or Linux installation you'll need to copy the installation command. Installed collectors will appear in the table on this page. When you're done you can view all collectors with the **Return to all Agents** button.

<figure><img src="/files/bUmxbUH1d2ubRHeGJUIw" alt="Bindplane docs - Install Your First Collector - image 3"><figcaption></figcaption></figure>

Upon successfully installing the collector, it will appear in the table below the install script.

<figure><img src="/files/gRjdopoOmflBSNOcYZsT" alt="Bindplane docs - Install Your First Collector - image 4"><figcaption></figcaption></figure>


# Build Your First Configuration

Configure an OpenTelemetry collector to start collecting telemetry and exporting it to your preferred destination

{% embed url="<https://www.youtube.com/watch?v=zqeUafSsoXg>" %}

### Configuration

To set up a collector configuration, navigate to the **Configurations** tab and click **Create Configuration**.

<figure><img src="/files/O1g2w45FwyMcWneuGqkb" alt="Bindplane docs - Build Your First Configuration - image 1"><figcaption></figcaption></figure>

You'll now be in the configuration wizard.

1. Give your config a name (see naming rules below)
2. Choose a platform for it to run on that corresponds to your collector(s)
3. You can optionally add a description for the config, then click **Next**

<figure><img src="/files/FM2Vkm8Dw7FtsJPYXFbT" alt="Bindplane docs - Build Your First Configuration - image 2"><figcaption></figcaption></figure>

{% hint style="info" %}
**NOTE**

Rules for naming configs:

* must be 63 characters or less
* must begin and end with an alphanumeric character ( \[a-z0-9A-Z] )
* can contain dashes ( - ), underscores ( \_ ), dots ( . ), and alphanumerics between
  {% endhint %}

#### Add a Source

Next, we'll add sources to our configuration. Sources are where you'd like to collect metrics, logs, or traces. We will start by collecting some host metrics using the Host source.

1. Click Add Source
2. Choose "Host"
3. Choose the metrics you'd like to collect
4. Click **Save** when you're all done

Click **Save** when you're done with the source configuration. You can add more sources, click on existing ones to see their configuration and edit or remove them, or click **Next** to move on to adding a destination.

<figure><img src="/files/ze3Nl1eMinOlg4ukQsPt" alt="Bindplane docs - Build Your First Configuration - image 3"><figcaption></figcaption></figure>

{% hint style="info" %}
**NOTE**

1. Source Limit per Configuration: A single configuration can contain up to **100 sources**. This limit includes both active and paused sources. Refer [FAQ](/frequently-asked-questions#is-there-a-limit-to-the-number-of-sources-that-can-be-assigned-to-a-configuration)
2. As a best practice, Bindplane recommends **25 sources** per configuration, as performance and manageability can degrade beyond that point.
   {% endhint %}

#### Add a Destination

The last step is to add a destination. This is where you'd like to ship your telemetry for storage or analysis. Bindplane supports the most popular destinations out of the box. [You can find a full list here.](/integrations/destinations)

For this example, we will show you how to configure a Google Cloud destination.

1. Click Add Destination
2. Select "Google Cloud" from the list of destinations
3. Enter a name (corresponding with the same naming rules listed above)
4. Fill in your Project ID
5. Select the desired authentication method

{% hint style="info" %}
**NOTE**

📘 If the VM running your Bindplane collector is already in Google Cloud, then you can leave the authentication method as auto.

📘 Creating a credentials file for Google Cloud

A Google Cloud Service Account can used for authentication by creating a service account and key.

[Create a service account](https://cloud.google.com/iam/docs/creating-managing-service-accounts) with the following roles:

* Metrics: roles/monitoring.metricWriter
* Logs: roles/logging.logWriter
* Traces: roles/cloudtrace.agent

[Create a service account JSON key](https://cloud.google.com/iam/docs/creating-managing-service-account-keys) and place it on the system that is running the collector.
{% endhint %}

6. Click **Save** to save the destination
7. Click **Save** again to finish building your configuration

<figure><img src="/files/7p4SaBLnOntQCV5SUoQZ" alt="Bindplane docs - Build Your First Configuration - image 4"><figcaption></figcaption></figure>

#### Apply Configuration

The next page is the Details page for the config you just created.

1. Click the **Add Agents** button to add a collector
2. Select which collectors you'd like to apply the config to
3. Click **Apply**

<figure><img src="/files/NncF6joFILCRI4a4hiXZ" alt="Bindplane docs - Build Your First Configuration - image 5"><figcaption></figcaption></figure>

#### Rollout The Configuration

Now that you've built your configuration and specified the collectors it should be applied to, you need to roll out the configuration. [Rollouts](broken://pages/gPCNbzCph7b1Uhp8VKql) are how we deploy configuration changes to our collectors.

Click "Start Rollout", and your configuration will be sent to your collector(s)!

<figure><img src="/files/GQl8fMqOFfz0dIN0QDvl" alt="Bindplane docs - Build Your First Configuration - image 6"><figcaption></figcaption></figure>

### Next Steps

Congratulations! You've successfully configured Bindplane, and you should now see telemetry flowing into your destination. If you run into any issues during setup, don't hesitate to contact us on [Slack](https://launchpass.com/bindplane); we'd be happy to help.

Next, you should take some time to explore the integrations available in Bindplane on our [Sources](/integrations/sources) page and [Destinations](/integrations/destinations) page.

Once you've configured your first pipeline, we can begin exploring the real power of Bindplane: routing, transforming, and reducing your telemetry data.


# Plans & Pricing

Bindplane offers three types of plans, each designed for different use cases. This page provides a high-level look at each plan and links to sub-pages with detailed usage limits and feature comparisons.

## Free

For individuals, small teams, or proofs-of-concept that need core telemetry capabilities without cost

[Learn more about the Free plan.](/plans-and-pricing/free)

## Growth

For teams that have moved beyond experimentation and need higher data volumes, more integrations, and support for scaling.

[Learn more about the Growth plan.](/plans-and-pricing/growth)

## Enterprise

For large organizations that require enterprise-grade scale, security, and support.

[Learn more about the Enterprise plan.](/plans-and-pricing/enterprise)

{% hint style="info" %}
For a detailed comparison of limits and included features across these three plans, see the [Pricing page](https://bindplane.com/pricing).
{% endhint %}

***

## Google Edition

We have partnered with Google to provide Google Cloud Observability and Security Operations customers access to Bindplane for no additional cost.

### Bindplane (Google Edition)

For Google Cloud Observability or Google Security Operations customers who want to ingest, standardize, and ship telemetry to any Google Destination.

[Learn more about Bindplane (Google Edition).](/plans-and-pricing/google-edition#bindplane-google-edition)

### Bindplane Enterprise (Google Edition)

For Google Security Operations customers who want data reduction and data masking for compliance.

[Learn more about Bindplane Enterprise (Google Edition).](/plans-and-pricing/google-edition#bindplane-enterprise-google-edition)

{% hint style="info" %}
For a detailed comparison of limits and included features across these Google-bundled plans, see the [Google Edition plans page](https://bindplane.com/google).
{% endhint %}


# Free

$0 per month

The **Free plan** is the quickest way to start using Bindplane without cost or commitment. It’s designed for individuals, small teams, or proofs-of-concept that need core telemetry capabilities without cost.

## What You Get

* **Production-ready features at evaluation scale** – Visual no-code pipelines, centralized collector management, automatic parsing, real-time transformation and masking, and built-in data reduction and compression
* **Everything you want to connect to** – All connectors, destinations, and processors included; limit apply only to usage
* **Collaboration included** – Unlimited users and one project to organize your work.

| Free Included Usage                      |                     |
| ---------------------------------------- | ------------------- |
| Users                                    | Unlimited           |
| Projects                                 | 1                   |
| Collectors[^1]                           | 10                  |
| Telemetry volume (logs, metrics, traces) | 100 GB/day combined |

<details>

<summary>Unified Fleet Management</summary>

* Centralized Collector Management
* Rollouts
* Visual Pipelines
* No Code Pipeline Builder
* Persistent Queue
* Resource Library

</details>

<details>

<summary>Unified Telemetry</summary>

* Standardized Telemetry
* Instrument Once, Send Anywhere
* Automatic Parsing
* Collect All Telemetry Signals
* Transformation Preview

</details>

<details>

<summary>Unified Control</summary>

* View Real Time Data Flow
* Enrich and Transform Telemetry
* Mask and Redact PII Data
* Telemetry Aggregation (Logs/Spans to Metrics)
* Advanced Data Reduction & Compression
* Rehydrate from Cold Storage

</details>

<details>

<summary>Security, Redundancy, &#x26; Support</summary>

* Best effort & community support

</details>

{% hint style="info" %}
For a detailed comparison of limits and included features across the three Direct plans, see the [Pricing page](https://bindplane.com/pricing).
{% endhint %}

## Need more data? Upgrade to a Growth plan

The Growth plan helps you scale your fleet and ingest without re-architecting, with 3 projects, 50 collectors, and bigger daily caps. [Explore the Growth plan here.](/plans-and-pricing/growth)

To upgrade from a Free plan:

1. Go to your [Organization page](https://app.bindplane.com/organization).
2. Under Free Plan, click the Upgrade to Growth button.
3. Enter your card details
4. Click Subscribe

If you would like to end your paid Growth plan, you can always downgrade back to Free.

[^1]: <sub>Collectors may also be referred to as "agents" in Bindplane. Limit for Free is for simultaneously connected collectors.</sub>


# Growth

Starts at $499/month

The **Growth plan** is built for teams moving from evaluation to steady-state production. It includes all Free features and adds capacity and governance for multi-environment deployments.

## What You Get

* **Production-ready features at production scale** – Same pipeline, parsing, and queueing capabilities, with higher limits.
* **Everything you want to connect to** – All connectors, destinations, and processors included; limits apply only to usage.
* **Collaboration and control** – Unlimited users with external auth (SSO), role-based access control, and an audit trail, Bindplane API for automation, and 8×5 support.

| Feature                                  | Included Usage                 |
| ---------------------------------------- | ------------------------------ |
| Users                                    | Unlimited                      |
| Projects                                 | 3                              |
| Collectors[^1]                           | 50 (then $1.50/agent/month)    |
| Telemetry volume (logs, metrics, traces) | 200 GB/day (then $0.28/GB/day) |

<details>

<summary>Unified Fleet Management</summary>

* Centralized Collector Management
* Rollouts
* Visual Pipelines
* No Code Pipeline Builder
* Persistent Queue
* Resource Library

</details>

<details>

<summary>Unified Telemetry</summary>

* Standardized Telemetry
* Instrument Once, Send Anywhere
* Automatic Parsing
* Collect All Telemetry Signals
* Transformation Preview

</details>

<details>

<summary>Unified Control</summary>

* View Real Time Data Flow
* Enrich and Transform Telemetry
* Mask and Redact PII Data
* Telemetry Aggregation (Logs/Spans to Metrics)
* Advanced Data Reduction & Compression
* Rehydrate from Cold Storage
* [Google SecOps Pipelines](https://docs.bindplane.com/feature-guides/google-secops-pipelines)

</details>

<details>

<summary>Security, Redundancy, &#x26; Support</summary>

* Bindplane API
* External Auth (SSO)
* Role Based Access Control
* Audit Trail
* 8 × 5 support

</details>

{% hint style="info" %}
For a detailed comparison of limits and included features across the three plans, see the [Pricing page](https://bindplane.com/pricing).
{% endhint %}

## Running large, distributed fleets? Upgrade to an Enterprise plan

The Enterprise plan is built for global fleets: up to 1,000,000 collectors across unlimited projects, with progressive rollouts, offline updates, external auth, and a self-hosted option. [Explore the Enterprise plan here.](/plans-and-pricing/enterprise)

Interested in the Enterprise plan? [Request a demo](https://bindplane.com/request-demo) or [contact us](mailto:sales@bindplane.com).

[^1]: <sub>Collectors may also be referred to as "agents" in Bindplane. Limit for Growth is for simultaneously connected collectors.</sub>


# Enterprise

Custom pricing to suit your needs, starts at $50,000/year

The **Enterprise plan** is built for organizations running global fleets and regulated workloads. It includes all Growth features and extends scale, deployment options, and identity integration, plus excellent 24x7 support.

## What You Get

* **Production at global scale** – Manage up to 1,000,000 collectors across unlimited projects, with progressive rollouts and offline updates for safe changes at the edge.
* **Everything you want to connect to** – All connectors, destinations, and processors included; usage is governed by custom limits aligned to your traffic.
* **Collaboration and control** – Unlimited users with external auth (SSO), role-based access control, and an audit trail; Bindplane API for automation; self-hosted deployment option; and 24×7 dedicated customer success.

| Enterprise Included Usage |            |
| ------------------------- | ---------- |
| Users                     | Unlimited  |
| Projects                  | Unlimited  |
| Collectors[^1]            | Custom[^2] |
| Logs                      | Custom[^2] |
| Metrics                   | Custom[^2] |
| Traces                    | Custom[^2] |

<details>

<summary>Unified Fleet Management</summary>

* Centralized Collector Management
* Rollouts
* Visual Pipelines
* No Code Pipeline Builder
* Persistent Queue
* Resource Library
* Manage up to 1 Million Collectors
* Progressive Rollouts
* Offline Collector Updates

</details>

<details>

<summary>Unified Telemetry</summary>

* Standardized Telemetry
* Instrument Once, Send Anywhere
* Automatic Parsing
* Collect All Telemetry Signals
* Transformation Preview

</details>

<details>

<summary>Unified Control</summary>

* View Real Time Data Flow
* Enrich and Transform Telemetry
* Intelligent Recommendations
* Mask and Redact PII Data
* Telemetry Aggregation (Logs/Spans to Metrics)
* Advanced Data Reduction & Compression
* Rehydrate from Cold Storage
* [Google SecOps Pipelines](https://docs.bindplane.com/feature-guides/google-secops-pipelines)

</details>

<details>

<summary>Security, Redundancy, &#x26; Support</summary>

* Bindplane API
* Role Based Access Control
* Audit Trail
* External Auth (SSO)
* Self-Hosted Option
* 24 × 7 dedicated customer success

</details>

{% hint style="info" %}
For a detailed comparison of limits and included features across the three plans, see the [Pricing page](https://bindplane.com/pricing).
{% endhint %}

## Ready to upgrade to an Enterprise plan?

The Enterprise plan is built for organizations that need a governed, reliable telemetry platform at company-wide scale. [Request a demo](https://bindplane.com/request-demo) or [contact us](mailto:sales@bindplane.com).

[^1]: <sub>Collectors may also be referred to as "agents" in Bindplane.</sub>

[^2]: For Enterprise customers, our sales team will work with you to define specific usage terms in your contract. These can be customized based on your exact use case and will differ between contracts.


# Google Edition

Free\* for Google Cloud Observability and Security Operations Customers

Included for Google customers, Bindplane offers two Google Edition plans: **Bindplane (Google Edition)** and **Bindplane Enterprise (Google Edition).** These deliver the core Bindplane platform with unlimited capacity to Google destinations, billed and supported under your existing Google agreement.

## Bindplane (Google Edition)

* **Core platform for Google Destinations** – Visual no-code pipelines, centralized collector management, instrument once and send to Google services; real-time transforms, basic data processing.
* **Scale and collaboration** – Unlimited users, unlimited projects, unlimited collectors, and unlimited logs/metrics/traces/profiles.
* **Automation and control** – Bindplane API, external auth (SSO), role-based access control, audit trail, optional self-hosted deployment.

| Bindplane (Google Edition) Included Usage |           |
| ----------------------------------------- | --------- |
| Users                                     | Unlimited |
| Projects                                  | Unlimited |
| Collectors[^1]                            | Unlimited |
| Logs                                      | Unlimited |
| Metrics                                   | Unlimited |
| Traces                                    | Unlimited |

{% hint style="warning" %}
**Limited Data Processing**

This plan includes a curated [subset of data processors](/integrations/processors#available-processors-by-bindplane-plan-license). For the full processor catalog, upgrade to the [Growth plan](/plans-and-pricing/growth).
{% endhint %}

{% hint style="warning" %}
**Limited Destinations**

This plan only supports Google destinations. For non-Google or multi-cloud destinations, upgrade to the [Growth](/plans-and-pricing/growth) or [Enterprise plan](/plans-and-pricing/enterprise).
{% endhint %}

<details>

<summary>Unified Fleet Management</summary>

* Centralized Collector Management
* Rollouts
* Visual Pipelines
* No Code Pipeline Builder
* Persistent Queue
* Resource Library
* Manage up to 1 Million Collectors

</details>

<details>

<summary>Unified Telemetry</summary>

* Standardized Telemetry
* Instrument Once, Send to Any Google Destinations
* Automatic Parsing
* Collect All Telemetry Signals
* Transformation Preview

</details>

<details>

<summary>Unified Control</summary>

* View Real Time Data Flow
* Basic Data Processors
* Intelligent Recommendations
* Rehydrate from Cold Storage
* [Google SecOps Pipelines](https://docs.bindplane.com/feature-guides/google-secops-pipelines)

</details>

<details>

<summary>Security, Redundancy, &#x26; Support</summary>

* Bindplane API
* External auth (SSO)
* Role Based Access Control
* Audit Trail
* Self-Hosted Option
* Google Support

</details>

## Bindplane Enterprise (Google Edition)

{% hint style="info" %}
\*Bindplane Enterprise Google Edition requires Enterprise Plus Tier of Google Security Operations.
{% endhint %}

* **Safer fleet changes** — Everything in Bindplane (Google Edition) plus progressive rollouts and offline agent updates for remote or intermittently connected collector&#x73;*.*
* **Full data processing and migration** — Full processor catalog (PII masking, logs/spans to metrics, advanced reduction/compression) and one non-Google destination allowed for 12 months to assist migration.
* **Scale and control** — Unlimited users/projects/collectors and unlimited logs/metrics/traces/profiles to Google destinations; plus Bindplane API, external auth (SSO), RBAC, audit trail, and an optional self-hosted deployment.

| Bindplane Enterprise (Google Edition) Included Usage |           |
| ---------------------------------------------------- | --------- |
| Users                                                | Unlimited |
| Projects                                             | Unlimited |
| Collectors[^1]                                       | Unlimited |
| Logs                                                 | Unlimited |
| Metrics                                              | Unlimited |
| Traces                                               | Unlimited |

{% hint style="warning" %}
**Limited Destinations**

This plan only includes 12 months of routing to one non-Google destination for SIEM migrations. For more non-Google or multi-cloud destinations, upgrade to the [Growth](/plans-and-pricing/growth) or [Enterprise plan](/plans-and-pricing/enterprise).
{% endhint %}

<details>

<summary>Unified Fleet Management</summary>

* Centralized Collector Management
* Rollouts
* Visual Pipelines
* No Code Pipeline Builder
* Persistent Queue
* Resource Library
* Manage up to 1 Million Collectors
* Progressive Rollouts
* Offline Collector Updates

</details>

<details>

<summary>Unified Telemetry</summary>

* Standardized Telemetry
* Instrument Once, Send to Any Google Destinations
* Automatic Parsing
* Collect All Telemetry Signals
* Transformation Preview

</details>

<details>

<summary>Unified Control</summary>

* View Real Time Data Flow
* Enrich and Transform Telemetry
* Intelligent Recommendations
* Mask and Redact PII Data
* Telemetry Aggregation (Logs/Spans to Metrics)
* Advanced Data Reduction & Compression
* Rehydrate from Cold Storage
* [Google SecOps Pipelines](https://docs.bindplane.com/feature-guides/google-secops-pipelines)

</details>

<details>

<summary>Security, Redundancy, &#x26; Support</summary>

* Bindplane API
* External auth (SSO)
* Role Based Access Control
* Audit Trail
* External Auth
* Self-Hosted Option
* Google support

</details>

{% hint style="info" %}
For a detailed comparison of limits and included features across the two Google-bundled plans, see the [Google Plans Comparison page](https://bindplane.com/google).
{% endhint %}

## Standardized on Google but want flexibility? Upgrade to an Enterprise plan

The Enterprise plan extends the Google Edition plans with multi-cloud/non-Google [destinations](/integrations/destinations) so you can direct each signal to the right system and avoid vendor lock-in as your stack evolves. [Explore the Enterprise plan here.](/plans-and-pricing/enterprise)

Interested in the Enterprise plan? [Request a demo](https://bindplane.com/request-demo) or [contact us](mailto:sales@bindplane.com).

[^1]: <sub>Collectors may also be referred to as "agents" in Bindplane.</sub>


# Deployment

Comprehensive deployment guides for Bindplane Server and Collectors across virtual machines, Kubernetes clusters, Docker environments, and Google Cloud Marketplace

This section contains comprehensive deployment guides for Bindplane Server and Collectors across various platforms and environments. Choose the deployment method that best fits your infrastructure and requirements.

## Deployment Options

### [Virtual Machine](/deployment/virtual-machine)

Deploy Bindplane Server and Collectors on virtual machines using system packages or Docker containers. Includes guides for Ubuntu, CentOS, RHEL, and other Linux distributions.

### [Kubernetes](/deployment/kubernetes)

Deploy Bindplane Server and Collectors on Kubernetes clusters with Helm charts, YAML manifests, and operator-based deployments. Includes high-availability configurations and production best practices.

### [Docker](/deployment/docker)

Deploy Bindplane Server and Collectors using Docker containers and Docker Compose. Perfect for development environments and containerized deployments.

### [Google Marketplace](/deployment/google-marketplace)

Deploy Bindplane Server directly from the Google Cloud Marketplace with pre-configured settings and automated setup.

## Choosing Your Deployment Method

* **Virtual Machine**: Best for traditional infrastructure, on-premises deployments, and environments with existing VM management
* **Kubernetes**: Ideal for container-native environments, microservices architectures, and cloud-native applications
* **Docker**: Perfect for development, testing, and containerized environments
* **Google Marketplace**: Quickest setup for Google Cloud Platform users

## Next Steps

After deploying Bindplane Server:

1. [Install your first collector](/readme/install-your-first-collector)
2. [Build your first configuration](/readme/build-your-first-configuration)
3. [Configure monitoring](/production-checklist/bindplane/monitoring-bindplane)
4. [Set up high availability](/production-checklist/bindplane/high-availability) for production environments


# Bare Metal or Virtual Machine

Deploy and manage Bindplane Server and Collectors on virtual machines using system packages

Deploy Bindplane Server and Collectors on virtual machines using system packages for traditional infrastructure deployments. This guide covers installation, upgrades, and configuration to help you get started quickly.

## Components

### [Server](/deployment/virtual-machine/bindplane)

The virtual machine deployment provides:

* Single-line install script
* Native system package installation
* Systemd service management
* Direct file system access
* Host-level monitoring
* Simple backup capabilities

### [Collector](/deployment/virtual-machine/collector)

Install Bindplane Collectors with a single install script and get:

* Systemd service management
* Direct file system access
* Native operating system packages

## Quick Start

1. [Install Server](/deployment/virtual-machine/bindplane/install-bindplane-server) - Deploy Bindplane Server
2. [Install Collectors](/deployment/virtual-machine/collector/install-and-uninstall-bindplane-collectors) - Deploy BDOT Collectors
3. [Upgrade/Uninstall](/deployment/virtual-machine/bindplane/upgrade-or-uninstall-bindplane-server) - Manage your deployment

## Additional Resources

* [Configure Server](/configuration/bindplane) - Set up your deployment
* [Install CLI](/cli-and-api/cli/installation) - Command line management
* [Use CLI](/cli-and-api/cli) - CLI documentation
* [Package Downloads](/deployment/virtual-machine/bindplane/package-downloads) - Available packages


# Bindplane Server (Self-Hosted)

Deploy Bindplane Server on virtual machines. This guide covers installation, upgrades, and configuration.

## Quick Start

1. [Install Server](/deployment/virtual-machine/bindplane/install-bindplane-server) - Deploy Bindplane Server.
2. [Upgrade/Uninstall](/deployment/virtual-machine/bindplane/upgrade-or-uninstall-bindplane-server) - Manage your deployment.
3. [Configure PostgreSQL](/deployment/virtual-machine/bindplane/postgresql) - PostgreSQL is used by Bindplane for storing data.


# Prerequisites

## Pre-Deployment Checklist

### License Key

If you do not have a license, you can obtain one by visiting the [Download](https://bindplane.com/download) page or working with your Bindplane representative.

### PostgreSQL Database

PostgreSQL is required for Bindplane to store configurations, collector metadata, and all other data.\
For small deployments, you can install PostgreSQL on the same server as Bindplane. For larger deployments, it is recommended to install PostgreSQL on a separate server.

See the [PostgreSQL](/deployment/virtual-machine/bindplane/postgresql) documentation for installation instructions.

## Bindplane Instance Sizing

Bindplane's resource requirements will differ based on the number of managed collectors. CPU, Memory, Disk throughput / IOPS, and network consumption will increase as the number of managed collectors increases.

Follow this table for CPU, memory, and storage capacity sizing.

<table><thead><tr><th width="165.2109375">Collector Count</th><th width="155.03125">Bindplane Nodes</th><th>Fault Tolerance</th><th width="128.609375">CPU Cores</th><th>Memory</th></tr></thead><tbody><tr><td>1-100</td><td>1</td><td>N/A</td><td>2</td><td>4GB</td></tr><tr><td>100-25,000</td><td>1</td><td>N/A</td><td>4</td><td>16GB</td></tr><tr><td>1-60,000</td><td>3</td><td>1</td><td>2</td><td>8GB</td></tr><tr><td>60,000-125,000</td><td>5</td><td>1</td><td>2</td><td>8GB</td></tr><tr><td>125,000-250,000</td><td>10</td><td>2</td><td>2</td><td>8GB</td></tr></tbody></table>

{% hint style="info" %}
**NOTE**

When exceeding 100 collectors, it is recommended to install PostgreSQL on a separate dedicated server. This will ensure that Bindplane and PostgreSQL do not compete for resources.
{% endhint %}

{% hint style="info" %}
**NOTE**

When exceeding 25,000 collectors, it is recommended to operate Bindplane in [High Availability](/production-checklist/bindplane/high-availability).
{% endhint %}

### High Availability and Fault Tolerance

When operating Bindplane in [High Availability](/production-checklist/bindplane/high-availability), you need to consider how many collectors you expect a single Bindplane instance to handle.

Take the total number of Bindplane instances, and subtract the maximum number of nodes you expect to become unavailable due to maintenance. It is important to make sure each node is not responsible for more than 30,000 collectors during a node outage.

See [Load Balancer Connection Constraints](#load-balancer-connection-constraints) for details.

### Load Balancer Connection Constraints

Most load balancers will be limited to roughly 65,535 connections per backend instance. When sizing your Bindplane cluster, you must consider how many collectors each node will be responsible for during maximum fault tolerance. A good rule of thumb is to not exceed 30,000 collectors. This is because each collector will open two connections to Bindplane. One for OpAMP remote management, and one for publishing throughput metrics.

If you have 100,000 collectors, a cluster size of three would be insufficient as each node would be responsible for roughly 33,000 collectors. 33,000 collectors \* 2 results in 66,000 TCP connections to each Bindplane instance. This situation gets worse if you bring one node down for maintenance, as each Bindplane instance would become responsible for 50,000 collectors, or 100,000 TCP connections.

## Network Requirements

### Bandwidth

Bindplane maintains network connections for the following:

* Collector Management
* Collector Throughput Measurements
* Command line and Web user interfaces

Maximum network throughput scales linearly with the number of connected collectors. As a rule of thumb, expect to consume 265B/s for every connected collector, or 2.12Mbps per 1,000 collectors.

### Firewall

Bindplane can run on a local area network and behind a firewall.

Bindplane does not need to be reachable from the internet, however, if collectors or users outside of\
your WAN require access, a VPN or inbound firewall rules must be configured to allow access.

### **Ports**

Bindplane listens on port `3001` by default. This port is configurable. See the [configuration documentation](/configuration/bindplane).

The Bindplane port is used for:

* Collector command and control using the [Open Agent Management Protocol (OpAMP)](https://github.com/open-telemetry/opamp-spec) (Websocket)
* Collector throughput measurement requests (HTTP POST request)
* Browser and CLI users (HTTP and Websocket)

**Browsers and API Clients**

The firewall must allow HTTP traffic to reach Bindplane on the configured port.


# Supported Operating Systems

### Supported Operating Systems

Bindplane Server can be installed on Linux[^1]<sup>1</sup> and supports the following distributions:

* Enterprise Linux[^2]<sup>2</sup> 9, 10
* Debian 12, 13
* Ubuntu LTS 22.04 LTS, 24.04 LTS, 26.04 LTS
* SUSE Linux 15, 16

### End-of-Life distributions

Bindplane Server is only supported on distributions that are actively supported by their upstream vendor. Earlier versions may still install and run, but we recommend upgrading to a currently supported version.

#### Resources

* Enterprise Linux: <https://access.redhat.com/support/policy/updates/errata>
* Debian: <https://www.debian.org/releases/>
* Ubuntu: <https://ubuntu.com/about/release-cycle>
* SUSE Linux: <https://www.suse.com/lifecycle/>

***

1. *While Bindplane Server will generally run on any modern distribution of Linux, `systemd` is the only supported init system.*
2. *Enterprise Linux refers to Red Hat Enterprise Linux and derivatives such as Oracle Enterprise* *Linux, Scientific Linux, CentOS, AlmaLinux, and Rocky Linux.*

[^1]: While Bindplane Server will generally run on any modern distribution of Linux, systemd is the only supported init system.

[^2]: Enterprise Linux refers to Red Hat Enterprise Linux and derivatives such as Oracle Enterprise Linux, CentOS, AlmaLinux, and Rocky Linux.


# Install Bindplane Server

Bindplane will run on Linux.

{% hint style="info" %}
If you use Docker, view [this guide](/deployment/docker/server/install-bindplane-in-docker-compose).
{% endhint %}

## Prerequisites

Self-hosted Bindplane requires the following prerequisites:

* A Bindplane license key
* A PostgreSQL database
* Verify that your system meets the recommended [Resource Requirements](/deployment/virtual-machine/bindplane/prerequisites)

See the [Prerequisites](/deployment/virtual-machine/bindplane/prerequisites) documentation for more information.

## Download and Install Bindplane Server

The first step is to download Bindplane from the [download page](https://bindplane.com/download).

<figure><img src="/files/WURkrKOUUOnutShG3UaE" alt="bindplane-self-hosted-download" width="375"><figcaption></figcaption></figure>

You download and install Bindplane by following these steps:

1. Select your platform. Choose Linux.
2. If you don't already have a license, you can request one.
3. Run the install command in a terminal.

The install command will look like the example below.

{% code overflow="wrap" %}

```bash
curl -fsSlL https://downloads.bindplane.com/bindplane/latest/install-linux.sh -o install-linux.sh && bash install-linux.sh --init && rm install-linux.sh
```

{% endcode %}

<figure><img src="/files/v5GjkQbjSrQ2aPCXQtse" alt="Bindplane docs - Install Bindplane Server - image 2"><figcaption></figcaption></figure>

## Configure Bindplane Server

Type y to continue the installation process. This will initialize the server with some configuration parameters, which updates the fields in the `config.yaml` located by default at `/etc/bindplane/config.yaml`:

* **License Key**: A license is required to initialize the server configuration. If you do not have a license, you can request one on the [Download](https://bindplane.com/download) page.
* **Server Host**: Set to the instance's IP address, or `0.0.0.0` to bind to all IP addresses.
* **Server Port**: Set to `3001` (the default value) unless you have a reason to change it.
* **Remote URL**: Set to the URL that should be used to communicate with Bindplane externally. Generally, this is your server's hostname or IP address followed by the port. If Bindplane is behind a load balancer please follow the [High Availability](/production-checklist/bindplane/high-availability) instructions.
* **Authentication Method**: Choose the authentication type you would like to configure. (Free Edition users will not be prompted, instead, basic auth is configured automatically)
  * **LDAP and Active Directory (Google Edition or Enterprise)**
    * **Enable TLS**: If enabled, TLS will be used when communicating with the directory server.
      * **Enable Mutual TLS**: If enabled, mutual TLS authentication will be used when communicating with the directory server.
        * **TLS Certificate**: Path to the X509 PEM TLS certificate to use when mutual TLS is enabled.
        * **Private Key**: Path to the X509 PEM TLS private key to use when mutual TLS is enabled.
      * **Certificate Authority**: Optional path to the X509 PEM TLS certificate authority that should be used to validate the directory server's certificate.
      * **Insecure Skip Verify**: Choose "n" here. It is not recommended to skip certificate verification outside of a development environment.
    * **Server Address**: Set to the IP address or hostname of the directory server.
    * **Server Port**: Set to the port of the directory server.
    * **Base DN**: Set to the distinguished name that should be used to search for users.
    * **Search Filter**: Set to the search filter that should be used to search for users.
    * **Bind Username**: Set to the username that should be used when authenticating with the directory server.
    * **Bind Password**: Set to the password that should be used when authenticating with the directory server.
  * **Single User**
    * **Username**: Set to your desired basic auth username
    * **Password**: Set to your desired basic auth password
* **Store Type**: Choose PostgreSQL. The legacy Bbolt store is deprecated and will be removed in a future release.
  * **PostgreSQL**: Provide connection parameters for the PostgreSQL database to connect to.
    * **Host**: Set to the IP address or hostname of the PostgreSQL instance.
    * **Port**: Set to the port that the PostgreSQL instance is reachable on.
    * **Database Name**: Set to the name of the database to use for storage. Bindplane will create the database at startup if it does not already exist.
    * **SSL Mode**: Set to the preferred SSL Mode for connecting to the PostgreSQL instance.
    * **Username**: Set to the PostgreSQL user to authenticate as.
    * **Password**: Set to the password for the chosen PostgreSQL user.

<figure><img src="/files/foomMgZM3gLVgFF7Zz3b" alt="Bindplane docs - Initialize Server Image"><figcaption></figcaption></figure>

## **Restart Bindplane Server**

At the end of initialization, you'll be prompted to automatically restart Bindplane to have the changes take effect. If you choose not to restart automatically, use the following command to restart the server manually.

```bash
sudo systemctl restart bindplane
```

That's it; you've successfully installed Bindplane. Next, we'll show you how to access the [Bindplane UI](/readme/access-bindplane-ui) in your browser.

## View Bindplane Server Status

Once initialized, you can check the service.

```bash
sudo systemctl status bindplane
```

For upgrade, downgrade and uninstall instructions, please see [Upgrade, Downgrade or Uninstall Bindplane Server](/deployment/virtual-machine/bindplane/upgrade-or-uninstall-bindplane-server)

Additionally, you can download packages directly, see our [Downloads](/deployment/virtual-machine/bindplane/package-downloads).


# Upgrade or Uninstall Bindplane Server

{% hint style="info" %}
**NOTE**

We recommend backing up your environment prior to an upgrade. See our [Backup and Disaster Recovery Guide](/configuration/bindplane/backup-and-disaster-recovery/bolt-store).
{% endhint %}

## Upgrading Bindplane Server

Upgrading the Bindplane Server is as simple as re-running the install script without the `--init` flag. A convenient piped one liner is below.

```bash
curl -fsSlL https://storage.googleapis.com/bindplane-op-releases/bindplane/latest/install-linux.sh | bash -s --
```

Additionally, if you want to upgrade to a specific version, you can do it using the below command. Replace 1.72.1 with the specific version you want.

```bash
curl -fsSlL https://storage.googleapis.com/bindplane-op-releases/bindplane/latest/install-linux.sh | bash -s -- --version 1.72.1
```

After upgrading you will need to restart the Bindplane Server.

```bash
sudo systemctl restart bindplane
```

### Older Transform Agent binaries

Each Bindplane release ships a versioned Transform Agent binary into `/var/lib/bindplane/transform-agents/`. Older `bta-v*` binaries are left in place during upgrades, and on service start the Bindplane Server launches every binary in this directory as a subprocess to support Live Preview for collectors on different versions.

If you'd prefer not to keep older `bta-v*` binaries around, you're free to remove all but the latest. The server runs fine with every version present; trimming simply reduces startup time and idle subprocesses. The change takes effect at the next service start.

## Downgrading Bindplane Server

{% hint style="danger" %}
**WARNING**

Downgrading is generally not recommended.
{% endhint %}

If you need to downgrade, please [contact the Bindplane support team](https://bindplane.com/support).

## Uninstall Bindplane Server

1. Stop the process:

```bash
sudo systemctl disable bindplane && sudo systemctl stop bindplane
```

2. Remove the package

* Debian and Ubuntu:

```bash
sudo apt-get remove bindplane-ee -y && sudo apt-get purge bindplane-ee -y
```

* CentOS and RHEL 8 and newer (use yum for anything older)

```bash
sudo dnf remove bindplane-ee -y
```

3. Optionally remove leftover data

```bash
sudo rm -rf /etc/bindplane /var/lib/bindplane /var/log/bindplane
```


# Package Downloads

The recommended way to install Bindplane is to use the install commands found on the [Installation](/deployment/virtual-machine/bindplane/install-bindplane-server) page. Alternatively, these are direct downloads to server and client packages.

### Direct Download Links

Bindplane releases are uploaded [here](https://console.cloud.google.com/storage/browser/bindplane-op-releases/bindplane?project=bindplane-op-releases\&pageState=\(%22StorageObjectListTable%22:\(%22f%22:%22%255B%255D%22\)\)\&prefix=\&forceOnObjectsSortingFiltering=false).

#### Server Linux Packages

**DEB**

* [AMD64](https://downloads.bindplane.com/bindplane/latest/bindplane-ee_linux_amd64.deb)
* [ARM64](https://downloads.bindplane.com/bindplane/latest/bindplane-ee_linux_arm64.deb)

**RPM**

* [AMD64](https://downloads.bindplane.com/bindplane/latest/bindplane-ee_linux_amd64.rpm)
* [ARM64](https://downloads.bindplane.com/bindplane/latest/bindplane-ee_linux_arm64.rpm)

#### Client Binaries

**macOS**

* [Intel](https://downloads.bindplane.com/bindplane/latest/bindplane-ee-darwin-amd64.zip)
* [Apple Silicon](https://downloads.bindplane.com/bindplane/latest/bindplane-ee-darwin-arm64.zip)

**Linux**

* [AMD64](https://downloads.bindplane.com/bindplane/latest/bindplane-ee-linux-amd64.zip)
* [ARM64](https://downloads.bindplane.com/bindplane/latest/bindplane-ee-linux-arm64.zip)

**Windows**

* [AMD64](https://downloads.bindplane.com/bindplane/latest/bindplane-ee-windows-amd64.zip)


# PostgreSQL

[PostgreSQL](https://www.postgresql.org/) is used by Bindplane for storing data such as agent metadata and configurations.

### Prerequisites

#### 1. Postgres Sizing

Postgres can be scaled vertically based on the number of managed collectors. See the [Postgresql Sizing](/deployment/virtual-machine/bindplane/postgresql/postgres-sizing) documentation for sizing details.

#### 2. Postgres Installation

Postgres installation must be done before installing Bindplane. See the [Postgres Installation](/deployment/virtual-machine/bindplane/postgresql/postgres-installation) documentation for more information.

#### 3. Postgres Configuration

After installing Postgres, you will need to configure it. See the [Postgres Configuration](/deployment/virtual-machine/bindplane/postgresql/postgres-configuration) documentation for more information.

### Bindplane Configuration

For a list of supported Bindplane PostgreSQL configuration options, see the [Postgres Configuration](/configuration/bindplane#postgres) section in the configuration documentation.


# Postgres Sizing

PostgreSQL performance is generally limited by the number of CPU cores and Memory available. It is recommended that the storage backing Postgres be low-latency (SSD) and capable of high throughput.

The following table provides a general guideline for sizing your PostgreSQL instance based on the number of collectors.

| Collector Count   | CPU Cores | Memory | Disk (GB) |
| ----------------- | --------- | ------ | --------- |
| 1-60,000          | 4         | 16GB   | 60        |
| 60,000-125,000    | 8         | 32GB   | 120       |
| 125,000-250,000   | 16        | 64GB   | 180       |
| 250,000-500,000   | 24        | 48GB   | 240       |
| 500,000-1,000,000 | 32        | 64GB   | 300       |


# Postgres Installation

PostgreSQL is a prerequisite for installing Bindplane. This document provides useful information on how to install PostgreSQL.

### Postgres Installation

Bindplane supports PostgreSQL on Linux, Kubernetes, and cloud providers. The following table shows the PostgreSQL versions supported and the Bindplane version that introduced support:

| PostgreSQL Version | Bindplane Version |
| ------------------ | ----------------- |
| 14                 | All versions      |
| 15                 | All versions      |
| 16                 | All versions      |
| 17                 | v1.94.3+          |

#### Linux

This guide will not cover the installation of PostgreSQL on Linux. Please refer to the [PostgreSQL documentation](https://www.postgresql.org/download/linux/) for installation instructions.

#### Kubernetes

Operating PostgreSQL on Kubernetes is supported but not recommended. If you must run\
PostgreSQL on Kubernetes, [CloudNativePG](https://cloudnative-pg.io/) operator is recommended.

Take care when operating stateful applications on Kubernetes. Stateful applications require\
persistent storage.

#### Cloud Provider

* [Google Cloud SQL](https://cloud.google.com/sql?hl=en)
* [Amazon Relational Database Service (RDS)](https://aws.amazon.com/rds/)
* [Azure Database for PostgreSQL](https://azure.microsoft.com/en-us/products/postgresql)


# Postgres Configuration

Once PostgreSQL is installed, you need to create a user, database, and assign permissions.

### 1. Create User

Replace `your_password` with a secure password.

```sql
CREATE USER "bindplane" WITH PASSWORD 'your_password';
```

### 2. Create Database

Create a database named `bindplane`. You can use a different database name if you prefer.

```sql
CREATE DATABASE "bindplane" ENCODING 'UTF8' TEMPLATE template0;
GRANT CREATE ON DATABASE "bindplane" TO "bindplane";
\c "bindplane";
```

### 3. Grant Permissions

Switch to the database created in step 1 with `\c bindplane`. Replace `bindplane` with the name of your database. Once connected, execute the following `GRANT` commands to give the `bindplane` user access to the `bindplane` database. Update the schema and database name if you used a different name.

```sql
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO "bindplane";
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO "bindplane";
GRANT ALL PRIVILEGES ON SCHEMA public TO "bindplane";
```


# Bindplane OTel Collector

Deploy Bindplane Collectors on virtual machines. This guide covers installation, upgrades, and configuration.

## Quick Start

1. [Prerequisites](/deployment/virtual-machine/collector/prerequisites) - Pre-deployment checklist.
2. [Supported Operating Systems](/deployment/virtual-machine/collector/supported-operating-systems)
3. [Install and Uninstall Collectors](/deployment/virtual-machine/collector/install-and-uninstall-bindplane-collectors) - Deploy BDOT Collectors.


# Prerequisites

## Pre-Deployment Checklist

Collectors must be able to initiate connections to Bindplane for OpAMP (websocket) and throughput measurements (HTTP). Bindplane will never initiate connections to the collector. The firewall can be configured to prevent Bindplane from reaching the collector networks, however, collector networks must be able to reach Bindplane on the configured port.

### **Collector Updates**

Bindplane will reach out to [github.com/observIQ/bindplane-agent/releases](https://github.com/observIQ/bindplane-otel-collector/releases) to detect new collector releases. This feature is optional.

You can disable GitHub polling by setting `agentVersions.syncInterval` to `0` in your Bindplane configuration.

```
agentVersions:
  syncInterval: 0
```


# Supported Operating Systems

Bindplane works in conjunction with the [Bindplane Collector](https://github.com/observIQ/bindplane-otel-collector), which can be installed on Linux, Mac, or Windows.

<table data-full-width="true"><thead><tr><th width="321">BDOT</th><th width="184" data-type="checkbox">Bindplane Enterprise</th><th width="289" data-type="checkbox">Bindplane Enterprise (Google Edition)</th><th width="219" data-type="checkbox">Bindplane (Google Edition)</th><th width="154" data-type="checkbox">Bindplane Free</th></tr></thead><tbody><tr><td>Windows 10 and 11</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Windows Server 2016, 2019, 2022, 2025</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td><a data-footnote-ref href="#user-content-fn-1">EL<sup>2</sup> 6</a><sup>3</sup></td><td>true</td><td>true</td><td>false</td><td>false</td></tr><tr><td>EL<sup>2</sup> 7, 8, 9, 10</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Fedora 40+</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Debian 10, 11, 12, 13</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Ubuntu 18.04+</td><td>true</td><td>true</td><td>true</td><td>false</td></tr><tr><td><a data-footnote-ref href="#user-content-fn-1">SuSE Enterprise Linux 11 SP4</a><sup>3</sup></td><td>true</td><td>true</td><td>false</td><td>false</td></tr><tr><td>SuSE Enterprise Linux 12 and 15</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Amazon Linux 2 and 2023</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>Mac OSX 12+</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td>AIX<sup>7</sup> 7.2 TL2+</td><td>true</td><td>true</td><td>false</td><td>false</td></tr></tbody></table>

***

1. *32-bit operating systems are not supported*
2. *Enterprise Linux refers to Red Hat Enterprise Linux and derivatives such as Oracle Enterprise Linux, Scientific Linux, CentOS, AlmaLinux, and Rocky Linux.*
3. *Bindplane will only provide support for the following if you are Bindplane Enterprise customer: Enterprise Linux 6 and SuSE Enterprise Linux 11 SP4 (Earlier SP are not supported)*
4. *The following versions of Windows are unsupported, but can have Windows Events collected remotely: Windows 7 and Windows Server 2008 and 2012*
5. *Other operating systems, especially modern Linux variants using systemd, will likely work. These are still considered unsupported, as they have not been tested and vetted by Bindplane.*
6. *The Bindplane Collector supports both amd64 and arm64 architectures on Windows, Linux, and macOS. Additionally, it supports ppc64 and ppc64le for Linux.*
7. *AIX requires installation on an LPAR of version 7.2 Tech Level 2 or above.*

[^1]: Additionally, we will only provide support for the following if you are Bindplane Enterprise customer: Enterprise Linux 6 and SuSE Enterprise Linux 11 SP4 (Earlier SP are not supported)


# Install and Uninstall Bindplane Collectors

The [Bindplane Collector](https://github.com/observIQ/bindplane-otel-collector) can be installed on Linux, Mac, or Windows with a single-line install script.

## Installation Script

{% hint style="warning" %}
**IMPORTANT**

🚧 Install Collectors from Bindplane

To install the collector, you should get the installation script from Bindplane as outlined in [Install Your First Collector](/readme/install-your-first-collector). Doing so ensures the collector instantly connects to Bindplane and can be managed without additional configuration.
{% endhint %}

{% hint style="info" %}
**NOTE**

📘 Agent or Collector: What's the difference?

We often use the terms Agent and Collector interchangeably. When you see either throughout the product or the documentation, we're always referring to the [Bindplane Collector](https://github.com/observIQ/bindplane-otel-collector)
{% endhint %}

## Uninstall The Bindplane Collector

On Linux, macOS, or Windows, run the following command to uninstall the collector.

#### Linux

{% code overflow="wrap" %}

```bash
sudo sh -c "$(curl -fsSlL https://github.com/observiq/bindplane-agent/releases/latest/download/install_unix.sh)" install_unix.sh -r
```

{% endcode %}

#### macOS

{% code overflow="wrap" %}

```bash
sudo sh -c "$(curl -fsSlL https://github.com/observiq/bindplane-agent/releases/latest/download/install_macos.sh)" install_macos.sh -r
```

{% endcode %}

#### Windows

{% code overflow="wrap" %}

```powershell
(Get-WmiObject -Class Win32_Product -Filter "Name = 'observIQ Distro for OpenTelemetry Collector'").Uninstall()
```

{% endcode %}

{% hint style="success" %}
**TUTORIAL**

[View step-by-step video tutorial how to install the Bindplane OTel Collector in a Windows VM.](https://www.youtube.com/watch?v=fMs70_qeTB0)
{% endhint %}

Optionally, on Windows, you can uninstall the collector via the control panel. Simply follow the steps below.

1. Navigate to the control panel, then to the "Uninstall a program" dialog.
2. Locate the `observIQ OpenTelemetry Collector` entry, and select uninstall.
3. Follow the wizard to complete the removal of the collector.

{% hint style="warning" %}
**IMPORTANT**

🚧 Data that persists after uninstalling

The collectors configuration files and log files are not removed when a collector is uninstalled. If you will not be re-installing the collector at a later time you may want to remove this folder. It will contain log files, the Bindplane configuration yaml, and any queue storage. Those files are located at `/opt/observiq-otel-collector` on Linux and `C:\Program Files\observIQ OpenTelemetry Collector` on Windows.
{% endhint %}


# Linux Package GPG Signing Verification

This document describes how to verify the GPG signature on the BDOT Collector's Linux packages.

{% hint style="info" %}
The BDOT Collector's Linux packages are signed with a GPG key starting with version v1.88.1.
{% endhint %}

## Preliminary Information

Signature verification is done automatically by the collector install script, but users who wish to use the Linux packages retrieved directly, without the install script, may wish to verify the signature on the packages independently.

## GPG Verification Data

The data required to verify the signature can be downloaded using curl:

```shellscript
curl https://bdot.bindplane.com/${COLLECTOR_VERSION}/gpg-keys.tar.gz -o /tmp/bdot-gpg-keys.tar.gz
tar -xzf /tmp/bdot-gpg-keys.tar.gz -C "/tmp/gpg"
```

`gpg-keys.tar.gz` contains:

* `bdot-public-gpg-key.asc`: This is the key used to verify the signature on this version of the collector.
* `deb-revocations/`: This folder contains any historically revoked keys. These keys are included to prevent any software signed with a revoked key from successfully installing on a Debian system.
  * Currently, there are no revocations included.
* `rpm-revocation.txt`: This file contains a list of all RPM key IDs that correspond to revoked keys. These key IDs should all be erased from the RPM store to prevent software signed with a revoked key from being installed on an RPM system.
  * Currently, there are no entries in this file, since there are no revocations.

## How to Verify

### Debian

#### Apt Verification

Debian based systems with apt-get do not have a mechanism for enforcing gpg checks on locally installed packages.

#### Manual Verification

First, ensure that both `gpg` and `ar` are installed on the system.

```shellscript
command -v gpg
command -v ar
```

If either of these commands don't return anything, install the corresponding package using apt.

```shellscript
sudo apt-get update
# gpg
sudo apt-get install gpg
# ar
sudo apt-get install binutils
```

Import `bdot-public-gpg-key.asc` and any entries in `deb-revocations/` to the GPG store.

```shellscript
gpg --import "bdot-public-gpg-key.asc"
if compgen -G "$TMP_DIR/gpg/deb-revocations/*" > /dev/null; then
  for key in "$TMP_DIR/gpg/deb-revocations/"*; do
    gpg --import "$key"
  done
fi
```

Then, extract `_gpgorigin` from the collector Debian package.

```shellscript
ar x  _gpgorigin observiq-otel-collector_<VERSION>_linux_<ARCH>.deb
```

Then, verify the signature.

```shellscript
ar p observiq-otel-collector_v1.88.0_linux_amd64.deb debian-binary control.tar.gz data.tar.gz | gpg --verify _gpgorigin -
```

If satisfied with the result (the key is not present, not expired, and not revoked), alter the trust level on the imported key to increase confidence in future signature verifications.

```shellscript
gpg --list-keys
# find the BDOT collector key, identify its fingerprint 
gpg --edit-key <FINGERPRINT>
gpg> trust
# select trust level
gpg> save
```

### RPM

First, import `bdot-public-gpg-key.asc` using RPM.

<pre class="language-shellscript"><code class="lang-shellscript"><strong>sudo rpm --import "bdot-public-gpg-key.asc"
</strong></code></pre>

Ensure that the key is not expired.

Next, ensure that there are no entries in your RPM store that match an ID in `rpm-revocations.txt`

```shellscript
while IFS= read -r id; do
  sudo rpm -q "$id"
done < rpm-revocations.txt
```

If any of the entries do not end with `is not installed`, those packages need to be removed.

```shellscript
sudo rpm -e "$id"
```

#### Yum Verification

First, ensure yum is configured to enforce GPG signing:

```bash
sudo vi /etc/yum.conf
```

Ensure the main block contains:

```viml
[main]
gpgcheck=1
localpkg_gpgcheck=1
```

Finally, attempt to install the package. If the package is signed with a valid signature, this should succeed.

```bash
sudo yum install observiq-otel-collector_<VERSION>_linux_<ARCH>.rpm
```

#### Dnf Verification

First, ensure dnf is configured to enforce GPG signing:

```bash
sudo vi /etc/dnf/dnf.conf
```

Ensure the main block contains:

```viml
[main]
gpgcheck=1
localpkg_gpgcheck=1
```

Finally, attempt to install the package. If the package is signed with a valid signature, this should succeed.<br>

```bash
sudo dnf install observiq-otel-collector_<VERSION>_linux_<ARCH>.rpm
```

#### Manual Verification

Manual verification is simple:

```shellscript
sudo rpm --checksig -v observiq-otel-collector_<VERSION>_linux_<ARCH>.rpm
```

Ensure all four lines end with `OK`.


# Kubernetes

Instructions for deploying Bindplane in Kubernetes using Helm charts and YAML manifests

Learn how to deploy Bindplane Server and Collectors on Kubernetes clusters for scalable, highly available telemetry collection.

## Components

### [Server](/deployment/kubernetes/server)

Deploy the Bindplane Server with:

* High availability and load balancing
* Persistent storage
* Ingress and TLS
* Monitoring and health checks
* Secure secrets management

### [Collector](/deployment/kubernetes/collector)

Deploy Collectors as DaemonSets or Deployments with:

* Node/Cluster coverage
* Gateway coverage
* Dynamic configuration
* Resource management
* Service discovery
* Kubernetes-native management

## Deployment Methods

* **Helm Charts**: Quick deployment with pre-configured charts
* **YAML Manifests**: Direct control over Kubernetes resources

## Requirements

* Kubernetes 1.20+
* 2 CPU cores, 4GB RAM minimum
* Persistent volume support
* Ingress controller
* kubectl CLI (Helm/kustomize optional)

## Next Steps

* [Deploy Server](/deployment/kubernetes/server)
* [Install Collectors](/deployment/kubernetes/collector)
* [Configure monitoring](https://github.com/observIQ/bindplane-docs/blob/main/docs/deployment/production-checklist/bindplane/monitoring-bindplane.md)
* [Set up high availability](https://github.com/observIQ/bindplane-docs/blob/main/docs/deployment/production-checklist/bindplane/high-availability/README.md)
* [Implement GitOps](https://github.com/observIQ/bindplane-docs/blob/main/docs/deployment/how-to-guides/gitops.md)


# Bindplane Server (Self-Hosted)

Covers Bindplane Server installation, upgrades, uninstallation, and core components required for deployment and operation.

Deploy and manage Bindplane Server on Kubernetes with comprehensive guides for installation, maintenance, and configuration.

## Overview

The Bindplane Server provides the central management plane for your telemetry pipeline. When deployed on Kubernetes, it offers:

* Scalable architecture for high availability
* Native Kubernetes integration
* Automated configuration management
* Built-in monitoring and health checks
* Secure communication with collectors

## Guides

### [Installation](/deployment/kubernetes/server/installation)

Step-by-step instructions for deploying Bindplane Server using Helm charts or YAML manifests.

### [Upgrade](/deployment/kubernetes/server/upgrade)

Safely upgrade your Bindplane Server deployment while maintaining availability.

### [Uninstall](/deployment/kubernetes/server/uninstall)

Clean removal of Bindplane Server and associated resources from your cluster.

### [Components](/deployment/kubernetes/server/components)

Detailed documentation of core Bindplane Server components and their configuration options.


# Installation

Deploy Bindplane Server to Kubernetes

Bindplane is fully supported on Kubernetes.

### Prerequisites

#### Helm

Bindplane is deployed with [Helm](https://helm.sh/). Make sure you have Helm installed on your workstation.

The Bindplane Helm Chart source can be found [here](https://github.com/observIQ/bindplane-op-helm).

#### Supported Distributions

The following Kubernetes distributions are officially supported:

* Google Kubernetes Engine (GKE)
* Amazon Elastic Kubernetes Service (EKS)
* Azure Kubernetes Service (AKS)
* OpenShift 4.x

Self-managed Kubernetes clusters are supported. See the [System Requirements](/deployment/kubernetes/server/installation/single-instance) section for details.

### Installation

Bindplane supports two architectures for Kubernetes. Single instance ([StatefulSet](/deployment/kubernetes/server/installation/single-instance)) and high availability ([Deployment](/deployment/kubernetes/server/installation/high-availability)).

The StatefulSet supports running Bindplane as a single pod without dependencies. It does not require a dedicated database or event bus. The StatefulSet is suitable for simple environments where Bindplane can be scaled vertically and 100% uptime is not a requirement.

The Deployment supports running Bindplane with multiple pods. Providing resiliency and load balancing among the Bindplane instances. When using the Deployment architecture, a dedicated database and event bus are required. The Deployment is suitable for environments where horizontal scaling and uptime are requirements.

* [Installation Guide](/deployment/kubernetes/server/installation/single-instance)
* [High Availability Installation Guide](/deployment/kubernetes/server/installation/high-availability)

### Usage

Once Bindplane Server is deployed, it can be reached by the remote URL endpoint. By default, the remote URL is set to the service endpoint.

```
BINDPLANE_REMOTE_URL=http://bindplane.bindplane.svc.cluster.local:3001
```

This remote URL is suitable for deploying collectors within the cluster. If you would like to reach Bindplane from outside of the cluster, see the [Next Steps](#next-steps) section.

When not exposing Bindplane with ingress, you can use port forwarding to connect to the web interface.

```bash
kubectl \
    -n bindplane \
    port-forward service/bindplane 3001:3001
```

Navigate to [http://localhost:3001](http://localhost:3001/) on your workstation.

### Next Steps

#### Collector Installation

With Bindplane deployed, you can move on to installing collectors to your cluster. See the [Kubernetes Agent Installation](/deployment/kubernetes/collector/install) documentation for details.

#### Ingress

If you would like to reach Bindplane from outside of the cluster (web interface, agent connections, etc), follow the [Bindplane Server Ingress](/deployment/kubernetes/server/components/kubernetes-ingress) documentation.


# Single Instance

Deploy Bindplane Server to Kubernetes

### Architecture

When Bindplane is deployed as a StatefulSet, it has the following architecture.

* Bindplane as a Single pod.
  * Deployed as a StatefulSet.
  * BBolt storage backend using a persistent volume claim.
* Prometheus time series database
  * Deployed as a StatefulSet.
  * Persistent storage using a persistent volume claim.
  * Prometheus is deployed and managed by the chart using [observIQ's Prometheus image](https://github.com/observiq/bindplane-op-enterprise/pkgs/container/bindplane-prometheus).
* Single transform agent pod, for [live preview](broken://pages/QeJXTHAiy3fbDC0oMrLz).

{% hint style="info" %}
**NOTE**

Bindplane uses Prometheus as a storage backend for collector throughput metrics. It is unnecessary to manage Prometheus outside of the Helm chart.
{% endhint %}

### Prerequisites

#### System Requirements

* Storage class which supports persistent volume claims (When running as a StatefulSet).
  * See [the instance sizing guidelines](/deployment/virtual-machine/bindplane/prerequisites) for recommended disk capacity.

### Installation

Add the Bindplane Helm chart to your workstation.

```bash
helm repo add "bindplane" \
    "https://observiq.github.io/bindplane-op-helm"

helm repo update
```

Create a `values.yaml` file, which will be used to configure your Helm deployment.

Add the initial options. Make sure to set the following:

* `config.username`: Your basic auth username for the Administrator project.
* `config.password`: Your basic auth password for the Administrator project.
* `config.sessions_secret`: A random uuid. You can use `uuidgen` to create one.

```yaml
config:
  # These options should be configured by
  # the user.
  username: ''
  password: ''
  sessions_secret: ''

backend:
  type: bbolt
  bbolt:
    volumeSize: '120Gi'

resources:
  # Request 2 cores and allow cpu bursting.
  # Request fixed amount of memory, 8Gb.
  requests:
    cpu: '2000m'
    memory: '8192Mi'
  limits:
    memory: '8192Mi'
```

{% hint style="info" %}
**NOTE**

Follow the [the instance sizing guidelines](/deployment/virtual-machine/bindplane/prerequisites) when modifying the resource requests and limits.
{% endhint %}

Deploy Bindplane to the `bindplane` namespace using Helm and your previously created `values.yaml` configuration file.

```bash
helm repo update

helm upgrade \
    --values="values.yaml" \
    --namespace=bindplane \
    --create-namespace \
    --install \
    bindplane \
    bindplane/bindplane
```

After a few moments, check the namespace by running `kubectl -n bindplane get pod`. You will see three pods:

* Bindplane
* Prometheus
* [Live Preview](broken://pages/QeJXTHAiy3fbDC0oMrLz) transform agent.

```
NAME                                        READY   STATUS    RESTARTS   AGE
bindplane-0                                 1/1     Running   0          3m42s
bindplane-prometheus-0                      1/1     Running   0          3m42s
bindplane-transform-agent-f5c6fb575-5cgtr   1/1     Running   0          3m42s
```

### Frequently Asked Questions

**Q: Why is the StatefulSet limited to one pod?**

**A:** Bindplane is limited to a single instance when configured with local storage. See the [Bindplane Deployment Installation](/deployment/kubernetes/server/installation/high-availability) documentation for details on how to deploy Bindplane using a scalable architecture.


# High Availability

Deploy Bindplane Server to Kubernetes with High Availability

### Architecture

When Bindplane is deployed as a Deployment, it has the following architecture.

* Bindplane with multiple replicas
  * Deployed as a Deployment.
* Prometheus time series database
  * Deployed as a StatefulSet.
  * Prometheus is deployed and managed by the chart using [observIQ's Prometheus image](https://github.com/observiq/bindplane-op-enterprise/pkgs/container/bindplane-prometheus).
* One or more Transform agent pods, for [live preview](broken://pages/QeJXTHAiy3fbDC0oMrLz)
* PostgreSQL storage backend

{% hint style="info" %}
**NOTE**

Bindplane uses Prometheus as a storage backend for collector throughput metrics. It is unnecessary to manage Prometheus outside of the Helm chart.
{% endhint %}

{% hint style="info" %}
**NOTE**

PostgreSQL is not deployed by the Bindplane Helm chart and must be deployed as a [prerequisite](#prerequisites).
{% endhint %}

### Prerequisites

#### Licensing

An Enterprise license is required when operating Bindplane in High Availability. Learn more [here](https://bindplane.com/solutions/).

#### PostgreSQL

PostgreSQL must be deployed and reachable from the cluster.

Postgres requirements

* Database named `bindplane`
* User with full permission to the `bindplane` database
* Reachable from Bindplane's Kubernetes cluster

#### Event Bus

Bindplane requires an external event bus when operating with more than one pod. See the [Event Bus](/deployment/kubernetes/server/components/event-bus) documentation for details.

### Installation

Add the Bindplane Helm chart to your workstation.

```bash
helm repo add "bindplane" \
    "https://observiq.github.io/bindplane-op-helm"

helm repo update
```

Create a `values.yaml` file, which will be used to configure\
your Helm deployment.

* `license`: Your Enterprise license.\
  Add the initial options. Make sure to set the following:
* `config.username`: Your basic auth username for the Administrator project.
* `config.password`: Your basic auth password for the Administrator project.
* `config.sessions_secret`: A random uuid. You can use `uuidgen` to create one.
* `config.eventbus.type`: The event bus type to use. This example will use Google Pub/Sub.
  * See the [Helm Event Bus Configuration](/production-checklist/bindplane/high-availability/event-bus) doc for available options.
* `backend.postgres.host`: The Hostname or IP address of the PostgreSQL server.
* `backend.postgres.port`: The PostgreSQL server's port.
* `backend.postgres.username`: The username the Bindplane server should use to connect to Postgres.
* `backend.postgres.password`: The password the Bindplane server should use to connect to Postgres.

```yaml
config:
  # An Enterprise license is required for
  # Bindplane when using PostgreSQL and an event bus.
  license: ''

  # These options should be configured by
  # the user.
  username: ''
  password: ''
  sessions_secret: ''

replicas: 3

# Eventbus is required when operating Bindplane
# using a distributed architecture.
eventbus:
  type: 'pubsub'
  pubsub:
    projectid: ''
    topic: ''

# Postgres is deployed outside of this chart
# shared by all Bindplane pods.
backend:
  type: postgres
  postgres:
    host: ''
    port: 5432
    database: 'bindplane'
    username: ''
    password: ''

resources:
  # Allow cpu bursting.
  # Request fixed amount of memory, 1Gb.
  requests:
    cpu: '500m'
    memory: '1024Mi'
  limits:
    memory: '1024Mi'

transform_agent:
  replicas: 2
```

Deploy Bindplane to the `bindplane` namespace using Helm and your previously\
created `values.yaml` configuration file.

```bash
helm repo update

helm upgrade \
    --values="values.yaml" \
    --namespace=bindplane \
    --create-namespace \
    --install \
    bindplane \
    bindplane/bindplane
```

After a few moments, check the namespace by running `kubectl -n bindplane get pod`.\
You will see three pods.

* Bindplane
* Prometheus
* [Live Preview](broken://pages/QeJXTHAiy3fbDC0oMrLz) transform agent.

```
NAME                                            READY   STATUS    RESTARTS   AGE
pod/bindplane-657d79f559-69wmw                  1/1     Running   0          55s
pod/bindplane-657d79f559-h8j2l                  1/1     Running   0          55s
pod/bindplane-657d79f559-tdl8j                  1/1     Running   0          19m
pod/bindplane-prometheus-0                      1/1     Running   0          22m
pod/bindplane-transform-agent-b44d78f5b-dgn2h   1/1     Running   0          22m
pod/bindplane-transform-agent-b44d78f5b-k9jdg   1/1     Running   0          22m

NAME                                TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/bindplane                   ClusterIP   10.53.39.91    <none>        3001/TCP   24m
service/bindplane-prometheus        ClusterIP   10.53.35.68    <none>        9090/TCP   24m
service/bindplane-transform-agent   ClusterIP   10.53.34.233   <none>        4568/TCP   24m

NAME                                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/bindplane                   3/3     3            3           24m
deployment.apps/bindplane-transform-agent   2/2     2            2           24m

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/bindplane-657d79f559                  3         3         3       19m
replicaset.apps/bindplane-685bd7f59b                  0         0         0       24m
replicaset.apps/bindplane-transform-agent-b44d78f5b   2         2         2       24m

NAME                                    READY   AGE
statefulset.apps/bindplane-prometheus   1/1     24m
```


# Upgrade

### Upgrade Chart Version

You can update your version of the Helm chart with the Helm repo update command.

```bash
helm repo update
```

### Upgrade Bindplane Version

Bindplane Server can be upgraded by updating the image version tag in your `values.yaml` file.

```yaml
image:
  name: ghcr.io/observiq/bindplane-ee
  tag: 1.39.0
```

Once the new image tag is in place, run the upgrade command.

```bash
helm upgrade \
    --values="values.yaml" \
    --namespace=bindplane \
    --create-namespace \
    --install \
    bindplane \
    bindplane/bindplane
```


# Uninstall

### Helm

When Bindplane is managed by Helm, it can be uninstalled with the `helm uninstall` command.

This example assumes that Bindplane was deployed with Helm using the application name "bindplane".

```
helm -n bindplane uninstall bindplane
```

### Manually

Bindplane can be cleaned up manually by deleting the namespace it was deployed to.

```bash
kubectl delete namespace bindplane
```


# Components

Overview of the core systems behind Bindplane's architecture, including NATS for messaging, Kubernetes Ingress for routing, and PostgreSQL for stateful storage.

Bindplane Server relies on several key components when deployed on Kubernetes:

## Core Components

### [Event Bus](/deployment/kubernetes/server/components/event-bus)

NATS provides the messaging backbone for Bindplane, enabling reliable communication between server instances and collectors. It handles configuration updates, heartbeats, and telemetry routing.

### [Kubernetes Ingress](/deployment/kubernetes/server/components/kubernetes-ingress)

The Ingress controller manages external access to Bindplane services, providing TLS termination, load balancing, and routing capabilities for both the UI and API endpoints.

### [PostgreSQL](/deployment/kubernetes/server/components/postgresql)

PostgreSQL serves as the primary stateful storage for Bindplane, maintaining configuration data, collector registrations, user information, and audit logs in a reliable and scalable database.

These components work together to provide a resilient, scalable platform for managing your telemetry pipeline. Each can be configured and scaled independently to meet your specific requirements.


# Event Bus

Bindplane Event Bus Helm Configuration

When operating Bindplane in a distributed architecture, an external event bus must be configured.

### NATS

The NATS event bus is Bindplane's embedded event bus, suitable for high availability without the need for external infrastructure.

NATS is configured by setting `eventbus.type` to `nats`.

```yaml
eventbus:
  type: nats
```

#### Resource Tuning

When using NATS, three dedicated StatefulSet pods are deployed. You can set their resource allocation by setting `nats.resources`.

```yaml
eventbus:
  type: nats

nats:
  resources:
    requests:
      memory: 1000Mi
      cpu: 1000m
    limits:
      memory: 1000Mi
```

### Google Pub/Sub

#### Automatic Authentication

Google Pub/Sub can be configured without credentials when using [Google Application Default Credentials](https://cloud.google.com/docs/authentication/application-default-credentials).

When running on a Google Kubernetes Engine cluster, Bindplane can authenticate to Pub/Sub without the use of a service account as long as the GKE node pool has the [Required Scopes](https://developers.google.com/identity/protocols/oauth2/scopes#pubsub) enabled.

```yaml
eventbus:
  type: 'pubsub'
  pubsub:
    projectid: 'my-project'
    topic: 'bindplane'
```

#### Service Account Credentials

If operating outside of Google Cloud, a service account JSON credential can be used. This example creates a secret named `bindplane-pubsub` which contains the service account JSON key.

```bash
kubectl create secret generic bindplane-pubsub \
  --from-file=credentials.json
```

```yaml
eventbus:
  type: 'pubsub'
  pubsub:
    projectid: 'my-project'
    topic: 'bindplane'
    credentials:
      secret: bindplane-pubsub
      subPath: credentials.json
```


# Kubernetes Ingress

Access Bindplane from Outside of the Cluster

{% hint style="warning" %}
**IMPORTANT**

🚧 Make sure Bindplane Server is configured with a secure password before exposing it.
{% endhint %}

### Basic Example

Bindplane can be exposed by Kubernetes ingress.

This example will expose Bindplane on the host `bindplane.local`using the `nginx` ingress class.

```yaml
ingress:
  enable: true
  host: bindplane.local
  class: nginx
```

{% hint style="info" %}
**NOTE**

It is recommended that TLS be configured when exposing Bindplane with ingress.
{% endhint %}

### TLS Example

This example will expose Bindplane on the host `bindplane.mycorp.net`using the `nginx` ingress class. It will also set the [Cert Manager Annotation](https://cert-manager.io/docs/usage/ingress/)`cert-manager.io/cluster-issuer`, which will trigger Cert Manager to retrieve a TLS certificate and store it in the secret named `bindplane-nginx-tls`.

```yaml
ingress:
  enable: true
  host: bindplane.mycorp.net
  class: nginx
  tls:
    enable: true
    secret: bindplane-nginx-tls
  annotations:
    cert-manager.io/cluster-issuer: 'letsencrypt-prod'
```


# PostgreSQL

Bindplane Postgres Helm Configuration

When operating Bindplane in a distributed architecture, a shared PostgreSQL instance is required.

### Basic Example

This example will configure Bindplane to connect to the host`postgres.mycorp.net` on port `5432`.

```yaml
backend:
  type: postgres
  postgres:
    host: 'postgres.mycorp.net'
    port: 5432
    database: 'bindplane'
    username: 'bindplane'
    password: 'bindplane-pass'
```


# Bindplane OTel Collector

Covers Bindplane Collector essentials, including supported images, customer-managed services, and installation, upgrade, and uninstall procedures

Deploy and manage Bindplane Collectors in Kubernetes with comprehensive guides for installation, maintenance, and configuration.

## Overview

The Bindplane Collector provides flexible telemetry collection capabilities when deployed on Kubernetes, offering:

* Automated deployment across nodes
* Efficient resource utilization
* Native Kubernetes integration
* Dynamic configuration updates
* Secure communication with Bindplane Server

## Guides

### [Bindplane Collector](/deployment/kubernetes/collector/bindplane-collector)

Learn about the core collector component and its capabilities for telemetry collection.

### [Customer Service](/deployment/kubernetes/collector/custom-service)

Configure and manage custom services for specialized collection needs.

### [Images](/deployment/kubernetes/collector/images)

Details on available container images and version compatibility.

### [Install](/deployment/kubernetes/collector/install)

Step-by-step instructions for deploying collectors using Helm or YAML manifests.

### [Upgrade](/deployment/kubernetes/collector/upgrade)

Safely upgrade your collector deployments while maintaining data collection.

### [Uninstall](/deployment/kubernetes/collector/uninstall)

Clean removal of collectors and associated resources from your cluster.


# Bindplane Collector

Deploy Bindplane Collectors to Kubernetes

Bindplane manages three different Kubernetes Collector types. Node, Cluster, and Gateway. Each collector type serves a unique purpose within the cluster. They can be used together or independently.

## Node

The Bindplane Node agents are deployed as a [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/). The Node agent scales up and down with the size of the cluster. Each agent is responsible for collecting logs and metrics from the node it is running on.

Additionally, the Node agent supports receiving OTLP metrics, traces, and logs from other services running in the cluster, via [clusterIP](https://kubernetes.io/docs/concepts/services-networking/service/#type-clusterip) service.

> **Warning**\
> The Node agent runs with pod `spec.toleration` `operator: "Exists"`. This ensures the DaemonSet deploys to all nodes in the cluster, regardless of their taints. Remove the toleration if you require more fine grained control.

### **Supported Sources**

* [Bindplane Gateway](/integrations/sources/bindplane-gateway)
* [Custom](/integrations/sources/custom)
* [Kubernetes Container Logs](/integrations/sources/kubernetes-container-logs)
* [Kubernetes Kubelet Metrics](/integrations/sources/kubernetes-kubelet-metrics)
* [OpenTelemetry (OTLP)](/integrations/sources/opentelemetry-otlp)
* [Kubernetes Prometheus](/integrations/sources/kubernetes-prometheus-node)

### **Persistence**

The Node agent makes use of [Host Path](https://kubernetes.io/docs/concepts/storage/volumes/#hostpath) volumes to persist the agent configuration file and exporter persistent queue directories.

The Host Path `/var/lib/observiq/otelcol/container`is mounted at `/etc/otel/storage` within the agent container.

Persistence allows the agents to operate during a Bindplane or backend outage.

## Cluster

The Bindplane Cluster agent is deployed as a [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/). The Cluster agent operates a single pod and is responsible for collecting cluster-level metrics and events (logs). The Cluster agent is not intended to scale above one pod, therefore it is limited to sources that should run on a single replica to avoid duplicate telemetry.

### **Supported Sources**

* [AWS S3 Event](/integrations/sources/aws-s3-event)
* [AWS S3 Rehydration](/integrations/sources/aws-s3-rehydration)
* [Azure Blob Rehydration](/integrations/sources/azure-blob-rehydration)
* [Bindplane Gateway](/integrations/sources/bindplane-gateway)
* [CrowdStrike FDR](/integrations/sources/crowdstrike-fdr)
* [Custom](/integrations/sources/custom)
* [Google Cloud Storage Rehydration](/integrations/sources/google-cloud-storage-rehydration)
* [Kubernetes Cluster Metrics](/integrations/sources/kubernetes-cluster-metrics)
* [Kubernetes Events](/integrations/sources/kubernetes-cluster-events)

## Gateway

The Bindplane Gateway agents are deployed as a [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) or [StatefulSet](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/). The Gateway agent is intended to operate as an aggregation layer, allowing other agents or services to forward metrics, traces, and logs to the gateway for additional processing before being shipped to a backend.

The Gateway agent is optional for monitoring a Kubernetes cluster. It should be used during the following situations:

* Offload processing from the Node and Cluster agent
* Limit backend access to a dedicated set of agents.
* You already have a solution for logs and metrics, and need a solution to receive telemetry from services running in the cluster.

### **Supported Sources**

* [AWS S3 Event](/integrations/sources/aws-s3-event)
* [Bindplane Gateway](/integrations/sources/bindplane-gateway)
* [Custom](/integrations/sources/custom)
* [Google Cloud Pub/Sub](/integrations/sources/google-cloud-pubsub)
* [OpenTelemetry (OTLP)](/integrations/sources/opentelemetry-otlp)
* [Splunk HEC](/integrations/sources/splunk-hec)
* [Splunk TCP](/integrations/sources/splunk-tcp)
* [Syslog](/integrations/sources/syslog)
* [TCP Logs](/integrations/sources/tcp)
* [UDP Logs](/integrations/sources/udp)

### **Persistence**

The Gateway agent uses a [Volume Claim Template](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#volume-claim-templates) to generate and assign volumes to each Gateway agent pod. The volume contains the agent's configuration file and exporter persistent queue directories. If an agent pod is killed or restarted for any reason, the volume assigned to that pod will be attached to the new instance of the pod, allowing the new pod to continue where the previous instance left off.

Persistence allows the agents to operate during a Bindplane or backend outage.

## Limitations

### Change Configurations

Kubernetes agents are bound to a single configuration. Changes to that configuration are supported, however, changing to a new configuration is not supported. To change to a new configuration, you can re-deploy the agents by using the Install Collectors page and selecting your new configuration.

### Non Kubernetes Collectors

Collectors running outside of Kubernetes can be installed as long as ingress has been configured. See the [getting started guide](/readme/install-your-first-collector) for collector installation instructions.


# Custom Service

A Kubernetes Service can be used to route network traffic to your Bindplane collectors.

When adding sources such as [Syslog](/integrations/sources/syslog), [TCP](/integrations/sources/tcp), [UDP](/integrations/sources/udp), you must create a custom [Kubernetes Service](https://kubernetes.io/docs/concepts/services-networking/service/) to route the traffic.

### **Bindplane Node**

This example shows how to expose TCP port `5140`, routing to the Bindplane Node agent.

```yaml
apiVersion: v1
kind: Service
metadata:
  name: bindplane-node-agent-syslog
  namespace: bindplane-agent
  labels:
    app.kubernetes.io/component: gateway
    app.kubernetes.io/name: bindplane-agent
spec:
  ports:
    - appProtocol: tcp
      name: syslog-tcp
      port: 5140
      protocol: TCP
      targetPort: 5140
  selector:
    app.kubernetes.io/component: node
    app.kubernetes.io/name: bindplane-agent
  type: ClusterIP
```

### **Bindplane Gateway**

This example shows how to expose TCP port `5140`, routing to the Bindplane Gateway agent.

```yaml
apiVersion: v1
kind: Service
metadata:
  name: bindplane-gateway-agent-syslog
  namespace: bindplane-agent
  labels:
    app.kubernetes.io/component: gateway
    app.kubernetes.io/name: bindplane-agent
spec:
  ports:
    - appProtocol: tcp
      name: syslog-tcp
      port: 5140
      protocol: TCP
      targetPort: 5140
  selector:
    app.kubernetes.io/component: gateway
    app.kubernetes.io/name: bindplane-agent
  type: ClusterIP
```

### Ingress

If you want to route traffic external to your cluster, you can use an Ingress resource to route traffic to the custom service.

You can read more about Ingress [here](https://kubernetes.io/docs/concepts/services-networking/ingress/).


# Images

The Bindplane Collector can be pulled from several container registries and offers multiple formats\
suitable for a variety of requirements.

### Registries

The Bindplane Collector container images can be pulled from the following registries:

<table><thead><tr><th>Registry</th><th width="380.48046875">Image</th><th>Architecture Support</th></tr></thead><tbody><tr><td><strong>GitHub Container Registry</strong> (default)</td><td><code>ghcr.io/observiq/bindplane-agent</code></td><td><code>amd64</code>, <code>arm64</code></td></tr><tr><td>Docker Hub</td><td><code>observiq/bindplane-agent</code></td><td><code>amd64</code>, <code>arm64</code></td></tr><tr><td>Google Artifact Registry</td><td><code>us-central1-docker.pkg.dev/observiq-containers/agent/bindplane-agent</code></td><td><code>amd64</code>, <code>arm64</code></td></tr></tbody></table>

### Image Tags

There are two image tags available for each version:

#### Standard Image

* Format: `{{major.minor.patch}}`
* Example: `1.55.0`
* Base: Ubuntu

The standard image is used by default and supports all collector receivers as it contains the required\
Systemd libraries (Journald receiver) and Java runtime (JMX receiver).

#### Minimal Image

* Format: `{{major.minor.patch}}-minimal`
* Example: `1.55.0-minimal`
* Base: Scratch

The minimal image is a scratch-based container, suitable for environments requiring low surface area\
images. It does not contain the required dependencies to support `journald` or `JMX` receivers. It does support all Kubernetes sources, except the container logs source's `journald` input.


# Install

### Install

Kubernetes Collector installation has a different flow than normal collectors.

Steps

1. Create a configuration for a Kubernetes platform
   1. Kubernetes Node: Deploys a collector to each node in the cluster using a DaemonSet.
   2. Kubernetes Cluster: Deploys a collector as a single pod Deployment.
   3. Kubernetes Gateway: Deploys a scalable set of collectors using a Deployment or StatefulSet.
   4. OpenShift Daemonset: Deploys a collector to each node in the cluster.
   5. OpenShift Deployment: Deploys a collector as a single pod deployment.
   6. OpenShift Gateway: Deploys a scalable set of collectors as a Deployment. See [OpenShift Gateway](#openshift-gateway) for special instructions.
2. Navigate to the collector's page and select "Install Collectors"
3. Choose a Kubernetes Platform
4. Select your configuration from step 1
5. Copy the YAML manifest to a file
6. Deploy the YAML manifest with `kubectl apply -f <file name>`

The collectors will be deployed to the cluster in the `bindplane-agent` namespace and connect to Bindplane automatically.

#### OpenShift Gateway

Unlike the OpenShift Node and Cluster agent, the Gateway agent does not require additional\
SecurityContextConstraint configuration nor does it require the same RBAC configuration.

Deploying the OpenShift Gateway is similar to deploying the Kubernetes Gateway, outlined in the steps above. There is one exception.

Create your namespace if it does not already exist. This will also create an OpenShift Project resource.

```bash
oc create namespace bindplane-agent
```

Determine your `uid` range by describing the project. Look for the `openshift.io/sa.scc.uid-range`\
label.

```bash
oc describe project bindplane-agent
```

```txt
Name:			bindplane-agent
Created:		8 minutes ago
Labels:			kubernetes.io/metadata.name=bindplane-agent
			pod-security.kubernetes.io/audit=restricted
			pod-security.kubernetes.io/audit-version=v1.24
			pod-security.kubernetes.io/warn=restricted
			pod-security.kubernetes.io/warn-version=v1.24
			openshift.io/display-name=bindplane-agent
			openshift.io/node-selector=
			openshift.io/sa.scc.mcs=s0:c33,c2
			openshift.io/sa.scc.supplemental-groups=1001060000/10000
			openshift.io/sa.scc.uid-range=1001060000/10000
Display Name:		bindplane-agent
Description:		<none>
Status:			Active
Node Selector:		<none>
Quota:			<none>
Resource limits:	<none>
```

In this example, the `openshift.io/sa.scc.uid-range` starts at `1001060000`. Yours will differ.

Update the YAML manifest downloaded from the Bindplane (Step 2 above). Make the following changes.

1. Replace all instances of `1000000000` with a UID from your range.
2. If you used a project name other than `bindplane-agent`, update all instances of `namespace: bindplane-agent` to reflect that change.

Apply the YAML manifest to your cluster with `oc apply`.

```txt
serviceaccount/bindplane-agent created
role.rbac.authorization.k8s.io/bindplane-gateway-agent created
rolebinding.rbac.authorization.k8s.io/bindplane-gateway-agent created
service/bindplane-gateway-agent created
service/bindplane-gateway-agent-headless created
deployment.apps/bindplane-gateway-agent created
horizontalpodautoscaler.autoscaling/bindplane-gateway-agent created
```

If the pods are running, everything is working.

```txt
$ oc -n bindplane-agent get pod

NAME                                       READY   STATUS    RESTARTS   AGE
bindplane-gateway-agent-74ff748988-bpzw5   1/1     Running   0          5s
bindplane-gateway-agent-74ff748988-ptd2x   1/1     Running   0          3s
```

### Example Installation

Create a configuration using a Kubernetes-compatible source. This example uses the Kubernetes Event Logs source.

<figure><img src="/files/ou2GJxBRwxc8b607l0mW" alt="Bindplane docs - Install Kubernetes Collectors - image 1"><figcaption></figcaption></figure>

Once the configuration has been created, navigate to the Collectors page and select "Install Collectors".

Select your Kubernetes platform and configuration. You will be prompted to copy the YAML manifest. Copy it and save it to a file.

<figure><img src="/files/QjE2luenkuUVpKDI94bp" alt="Bindplane docs - Install Kubernetes Collectors - image 2"><figcaption></figcaption></figure>

Ensure that the `OPAMP_ENDPOINT`environment variable has the correct value for your server. If you did not configure ingress, this value should match your deployment clusterIP service name and namespace. In this example, the service name is "my-bindplane" and the namespace is "default".

```
- name: OPAMP_ENDPOINT
  value: "ws://my-bindplane.default.svc.cluster.local:3001/v1/opamp"
```

If you configured ingress, your `OPAMP_ENDPOINT` should contain the ingress hostname and port. The port should be `80` for non-TLS ingress, and `443` if ingress TLS is enabled. Similarly, the protocol should be `ws` (websocket) when TLS is not configured, and `wss` (secure web socket) when TLS is enabled.

Deploy the YAML manifest with `kubectl apply -f <manifest file path>`. Once deployed, your collector(s) will appear on the Collectors page, and they will be bound to your configuration.

<figure><img src="/files/l8z2nSTg1uQ0n0R8VXN0" alt="Bindplane docs - Install Kubernetes Collectors - image 3"><figcaption></figcaption></figure>

### TLS

Kubernetes agents can be configured to connect to Bindplane using TLS. If the Bindplane TLS certificate is publicly signed, no action is required. If the certificate is signed by an internal certificate\
authority, the agent can be configured with a custom certificate authority for verifying the Bindplane\
certificate.

Your certificate authority file (`ca.crt`) can be added to a secret in the `bindplane-agent` namespace using the following command.

```bash
kubectl -n bindplane-agent create secret generic my-tls \
  --from-file ca.crt
```

Once the secret is created, you can modify your agent YAML manifest. Specifically, you need to append to the `volumes`, `volumeMounts`, and `env` sections of the agent container.

```yaml
spec:
  template:
    spec:
      containers:
        - name: opentelemetry-collector
          env:
+           - name: OPAMP_TLS_CA
+             value: /opt/tls/ca.crt
          volumeMounts:
+           - name: tls
+             mountPath: /opt/tls
      volumes:
+       - name: tls
+         secret:
+           secretName: my-tls
```

Using this example, the CA certificate `ca.crt` will be mounted to `/opt/tls/ca.crt`. The OpAMP client will be configured to use this certificate authority when validating CA certificates.

You can learn more about the various OpAMP environment variables [here](https://github.com/observIQ/bindplane-otel-collector/blob/main/docs/opamp.md#environment-variables).

#### Mutual TLS

When using mutual TLS, the same process is used. In this case, a client keypair is provided. This example uses `client.crt` and `client.key`.

```bash
kubectl -n bindplane-agent create secret generic my-tls \
  --from-file ca.crt \
  --from-file client.crt \
  --from-file client.key
```

```yaml
spec:
  template:
    spec:
      containers:
        - name: opentelemetry-collector
          env:
+           - name: OPAMP_TLS_CA
+             value: /opt/tls/ca.crt
+           - name: OPAMP_TLS_CERT
+             value: /opt/tls/client.crt
+           - name: OPAMP_TLS_KEY
+             value: /opt/tls/client.key
          volumeMounts:
+           - name: tls
+             mountPath: /opt/tls
      volumes:
+       - name: tls
+         secret:
+           secretName: my-tls
```


# Upgrade

Bindplane does not support upgrading container-based collectors when using the web interface. This is because the container is immutable and operates with a read-only filesystem. Volumes are used for any data that needs to be written at runtime.

You can upgrade the collector version by re-deploying the collectors using the process outlined in the Install section. Alternatively, you can modify the image tag and re-deploy with `kubectl apply`.


# Uninstall

Collectors can be uninstalled by using the `kubectl delete` command against the previously downloaded YAML manifest.

```bash
kubectl delete -f <file name>
```

If the yaml file is not available, you can clean up all resources with the following commands:

```bash
kubectl -n bindplane-agent delete ds bindplane-node-agent
kubectl -n bindplane-agent delete deploy bindplane-cluster-agent
kubectl -n bindplane-agent delete sts bindplane-gateway-agent
kubectl delete namespace bindplane-agent
```


# Docker

Instructions for running Bindplane Server and Collector using Docker

Learn how to deploy Bindplane Server and Collectors using Docker containers.

## Components

### [Server](/deployment/docker/server)

Deploy the Bindplane Server with:

* Docker Compose support
* Persistent storage
* Environment configuration
* Health monitoring
* Container updates

### [Collector](/deployment/docker/collector)

Deploy Collectors with:

* Containerized collection
* Dynamic configuration
* Resource controls
* Network isolation
* Horizontal scaling

## Images

* Server: `ghcr.io/observiq/bindplane-ee:latest`
* Collector: `ghcr.io/observiq/bindplane-otel-collector:latest`
* Tags: `latest`, `v1.89.5` (stable), `dev` (testing)

## Requirements

* Docker Engine 20.10+
* Docker Compose 2.0+ (optional)
* 2GB RAM, 1 CPU core
* 10GB disk space
* Internet access
* Available ports (3001, 3002)

## Configuration

### Environment

* `BINDPLANE_LICENSE`
* `BINDPLANE_USERNAME`
* `BINDPLANE_PASSWORD`
* `BINDPLANE_REMOTE_URL`
* `OPAMP_ENDPOINT`

### Storage

* Configuration files
* Database data
* TLS certificates
* Log files

## Next Steps

* [Install Collectors](/deployment/docker/collector)
* [Configure monitoring](https://github.com/observIQ/bindplane-docs/blob/main/docs/deployment/production-checklist/bindplane/monitoring-bindplane.md)
* [Set up storage](https://github.com/observIQ/bindplane-docs/blob/main/docs/deployment/configuration/bindplane/README.md)
* [Implement security](https://github.com/observIQ/bindplane-docs/blob/main/docs/deployment/configuration/bindplane/authentication/README.md)


# Bindplane Server (Self-Hosted)

Deploy and manage Bindplane Server using Docker Compose for centralized telemetry pipeline management

Deploy Bindplane Server using Docker Compose for simplified container orchestration and management. This guide covers installation, upgrades, and configuration to help you get started quickly.

The Docker Compose deployment provides:

* One-command installation and updates
* Built-in container orchestration
* Automated storage management
* Health checks and monitoring
* Simple rollback capabilities

## Quick Start

1. [Install](/deployment/docker/server/install-bindplane-in-docker-compose) - Deploy Bindplane Server
2. [Upgrade](/deployment/docker/server/upgrade-bindplane-server-in-docker-compose) - Update your deployment
3. [Uninstall](/deployment/docker/server/uninstall-bindplane-server-in-docker-compose) - Remove Bindplane Server


# Install Bindplane Server in Docker Compose

Learn how to install and configure Bindplane using Docker Compose.

This guide explains how to install and configure Bindplane using Docker Compose. Docker Compose provides an easy way to manage and run Bindplane in a containerized environment.

This setup is intended for development and testing purposes.

## Prerequisites

Before installing Bindplane, ensure you have:

* Docker installed (version 20.10.0 or later)
* Docker Compose installed (version 2.0.0 or later)
* At least 2 CPU cores and 4GB of RAM available
* Ports 3001 available for Bindplane
* A valid [Bindplane license](https://bindplane.com/download)

## Step 1: Create Docker Compose Configuration

Create a `docker-compose.yaml` file. Go to the [Download page](https://bindplane.com/download), select Docker as your platform, copy the content and paste it into your `docker-compose.yaml` file.

```yaml
version: "3"

volumes:
  bindplane:
  prometheus:

services:
  bindplane:
    container_name: bindplane-server
    restart: always
    image: ghcr.io/observiq/bindplane-ee:1.89.5
    ports:
      - "3001:3001"
    environment:
      - BINDPLANE_LICENSE=YOUR_LICENSE_KEY
      - BINDPLANE_USERNAME=admin
      - BINDPLANE_PASSWORD=admin
      - BINDPLANE_REMOTE_URL=http://localhost:3001
      - BINDPLANE_SESSION_SECRET=$(uuidgen)
      - BINDPLANE_LOG_OUTPUT=stdout
      - BINDPLANE_ACCEPT_EULA=true
      - BINDPLANE_PROMETHEUS_ENABLE=true
      - BINDPLANE_PROMETHEUS_ENABLE_REMOTE=true
      - BINDPLANE_PROMETHEUS_HOST=prometheus
      - BINDPLANE_PROMETHEUS_PORT=9090
      - BINDPLANE_TRANSFORM_AGENT_ENABLE_REMOTE=true
      - BINDPLANE_TRANSFORM_AGENT_REMOTE_AGENTS=transform:4568
      - BINDPLANE_STORE_TYPE=postgres
      - BINDPLANE_POSTGRES_HOST=postgres
      - BINDPLANE_POSTGRES_PORT=5432
      - BINDPLANE_POSTGRES_DATABASE=bindplane
      - BINDPLANE_POSTGRES_USERNAME=bindplane
      - BINDPLANE_POSTGRES_PASSWORD=password
    depends_on:
      - postgres
      - prometheus
      - transform

  postgres:
    container_name: bindplane-postgres
    restart: always
    image: postgres:16
    environment:
      - POSTGRES_DB=bindplane
      - POSTGRES_USER=bindplane
      - POSTGRES_PASSWORD=password
    volumes:
      - bindplane:/var/lib/postgresql/data

  prometheus:
    container_name: bindplane-prometheus
    restart: always
    image: ghcr.io/observiq/bindplane-prometheus:1.89.5
    volumes:
      - prometheus:/prometheus

  transform:
    container_name: bindplane-transform-agent
    restart: always
    image: ghcr.io/observiq/bindplane-transform-agent:1.89.5-bindplane
```

## Step 2: Configure Environment Variables

Replace the placeholder with your real values:

* `BINDPLANE_LICENSE` should be set to your license key.
* `BINDPLANE_REMOTE_URL` should be set to the Docker host's IP address, hostname, or external load balancer. This endpoint is used by agents to communicate with Bindplane for OpAMP and Measurements. `localhost` is sufficient for testing on your local machine only.
* `BINDPLANE_USERNAME` and `BINDPLANE_PASSWORD` should be set to something secure and unique.
* `BINDPLANE_POSTGRES_PASSWORD` in the bindplane service and `POSTGRES_PASSWORD` in the postgres service should be set to something secure.

## Step 3: Start Bindplane

Start the Bindplane service:

```bash
docker-compose up -d
```

Verify that the container is running:

```bash
docker-compose ps
```

View logs for troubleshooting:

```bash
docker compose logs -f
```

## Step 4: Access Bindplane

Once the container is running, you can access Bindplane:

* Bindplane UI: `http://localhost:3001`
* Prometheus UI: `http://localhost:9090`

## Step 5: Stopping the Services

```bash
# Stop all services
docker compose down

# Stop and remove volumes (this will delete all data)
docker compose down -v
```

## Troubleshooting

### Common Issues

1. **PostgreSQL fails to start**
   * Check if port 5432 is already in use
   * Ensure you have proper permissions for the data volume
2. **Bindplane fails to connect to PostgreSQL**
   * Wait for PostgreSQL to fully initialize
   * Check the PostgreSQL logs: `docker compose logs postgres`
3. **Transform agent connection issues**
   * Verify the transform agent is running: `docker compose ps transform`
   * Check transform agent logs: `docker compose logs transform`

## Viewing Logs

```bash
# View logs for a specific service
docker compose logs -f bindplane
docker compose logs -f postgres
docker compose logs -f transform
docker compose logs -f prometheus

# View all logs
docker compose logs -f
```

## Data Persistence

Data is persisted in Docker volumes:

* PostgreSQL data: `bindplane` volume
* Prometheus data: `prometheus` volume

To back up your data, you can use Docker volume backup commands:

```bash
docker run --rm -v bindplane:/data -v $(pwd):/backup alpine tar czf /backup/bindplane-backup.tar.gz /data
```

## Container Image Repositories

Bindplane container images can be found in the following locations:

* Github Packages: `ghcr.io/observiq/bindplane-ee`
* Google Artifact Repository: `us-central1-docker.pkg.dev/observiq-containers/bindplane/bindplane-ee`
* Docker Hub: `observiq/bindplane-ee`

Container images are tagged with the release version. For example, Release `v1.35.0` will have the tag `observiq/bindplane-ee:1.35.0`.

## Security Notes

* This configuration uses default passwords for PostgreSQL. In a production environment, you should change these.
* The default configuration exposes ports to localhost only.
* Sensitive information should be stored in environment variables or secrets management.
* Generate unique UUIDs for `BINDPLANE_SESSIONS_SECRET`.

## Additional Resources

* [Bindplane Documentation](/)
* [Docker Compose Documentation](https://docs.docker.com/compose/)

## Next Steps

After installing Bindplane:

* [Configure collectors](/deployment/docker/collector/install-bdot-collector-in-docker-compose)
* [Set up monitoring](/production-checklist/bindplane-otel-collector/monitoring)
* [Configure high availability](/production-checklist/bindplane-otel-collector/high-availability)


# Upgrade Bindplane Server in Docker Compose

Steps for upgrading the Bindplane Server when deployed via Docker, including image management

Bindplane Server can be upgraded by updating the image version tag in your `docker-compose.yaml` file.

```yaml
# ...
services:
  bindplane:
    image: ghcr.io/observiq/bindplane-ee:1.87.0
    # ...
```

Once the new image tag is updated in the `docker-compose.yaml`, restart your Docker Compose services.

```bash
docker compose down
docker compose up -d
```


# Uninstall Bindplane Server in Docker Compose

Guide for removing Bindplane Server when deployed with Docker, including container, image, and volume cleanup.

Bindplane Server can be uninstalled by using the `docker compose down` command. Use the `-v` flag to remove volumes as well.

```bash
docker compose down (-v)
```


# Bindplane OTel Collector

Deploy and manage Bindplane OpenTelemetry (BDOT) Collectors using Docker containers

Deploy and manage Bindplane Distro for OpenTelemetry (BDOT) Collectors using Docker containers for simplified telemetry collection. This guide covers installation, upgrades, and configuration to help you get started quickly.

The Docker container deployment provides:

* Containerized collection of logs, metrics, and traces
* Dynamic configuration management
* Resource usage controls
* Network isolation
* Horizontal scaling capabilities
* Secure communication with Bindplane Server

## Quick Start

1. [Install](/deployment/docker/collector/install-bdot-collector-in-docker-compose) - Deploy BDOT Collector
2. [Upgrade](/deployment/docker/collector/upgrade-bdot-collectors-in-docker-compose) - Update your deployment
3. [Uninstall](/deployment/docker/collector/uninstall-bdot-collectors-in-docker-compose) - Remove BDOT Collector


# BDOT Collector Architecture

Deploy Bindplane Collectors with Docker Compose

Deploying a Bindplane Distribution for OpenTelemetry (BDOT) Collector with Docker Compose is based on the Linux installation.

#### Docker Compose Service

The BDOT Collector is deployed as a service in a Docker Compose network.

**Supported Integrations**

Just as with the Linux, Mac, and Windows installation, all integrations are supported.

* [Sources](/integrations/sources)
* [Destinations](/integrations/destinations)
* [Processors](/integrations/processors)

{% hint style="info" %}
**NOTE**

Please note certain sources require special setup to work correctly, and may not always behave as expected. If you encounter any strange behavior, please let us know in our [Slack Community](https://www.launchpass.com/bindplane/free)!
{% endhint %}

**Configuration**

The BDOT Collector makes use of `storage` and `config` directories when mounted.

```
> config
    manager.yaml
> storage
    config.yaml
    logging.yaml
  docker-compose.yaml
```

Volume mounts:

```yaml
volumes:
    - ./config:/etc/otel/config
    - ./storage:/etc/otel/storage
```

### Limitations

#### Collector Version Upgrade

Container-based collectors are bound to the version which is specified in Docker. To change to a new version, you can re-deploy the collectors by editing the version in Docker Compose, and redeploying the collector.


# BDOT Collector Container Images

Details on available BDOT Collector container images, including versioning, tags, and image sources.

The Bindplane Distro for OpenTelemetry (BDOT) Collector can be pulled from several container registries and offers multiple formats suitable for a variety of requirements.

### Registries

The BDOT Collector container images can be pulled from the following registries:

| Registry                                | Image                              | Architecture Support |
| --------------------------------------- | ---------------------------------- | -------------------- |
| **GitHub Container Registry** (default) | `ghcr.io/observiq/bindplane-agent` | `amd64`, `arm64`     |
| Docker Hub                              | `observiq/bindplane-agent`         | `amd64`, `arm64`     |

### Image Tags

There are two image tags available for each version:

#### Standard Image

* Format: `{{major.minor.patch}}`
* Example: `1.76.3`
* Base: Ubuntu

The standard image is used by default and supports all collector receivers as it contains the required\
Systemd libraries (Journald receiver) and Java runtime (JMX receiver).

#### Minimal Image

* Format: `{{major.minor.patch}}-minimal`
* Example: `1.76.3-minimal`
* Base: Scratch

The minimal image is a scratch-based container, suitable for environments requiring low surface area\
images. It does not contain the required dependencies to support `journald` or `JMX` receivers. It\
does support all Kubernetes sources, except the container logs source's `journald` input.


# Install BDOT Collector in Docker Compose

Steps to deploy BDOT Collector using Docker Compose, including configuration and service definition.

Installing a BDOT Collector in Docker Compose has a different flow compared to collectors for Linux, Mac, and Windows.

### Install a BDOT Collector

1. Navigate to the **Agents** page and select **Install Agent**
2. Choose the **Linux** Platform
3. Copy the `secret-key` and `opamp-endpoint`
4. Create a `docker-compose.yaml` and paste this content below

   ```yaml
   volumes:
     bdot-collector-storage: # persistent storage for the bdot-collector

   services:
     bdot-collector:
       image: ghcr.io/observiq/bindplane-agent:1.84.0 # Select the image version you prefer
       container_name: bdot-collector
       hostname: bdot-collector
       volumes:
         - bdot-collector-storage:/etc/otel/storage
       ports:
         - "4317:4317"   # OTLP gRPC
         - "4318:4318"   # OTLP HTTP
         - "13133:13133" # Health check extension
         - "55679:55679" # ZPages debugging
       environment:
         OPAMP_ENDPOINT: "wss://app.bindplane.com/v1/opamp"   # point to your Bindplane server
         OPAMP_SECRET_KEY: "<YOUR_SECRET_KEY>"
         OPAMP_LABELS: ephemeral=true
         MANAGER_YAML_PATH: /etc/otel/storage/manager.yaml
   ```
5. The `config.yaml` will be autogenerated when starting the collector.
6. (Optional) Create a `logging.yaml` file:

   ```yaml
   output: stdout
   level: info
   ```

   Add a volume and environment variable:

   ```yaml
       volumes:
         - ./logging.yaml:/etc/otel/logging.yaml
       # ...
       environment:
         LOGGING_YAML_PATH: /etc/otel/logging.yaml
   ```
7. The `manager.yaml` will be autogenerated when connecting the collector to Bindplane and rolling out a configuration.

   <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><strong>NOTE</strong></p><p>If you want to re-use the <code>manager.yaml</code>, create a <code>storage</code> directory and change the <code>MANAGER_YAML_PATH</code> path to:</p><pre class="language-yaml"><code class="lang-yaml">volumes:
     # Replace the volume with a local directory
     # - bdot-collector-storage:/etc/otel/storage 
     - ./storage:/etc/otel/storage
   </code></pre><p>When starting new collectors from Docker Compose, make sure to delete the content of the <code>manager.yaml</code>.</p></div>
8. Start the BDOT Collector:

   ```bash
   docker compose up -d
   ```

### Create a configuration for Docker Compose

1. Navigate to the **Configurations** and select **Create Configuration**
2. Select the **Linux** Platform and give it a name
3. Add sources and destinations and create the configuration
4. Click **Add Agents**, select the BDOT Collector you created above, and click **Apply**
5. Finally, click **Start Rollout**, and you're done!

### Example Installation

This example uses the Host metrics, OTLP logs and metrics, and file logs.

<figure><img src="/files/w3P2bhtYIYzexTGH89m1" alt="Bindplane docs - Install BDOT Collector in Docker Compose - image 1"><figcaption></figcaption></figure>

Get the BDOT Collector secret key, installation id, and OpAMP configuration keys from the Collector installation page.

<figure><img src="/files/rIdlSLh8whllbuwoRGGt" alt="Bindplane docs - Install BDOT Collector in Docker Compose - image 2"><figcaption></figcaption></figure>

Ensure that the `OPAMP_ENDPOINT`environment variable has the correct value for your server.

```yaml
- name: OPAMP_ENDPOINT
  value: "ws://your-bindplane-server:3001/v1/opamp" # use "wss://app.bindplane.com/v1/opamp" for Bindplane Cloud
```

The port should be `3001` for non-TLS, and `443` if TLS is enabled. Similarly, the protocol should be `ws` (websocket) when TLS is not configured, and `wss` (secure web socket) when TLS is enabled.

Start Docker Compose with `docker compose up -d`. Once deployed, your collector will appear on the Agents page, and they will be bound to your configuration.

<figure><img src="/files/1WN1kNbMbpsxq7PaRAeI" alt="Bindplane docs - Install BDOT Collector in Docker Compose - image 3"><figcaption></figcaption></figure>

### TLS

BDOT Collectors in Docker Compose can be configured to connect to Bindplane using TLS. If the Bindplane TLS certificate is publicly signed, no action is required. If the certificate is signed by an internal certificate authority, the collector can be configured with a custom certificate authority for verifying the Bindplane certificate.

Your certificate authority file (ca.crt) can be added to a BDOT Collector `docker-compose.yaml` with the `OPAMP_TLS_CA` environment variable. The sample below considers you storing the `ca.crt` in a `certs` directory and binding the volume to the `bdot-collector`.

```yaml
# ...
  bdot-collector:
    image: ghcr.io/observiq/bindplane-agent:1.84.0 # Select the image version you prefer
    container_name: bdot-collector
    hostname: bdot-collector
    volumes:
    # ...
      - ./certs:/etc/otel/certs # Add certs volume
    environment:
      # ...
      OPAMP_TLS_CA: /etc/otel/certs/ca.crt # use this env var
      # Alternatively, skip verification
      OPAMP_TLS_SKIP_VERIFY: false # Set to true to skip TLS verification
# ...
```

Using this example, the CA certificate `ca.crt` will be mounted to `/opt/tls/ca.crt`. The OpAMP client will be configured to use this certificate authority when validating CA certificates.

### Mutual TLS (mTLS)

When using mutual TLS, the same process is used. In this case, a client keypair is provided. This example uses `client.crt` and `client.key`.

With these secrets you can modify your BDOT Collector Docker Compose service and add environment variables for the TLS certs and keys.

```yaml
# ...
  bdot-collector:
    image: ghcr.io/observiq/bindplane-agent:1.84.0 # Select the image version you prefer
    container_name: bdot-collector
    hostname: bdot-collector
    volumes:
      # ...
      - ./certs:/etc/otel/certs # Add certs volume
    # ...
    environment:
      # ...
      OPAMP_TLS_CA: /etc/otel/certs/ca.crt
      OPAMP_TLS_CERT: /etc/otel/certs/client.crt # Add env vars for the client certificate
      OPAMP_TLS_KEY: /etc/otel/certs/client.key  # and key
# ...
```


# Upgrade BDOT Collectors in Docker Compose

Bindplane **does not** support upgrading container-based collectors when using the web interface. This is because the container is immutable and operates with a read-only filesystem. Volumes are used for any data that needs to be written at runtime.

You can upgrade the collector version by re-deploying the collectors using the process outlined in the Install section.


# Uninstall BDOT Collectors in Docker Compose

Collectors can be uninstalled by using the `docker compose down` command. Use the `-v` flag to remove volumes as well.

```bash
docker compose down (-v)
```


# AWS ECS

Deploy BDOT Collectors on AWS ECS using Fargate and EC2 launch types with CloudFormation templates.

| Feature        | Fargate                         | EC2                                     |
| -------------- | ------------------------------- | --------------------------------------- |
| **Management** | Serverless, no EC2 management   | Full control over instances             |
| **Cost**       | Pay-per-use                     | More predictable pricing                |
| **Best For**   | Variable workloads, quick setup | Consistent workloads, cost optimization |

### Prerequisites

* AWS CLI v2.x configured
* Valid AWS account with appropriate permissions
* Bindplane OTel Collector secret key

### Architecture

* ECS Cluster with auto-scaling
* VPC with public/private subnets
* OpAMP protocol for server communication
* CloudWatch logging

### Security

* VPC isolation with security groups
* RDS encryption at rest and in transit
* IAM roles with least-privilege access
* Private subnets for database and internal services

### Monitoring

* CloudWatch logs and metrics
* ECS health checks
* ALB health checks
* Custom health endpoints


# Bindplane OTel Collector

Deploy BDOT Collectors on AWS ECS for scalable, managed collector deployment with automatic scaling and monitoring.

This section provides comprehensive guides for deploying BDOT Collectors on AWS ECS using both Fargate and EC2 launch types.

### Deployment Options

#### AWS ECS Fargate

* **Serverless compute** - No EC2 instances to manage
* **Automatic scaling** - Scales based on demand
* **Pay-per-use** - Only pay for resources consumed
* **Quick deployment** - Faster to get started
* **Best for**: Variable workloads, quick deployments, minimal infrastructure management

#### AWS ECS EC2

* **Full control** - Manage underlying EC2 instances
* **Cost-effective** - More predictable pricing for consistent workloads
* **Custom configurations** - Full control over instance types and configurations
* **SSH access** - Direct access to instances for debugging
* **Best for**: Consistent workloads, cost optimization, custom requirements

### Quick Start

#### Fargate Deployment

```bash
# Deploy with CloudFormation
aws cloudformation create-stack \
  --stack-name bindplane-collector-ecs-fargate \
  --template-body file://YOUR_CLOUDFORMATION_FILE.yaml \
  --parameters \
    ParameterKey=CollectorSecretKey,ParameterValue=YOUR_SECRET_KEY \
    ParameterKey=OpampEndpoint,ParameterValue=wss://app.bindplane.com/v1/opamp \
  --capabilities CAPABILITY_IAM
```

#### EC2 Deployment

```bash
# Deploy with CloudFormation
aws cloudformation create-stack \
  --stack-name bindplane-collector-ecs-ec2 \
  --template-body file://YOUR_CLOUDFORMATION_FILE.yaml \
  --parameters \
    ParameterKey=CollectorSecretKey,ParameterValue=YOUR_SECRET_KEY \
    ParameterKey=OpampEndpoint,ParameterValue=wss://app.bindplane.com/v1/opamp \
    ParameterKey=InstanceType,ParameterValue=t3.medium \
  --capabilities CAPABILITY_IAM
```


# BDOT Collector Architecture

Both Fargate and EC2 deployment options include:

* **VPC with Public Subnets** - Network isolation with internet access
* **Security Groups** - Controlled access to collector ports (`4317` and `4318`)
* **CloudWatch Logging** - Centralized logging and monitoring
* **Auto Scaling** - Automatic scaling based on demand

### Key Features

#### Container Configuration

* **BDOT Collector Image**: `ghcr.io/observiq/bindplane-agent`
* **OpAMP Protocol**: Connects to Bindplane Server via OpAMP
* **Automatic Configuration**: Receives configurations from Bindplane Server
* **Persistent Storage**: Maintains manager.yaml configuration

#### Ports and Services

* `4317`: OTLP gRPC receiver
* `4318`: OTLP HTTP receiver

#### Environment Variables

* `OPAMP_ENDPOINT`: Bindplane Server OpAMP endpoint
* `OPAMP_SECRET_KEY`: Collector authentication key
* `OPAMP_LABELS`: Collector labels for identification

### Prerequisites

Before deploying, ensure you have:

1. **AWS CLI v2.x** installed and configured
2. **Valid AWS account** with appropriate permissions
3. **Bindplane Server** running (self-hosted or cloud)
4. **Collector secret key** from your Bindplane Server

### Getting Your Secret Key

1. Navigate to your Bindplane Server UI
2. Go to **Agents** → **Install Agent**
3. Choose **Linux** platform
4. Copy the `secret-key` from the installation instructions

### Configuration

#### OpAMP Endpoint URLs

* **Bindplane Cloud**: `wss://app.bindplane.com/v1/opamp`
* **Self-hosted (HTTP)**: `ws://your-server:3001/v1/opamp`
* **Self-hosted (HTTPS)**: `wss://your-server:443/v1/opamp`

### Monitoring and Troubleshooting

#### CloudWatch Logs

```bash
# View collector logs
aws logs tail /ecs/collector --follow
```

#### Common Issues

1. **Collector not appearing**: Check OpAMP endpoint and secret key
2. **Connection failures**: Verify network connectivity and security groups
3. **High resource usage**: Scale up resources or add more instances

### Scaling

#### Manual Scaling

```bash
# Update desired count
aws ecs update-service \
  --cluster your-cluster \
  --service collector-service \
  --desired-count 3
```

#### Auto Scaling

Both deployment options support Application Auto Scaling for automatic scaling based on CPU/memory utilization.


# Install BDOT Collector in AWS ECS Fargate

Deploy BDOT Collector on AWS ECS Fargate for scalable, serverless collector deployment with automatic scaling and monitoring.

This guide walks you through deploying BDOT Collector on AWS ECS using Fargate launch type. Fargate provides serverless compute for containers, eliminating the need to manage EC2 instances for your collectors.

### Prerequisites

Before starting, ensure you have:

* **AWS CLI v2.x** installed and configured with appropriate permissions
* **Valid AWS account** with permissions to create ECS, VPC, and IAM resources
* **Bindplane Server** running and accessible (self-hosted or cloud)
* **Collector secret key** from your Bindplane Server
* **Basic understanding** of AWS ECS, VPC, and container concepts

### Quick Deployment with CloudFormation

For a quick deployment, you can use the provided CloudFormation template that creates all the necessary infrastructure automatically. This is the recommended approach for most users.

#### CloudFormation Template

The following CloudFormation template creates all the required AWS resources for BDOT Collector on ECS Fargate:

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: 'BDOT Collector on AWS ECS Fargate with VPC and Auto Scaling'

Parameters:
  CollectorSecretKey:
    Type: String
    Description: BDOT Collector secret key from Bindplane Server
    NoEcho: true
  
  OpampEndpoint:
    Type: String
    Description: OpAMP endpoint URL
    Default: 'wss://app.bindplane.com/v1/opamp'
    AllowedPattern: '^(ws|wss)://.*'
  
  CollectorImage:
    Type: String
    Description: BDOT Collector Docker image
    Default: 'ghcr.io/observiq/bindplane-agent:1.84.0'
  
  Environment:
    Type: String
    Description: Environment name (used for resource naming)
    Default: prod
    AllowedValues: [dev, staging, prod]
  
  DesiredCount:
    Type: Number
    Description: Desired number of Bindplane collector instances
    Default: 1
    MinValue: 1
    MaxValue: 10

Resources:
  # VPC and Networking
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsHostnames: true
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-bindplane-collector-vpc'

  # Internet Gateway
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-bindplane-collector-igw'

  InternetGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref VPC

  # Public Subnets
  PublicSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [0, !GetAZs '']
      CidrBlock: 10.0.1.0/24
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-bindplane-collector-public-1a'

  PublicSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [1, !GetAZs '']
      CidrBlock: 10.0.2.0/24
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-bindplane-collector-public-1b'

  # Route Tables
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-bindplane-collector-public-rt'

  DefaultPublicRoute:
    Type: AWS::EC2::Route
    DependsOn: InternetGatewayAttachment
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTable
      SubnetId: !Ref PublicSubnet1

  PublicSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTable
      SubnetId: !Ref PublicSubnet2

  # Security Groups
  CollectorSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for BDOT Collector
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 4317
          ToPort: 4317
          CidrIp: 0.0.0.0/0
          Description: OTLP gRPC
        - IpProtocol: tcp
          FromPort: 4318
          ToPort: 4318
          CidrIp: 0.0.0.0/0
          Description: OTLP HTTP
        - IpProtocol: tcp
          FromPort: 13133
          ToPort: 13133
          CidrIp: 0.0.0.0/0
          Description: Health check
        - IpProtocol: tcp
          FromPort: 55679
          ToPort: 55679
          CidrIp: 0.0.0.0/0
          Description: ZPages debugging
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-bindplane-collector-sg'

  # IAM Roles
  TaskExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: ecs-tasks.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-bindplane-collector-execution-role'

  TaskRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: ecs-tasks.amazonaws.com
            Action: sts:AssumeRole
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-bindplane-collector-task-role'

  # CloudWatch Log Group
  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub '/ecs/${Environment}-bindplane-collector'
      RetentionInDays: 30

  # ECS Cluster
  ECSCluster:
    Type: AWS::ECS::Cluster
    Properties:
      ClusterName: !Sub '${Environment}-bindplane-collector-cluster'
      CapacityProviders:
        - FARGATE
      DefaultCapacityProviderStrategy:
        - CapacityProvider: FARGATE
          Weight: 1

  # ECS Task Definition
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      Family: !Sub '${Environment}-bindplane-collector'
      NetworkMode: awsvpc
      RequiresCompatibilities:
        - FARGATE
      Cpu: 512
      Memory: 1024
      ExecutionRoleArn: !Ref TaskExecutionRole
      TaskRoleArn: !Ref TaskRole
      ContainerDefinitions:
        - Name: bdot-collector
          Image: !Ref CollectorImage
          PortMappings:
            - ContainerPort: 4317
              Protocol: tcp
            - ContainerPort: 4318
              Protocol: tcp
            - ContainerPort: 13133
              Protocol: tcp
            - ContainerPort: 55679
              Protocol: tcp
          Environment:
            - Name: OPAMP_ENDPOINT
              Value: !Ref OpampEndpoint
            - Name: OPAMP_SECRET_KEY
              Value: !Ref CollectorSecretKey
            - Name: OPAMP_LABELS
              Value: !Sub 'environment=${Environment},platform=aws-ecs-fargate'
            - Name: MANAGER_YAML_PATH
              Value: /etc/otel/storage/manager.yaml
          LogConfiguration:
            LogDriver: awslogs
            Options:
              awslogs-group: !Ref LogGroup
              awslogs-region: !Ref AWS::Region
              awslogs-stream-prefix: ecs

  # ECS Service
  ECSService:
    Type: AWS::ECS::Service
    Properties:
      ServiceName: !Sub '${Environment}-bindplane-collector-service'
      Cluster: !Ref ECSCluster
      TaskDefinition: !Ref TaskDefinition
      DesiredCount: !Ref DesiredCount
      LaunchType: FARGATE
      NetworkConfiguration:
        AwsvpcConfiguration:
          Subnets:
            - !Ref PublicSubnet1
            - !Ref PublicSubnet2
          SecurityGroups:
            - !Ref CollectorSecurityGroup
          AssignPublicIp: ENABLED

Outputs:
  VPCId:
    Description: VPC ID
    Value: !Ref VPC
    Export:
      Name: !Sub '${Environment}-bindplane-collector-vpc-id'

  ECSClusterName:
    Description: ECS Cluster Name
    Value: !Ref ECSCluster
    Export:
      Name: !Sub '${Environment}-bindplane-collector-cluster-name'

  ServiceName:
    Description: ECS Service Name
    Value: !Ref ECSService
    Export:
      Name: !Sub '${Environment}-bindplane-collector-service-name'

  TaskDefinitionArn:
    Description: ECS Task Definition ARN
    Value: !Ref TaskDefinition
    Export:
      Name: !Sub '${Environment}-bindplane-collector-task-definition-arn'
```

#### Deploy with CloudFormation

Save the template above as `bindplane-collector-ecs-fargate.yaml` and deploy it:

```bash
aws cloudformation create-stack \
  --stack-name bindplane-collector-ecs-fargate \
  --template-body file://bindplane-collector-ecs-fargate.yaml \
  --parameters \
    ParameterKey=CollectorSecretKey,ParameterValue=YOUR_SECRET_KEY \
    ParameterKey=OpampEndpoint,ParameterValue=wss://app.bindplane.com/v1/opamp \
    ParameterKey=CollectorImage,ParameterValue=ghcr.io/observiq/bindplane-agent:1.84.0 \
    ParameterKey=Environment,ParameterValue=prod \
    ParameterKey=DesiredCount,ParameterValue=1 \
  --capabilities CAPABILITY_IAM
```

### Architecture Overview

The deployment includes:

* **ECS Fargate Cluster**: Serverless compute for BDOT Collector
* **VPC with Public Subnets**: Network isolation with internet access
* **Security Groups**: Controlled access to collector ports
* **CloudWatch**: Monitoring and logging
* **Auto Scaling**: Configurable number of collector instances

#### Container Architecture

The ECS task runs a single container:

**BDOT Collector** (`ghcr.io/observiq/bindplane-agent:1.84.0`)

* OpenTelemetry collector on ports 4317 (gRPC), 4318 (HTTP), 13133 (health), 55679 (ZPages)
* Connects to Bindplane Server via OpAMP protocol
* Automatically receives configurations from Bindplane Server
* Persistent storage for manager.yaml configuration

### Manual Deployment Steps

If you prefer to understand each component or need custom configurations, you can follow the manual deployment steps below.

#### Step 1: Set Up AWS Infrastructure

**Important**: Follow these steps in order, as later steps depend on resources created in earlier steps.

**1.1 Create VPC and Networking**

```bash
# Create VPC
VPC_ID=$(aws ec2 create-vpc \
  --cidr-block 10.0.0.0/16 \
  --tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=bindplane-collector-vpc}]' \
  --query 'Vpc.VpcId' --output text)

# Enable DNS hostnames
aws ec2 modify-vpc-attribute --vpc-id $VPC_ID --enable-dns-hostnames

# Create Internet Gateway
IGW_ID=$(aws ec2 create-internet-gateway \
  --tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=bindplane-collector-igw}]' \
  --query 'InternetGateway.InternetGatewayId' --output text)

# Attach Internet Gateway to VPC
aws ec2 attach-internet-gateway --vpc-id $VPC_ID --internet-gateway-id $IGW_ID

# Get Availability Zones
AZ1=$(aws ec2 describe-availability-zones --query 'AvailabilityZones[0].ZoneName' --output text)
AZ2=$(aws ec2 describe-availability-zones --query 'AvailabilityZones[1].ZoneName' --output text)

# Create Public Subnets
PUBLIC_SUBNET_1=$(aws ec2 create-subnet \
  --vpc-id $VPC_ID \
  --availability-zone $AZ1 \
  --cidr-block 10.0.1.0/24 \
  --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=bindplane-collector-public-1a}]' \
  --query 'Subnet.SubnetId' --output text)

PUBLIC_SUBNET_2=$(aws ec2 create-subnet \
  --vpc-id $VPC_ID \
  --availability-zone $AZ2 \
  --cidr-block 10.0.2.0/24 \
  --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=bindplane-collector-public-1b}]' \
  --query 'Subnet.SubnetId' --output text)

# Enable auto-assign public IP
aws ec2 modify-subnet-attribute --subnet-id $PUBLIC_SUBNET_1 --map-public-ip-on-launch
aws ec2 modify-subnet-attribute --subnet-id $PUBLIC_SUBNET_2 --map-public-ip-on-launch

# Create Route Table
ROUTE_TABLE_ID=$(aws ec2 create-route-table \
  --vpc-id $VPC_ID \
  --tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=bindplane-collector-public-rt}]' \
  --query 'RouteTable.RouteTableId' --output text)

# Create default route
aws ec2 create-route \
  --route-table-id $ROUTE_TABLE_ID \
  --destination-cidr-block 0.0.0.0/0 \
  --gateway-id $IGW_ID

# Associate subnets with route table
aws ec2 associate-route-table --subnet-id $PUBLIC_SUBNET_1 --route-table-id $ROUTE_TABLE_ID
aws ec2 associate-route-table --subnet-id $PUBLIC_SUBNET_2 --route-table-id $ROUTE_TABLE_ID
```

**1.2 Create Security Group**

```bash
# Create Security Group
SECURITY_GROUP_ID=$(aws ec2 create-security-group \
  --group-name bindplane-collector-sg \
  --description "Security group for BDOT Collector" \
  --vpc-id $VPC_ID \
  --query 'GroupId' --output text)

# Allow OTLP gRPC (4317)
aws ec2 authorize-security-group-ingress \
  --group-id $SECURITY_GROUP_ID \
  --protocol tcp \
  --port 4317 \
  --cidr 0.0.0.0/0

# Allow OTLP HTTP (4318)
aws ec2 authorize-security-group-ingress \
  --group-id $SECURITY_GROUP_ID \
  --protocol tcp \
  --port 4318 \
  --cidr 0.0.0.0/0

# Allow Health Check (13133)
aws ec2 authorize-security-group-ingress \
  --group-id $SECURITY_GROUP_ID \
  --protocol tcp \
  --port 13133 \
  --cidr 0.0.0.0/0

# Allow ZPages (55679)
aws ec2 authorize-security-group-ingress \
  --group-id $SECURITY_GROUP_ID \
  --protocol tcp \
  --port 55679 \
  --cidr 0.0.0.0/0
```

#### Step 2: Create ECS Resources

**2.1 Create IAM Roles**

```bash
# Create Task Execution Role
cat > task-execution-role-trust-policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ecs-tasks.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF

TASK_EXECUTION_ROLE_ARN=$(aws iam create-role \
  --role-name bindplane-collector-execution-role \
  --assume-role-policy-document file://task-execution-role-trust-policy.json \
  --query 'Role.Arn' --output text)

# Attach managed policy
aws iam attach-role-policy \
  --role-name bindplane-collector-execution-role \
  --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

# Create Task Role
cat > task-role-trust-policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ecs-tasks.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF

TASK_ROLE_ARN=$(aws iam create-role \
  --role-name bindplane-collector-task-role \
  --assume-role-policy-document file://task-role-trust-policy.json \
  --query 'Role.Arn' --output text)
```

**2.2 Create CloudWatch Log Group**

```bash
# Create Log Group
aws logs create-log-group --log-group-name /ecs/bindplane-collector
```

**2.3 Create ECS Cluster**

```bash
# Create ECS Cluster
CLUSTER_NAME="bindplane-collector-cluster"
aws ecs create-cluster \
  --cluster-name $CLUSTER_NAME \
  --capacity-providers FARGATE \
  --default-capacity-provider-strategy capacityProvider=FARGATE,weight=1
```

#### Step 3: Create Task Definition

```bash
# Create Task Definition
cat > task-definition.json << EOF
{
  "family": "bindplane-collector",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "512",
  "memory": "1024",
  "executionRoleArn": "$TASK_EXECUTION_ROLE_ARN",
  "taskRoleArn": "$TASK_ROLE_ARN",
  "containerDefinitions": [
    {
      "name": "bdot-collector",
      "image": "ghcr.io/observiq/bindplane-agent:1.84.0",
      "portMappings": [
        {
          "containerPort": 4317,
          "protocol": "tcp"
        },
        {
          "containerPort": 4318,
          "protocol": "tcp"
        },
        {
          "containerPort": 13133,
          "protocol": "tcp"
        },
        {
          "containerPort": 55679,
          "protocol": "tcp"
        }
      ],
      "environment": [
        {
          "name": "OPAMP_ENDPOINT",
          "value": "wss://app.bindplane.com/v1/opamp"
        },
        {
          "name": "OPAMP_SECRET_KEY",
          "value": "YOUR_SECRET_KEY"
        },
        {
          "name": "OPAMP_LABELS",
          "value": "environment=prod,platform=aws-ecs-fargate"
        },
        {
          "name": "MANAGER_YAML_PATH",
          "value": "/etc/otel/storage/manager.yaml"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/bindplane-collector",
          "awslogs-region": "$(aws configure get region)",
          "awslogs-stream-prefix": "ecs"
        }
      },
      "healthCheck": {
        "command": [
          "CMD-SHELL",
          "curl -f http://localhost:13133/ || exit 1"
        ],
        "interval": 30,
        "timeout": 5,
        "retries": 3,
        "startPeriod": 60
      }
    }
  ]
}
EOF

TASK_DEFINITION_ARN=$(aws ecs register-task-definition \
  --cli-input-json file://task-definition.json \
  --query 'taskDefinition.taskDefinitionArn' --output text)
```

#### Step 4: Create ECS Service

```bash
# Create ECS Service
aws ecs create-service \
  --cluster $CLUSTER_NAME \
  --service-name bindplane-collector-service \
  --task-definition $TASK_DEFINITION_ARN \
  --desired-count 1 \
  --launch-type FARGATE \
  --network-configuration "awsvpcConfiguration={subnets=[$PUBLIC_SUBNET_1,$PUBLIC_SUBNET_2],securityGroups=[$SECURITY_GROUP_ID],assignPublicIp=ENABLED}"
```

### Configuration and Management

#### Connecting to Bindplane Server

1. **Get your collector secret key** from your Bindplane Server:
   * Navigate to **Agents** → **Install Agent**
   * Choose **Linux** platform
   * Copy the `secret-key`
2. **Update the OpAMP endpoint** in your task definition:
   * For Bindplane Cloud: `wss://app.bindplane.com/v1/opamp`
   * For self-hosted: `ws://your-server:3001/v1/opamp` (or `wss://` with TLS)
3. **Update the task definition** with your secret key:

   ```bash
   # Update the environment variable in task-definition.json
   # Replace "YOUR_SECRET_KEY" with your actual secret key
   ```

#### Scaling Collectors

**Manual Scaling**

```bash
# Update desired count
aws ecs update-service \
  --cluster $CLUSTER_NAME \
  --service bindplane-collector-service \
  --desired-count 3
```

**Auto Scaling with Application Auto Scaling**

```bash
# Register scalable target
aws application-autoscaling register-scalable-target \
  --service-namespace ecs \
  --resource-id service/$CLUSTER_NAME/bindplane-collector-service \
  --scalable-dimension ecs:service:DesiredCount \
  --min-capacity 1 \
  --max-capacity 10

# Create scaling policy
aws application-autoscaling put-scaling-policy \
  --service-namespace ecs \
  --resource-id service/$CLUSTER_NAME/bindplane-collector-service \
  --scalable-dimension ecs:service:DesiredCount \
  --policy-name collector-cpu-scaling \
  --policy-type TargetTrackingScaling \
  --target-tracking-scaling-policy-configuration '{
    "TargetValue": 70.0,
    "PredefinedMetricSpecification": {
      "PredefinedMetricType": "ECSServiceAverageCPUUtilization"
    }
  }'
```

#### Monitoring and Logging

**CloudWatch Logs**

```bash
# View logs
aws logs tail /ecs/bindplane-collector --follow

# Filter logs by container
aws logs filter-log-events \
  --log-group-name /ecs/bindplane-collector \
  --log-stream-name-prefix ecs/bdot-collector
```

**CloudWatch Metrics**

The ECS service automatically sends metrics to CloudWatch:

* CPU and Memory utilization
* Task count and health
* Network I/O

**Health Checks**

The collector includes health checks on port 13133:

* **Health endpoint**: `http://localhost:13133/`
* **ZPages debugging**: `http://localhost:55679/`

#### TLS Configuration

**For Self-Hosted Bindplane with TLS**

If your Bindplane Server uses TLS with a custom CA:

```bash
# Create a secret for the CA certificate
aws secretsmanager create-secret \
  --name collector-ca-cert \
  --secret-string file://ca.crt

# Update task role to access the secret
cat > task-role-policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "secretsmanager:GetSecretValue"
      ],
      "Resource": "arn:aws:secretsmanager:*:*:secret:collector-ca-cert*"
    }
  ]
}
EOF

aws iam put-role-policy \
  --role-name collector-task-role \
  --policy-name SecretsManagerAccess \
  --policy-document file://task-role-policy.json
```

Then update your task definition to include:

```json
{
  "name": "OPAMP_TLS_CA",
  "value": "/etc/otel/certs/ca.crt"
}
```

### Troubleshooting

#### Common Issues

**Collector Not Appearing in Bindplane**

1. **Check OpAMP endpoint**: Ensure the endpoint URL is correct
2. **Verify secret key**: Make sure the secret key matches your Bindplane Server
3. **Check network connectivity**: Ensure the collector can reach the Bindplane Server
4. **Review logs**: Check CloudWatch logs for connection errors

```bash
# Check service status
aws ecs describe-services \
  --cluster $CLUSTER_NAME \
  --services bindplane-collector-service

# Check task logs
aws logs tail /ecs/bindplane-collector --follow
```

**High CPU/Memory Usage**

1. **Scale up resources**: Increase CPU/memory in task definition
2. **Scale out**: Add more collector instances
3. **Optimize configuration**: Review collector configuration for efficiency

**Network Issues**

1. **Check security groups**: Ensure all required ports are open
2. **Verify VPC configuration**: Ensure subnets have internet access
3. **Test connectivity**: Use VPC endpoints if needed

#### Best Practices

1. **Resource Sizing**: Start with 512 CPU / 1024 Memory, adjust based on load
2. **Scaling**: Use Application Auto Scaling for automatic scaling
3. **Monitoring**: Set up CloudWatch alarms for key metrics
4. **Security**: Use IAM roles with minimal required permissions
5. **Logging**: Enable detailed logging for troubleshooting
6. **Updates**: Regularly update collector image versions

### Cleanup

To remove all resources created by this guide:

```bash
# Delete ECS Service
aws ecs update-service \
  --cluster $CLUSTER_NAME \
  --service bindplane-collector-service \
  --desired-count 0

aws ecs delete-service \
  --cluster $CLUSTER_NAME \
  --service bindplane-collector-service

# Delete Task Definition
aws ecs deregister-task-definition \
  --task-definition $TASK_DEFINITION_ARN

# Delete ECS Cluster
aws ecs delete-cluster --cluster $CLUSTER_NAME

# Delete CloudWatch Log Group
aws logs delete-log-group --log-group-name /ecs/bindplane-collector

# Delete IAM Roles
aws iam detach-role-policy \
  --role-name bindplane-collector-execution-role \
  --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

aws iam delete-role --role-name bindplane-collector-execution-role
aws iam delete-role --role-name bindplane-collector-task-role

# Delete Security Group
aws ec2 delete-security-group --group-id $SECURITY_GROUP_ID

# Delete Subnets
aws ec2 delete-subnet --subnet-id $PUBLIC_SUBNET_1
aws ec2 delete-subnet --subnet-id $PUBLIC_SUBNET_2

# Delete Route Table
aws ec2 delete-route-table --route-table-id $ROUTE_TABLE_ID

# Detach and Delete Internet Gateway
aws ec2 detach-internet-gateway --vpc-id $VPC_ID --internet-gateway-id $IGW_ID
aws ec2 delete-internet-gateway --internet-gateway-id $IGW_ID

# Delete VPC
aws ec2 delete-vpc --vpc-id $VPC_ID
```

### Next Steps

After successfully deploying your BDOT Collector:

1. **Verify connection** in your Bindplane Server UI
2. **Create configurations** for your collectors
3. **Set up monitoring** and alerting
4. **Configure auto-scaling** based on your needs
5. **Review security** settings and access controls


# Install BDOT Collector in AWS ECS EC2

Deploy BDOT Collector on AWS ECS EC2 for cost-effective, scalable collector deployment with full control over underlying infrastructure.

This guide walks you through deploying BDOT Collector on AWS ECS using EC2 launch type. EC2 provides full control over the underlying infrastructure and can be more cost-effective for consistent workloads.

### Prerequisites

Before starting, ensure you have:

* **AWS CLI v2.x** installed and configured with appropriate permissions
* **Valid AWS account** with permissions to create ECS, VPC, and IAM resources
* **Bindplane Server** running and accessible (self-hosted or cloud)
* **Collector secret key** from your Bindplane Server
* **Basic understanding** of AWS ECS, VPC, and container concepts

### Quick Deployment with CloudFormation

For a quick deployment, you can use the provided CloudFormation template that creates all the necessary infrastructure automatically. This is the recommended approach for most users.

#### CloudFormation Template

The following CloudFormation template creates all the required AWS resources for BDOT Collector on ECS EC2:

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: 'BDOT Collector on AWS ECS EC2 with Auto Scaling and VPC'

Parameters:
  CollectorSecretKey:
    Type: String
    Description: BDOT Collector secret key from Bindplane Server
    NoEcho: true
  
  OpampEndpoint:
    Type: String
    Description: OpAMP endpoint URL
    Default: 'wss://app.bindplane.com/v1/opamp'
    AllowedPattern: '^(ws|wss)://.*'
  
  CollectorImage:
    Type: String
    Description: BDOT Collector Docker image
    Default: 'ghcr.io/observiq/bindplane-agent:1.84.0'
  
  Environment:
    Type: String
    Description: Environment name (used for resource naming)
    Default: prod
    AllowedValues: [dev, staging, prod]
  
  InstanceType:
    Type: String
    Description: EC2 instance type for ECS cluster
    Default: t3.medium
    AllowedValues: [t3.small, t3.medium, t3.large, t3.xlarge, m5.large, m5.xlarge]
  
  MinSize:
    Type: Number
    Description: Minimum number of EC2 instances
    Default: 1
    MinValue: 1
    MaxValue: 10
  
  MaxSize:
    Type: Number
    Description: Maximum number of EC2 instances
    Default: 5
    MinValue: 1
    MaxValue: 20
  
  DesiredCapacity:
    Type: Number
    Description: Desired number of EC2 instances
    Default: 2
    MinValue: 1
    MaxValue: 10

Resources:
  # VPC and Networking
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsHostnames: true
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-bindplane-collector-vpc'

  # Internet Gateway
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-bindplane-collector-igw'

  InternetGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref VPC

  # Public Subnets
  PublicSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [0, !GetAZs '']
      CidrBlock: 10.0.1.0/24
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-bindplane-collector-public-1a'

  PublicSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [1, !GetAZs '']
      CidrBlock: 10.0.2.0/24
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-bindplane-collector-public-1b'

  # Route Tables
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-bindplane-collector-public-rt'

  DefaultPublicRoute:
    Type: AWS::EC2::Route
    DependsOn: InternetGatewayAttachment
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTable
      SubnetId: !Ref PublicSubnet1

  PublicSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTable
      SubnetId: !Ref PublicSubnet2

  # Security Groups
  CollectorSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for BDOT Collector
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 4317
          ToPort: 4317
          CidrIp: 0.0.0.0/0
          Description: OTLP gRPC
        - IpProtocol: tcp
          FromPort: 4318
          ToPort: 4318
          CidrIp: 0.0.0.0/0
          Description: OTLP HTTP
        - IpProtocol: tcp
          FromPort: 13133
          ToPort: 13133
          CidrIp: 0.0.0.0/0
          Description: Health check
        - IpProtocol: tcp
          FromPort: 55679
          ToPort: 55679
          CidrIp: 0.0.0.0/0
          Description: ZPages debugging
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
          Description: SSH access
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-bindplane-collector-sg'

  # IAM Roles
  TaskExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: ecs-tasks.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-bindplane-collector-execution-role'

  TaskRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: ecs-tasks.amazonaws.com
            Action: sts:AssumeRole
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-bindplane-collector-task-role'

  ECSInstanceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-bindplane-collector-instance-role'

  ECSInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Roles:
        - !Ref ECSInstanceRole

  # CloudWatch Log Group
  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub '/ecs/${Environment}-bindplane-collector'
      RetentionInDays: 30

  # ECS Cluster
  ECSCluster:
    Type: AWS::ECS::Cluster
    Properties:
      ClusterName: !Sub '${Environment}-bindplane-collector-cluster'

  # Launch Template
  LaunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    DependsOn: ECSInstanceProfile
    Properties:
      LaunchTemplateName: !Sub '${Environment}-bindplane-collector-lt'
      LaunchTemplateData:
        ImageId: !Sub '{{resolve:ssm:/aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id}}'
        InstanceType: !Ref InstanceType
        IamInstanceProfile:
          Arn: !GetAtt ECSInstanceProfile.Arn
        SecurityGroupIds:
          - !Ref CollectorSecurityGroup
        UserData:
          Fn::Base64: !Sub |
            #!/bin/bash
            echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config
            echo ECS_ENABLE_TASK_ENI=true >> /etc/ecs/ecs.config
        BlockDeviceMappings:
          - DeviceName: /dev/xvda
            Ebs:
              VolumeSize: 30
              VolumeType: gp3

  # Auto Scaling Group
  AutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    DependsOn: LaunchTemplate
    Properties:
      AutoScalingGroupName: !Sub '${Environment}-bindplane-collector-asg'
      LaunchTemplate:
        LaunchTemplateId: !Ref LaunchTemplate
        Version: !GetAtt LaunchTemplate.LatestVersionNumber
      MinSize: !Ref MinSize
      MaxSize: !Ref MaxSize
      DesiredCapacity: !Ref DesiredCapacity
      VPCZoneIdentifier:
        - !Ref PublicSubnet1
        - !Ref PublicSubnet2
      HealthCheckType: EC2
      HealthCheckGracePeriod: 300
      Tags:
        - Key: Name
          Value: !Sub '${Environment}-bindplane-collector-instance'
          PropagateAtLaunch: true

  # ECS Task Definition
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      Family: !Sub '${Environment}-bindplane-collector'
      NetworkMode: host
      RequiresCompatibilities:
        - EC2
      Cpu: 512
      Memory: 1024
      ExecutionRoleArn: !Ref TaskExecutionRole
      TaskRoleArn: !Ref TaskRole
      ContainerDefinitions:
        - Name: bdot-collector
          Image: !Ref CollectorImage
          PortMappings:
            - ContainerPort: 4317
              Protocol: tcp
            - ContainerPort: 4318
              Protocol: tcp
            - ContainerPort: 13133
              Protocol: tcp
            - ContainerPort: 55679
              Protocol: tcp
          Environment:
            - Name: OPAMP_ENDPOINT
              Value: !Ref OpampEndpoint
            - Name: OPAMP_SECRET_KEY
              Value: !Ref CollectorSecretKey
            - Name: OPAMP_LABELS
              Value: !Sub 'environment=${Environment},platform=aws-ecs-ec2'
            - Name: MANAGER_YAML_PATH
              Value: /etc/otel/storage/manager.yaml
          LogConfiguration:
            LogDriver: awslogs
            Options:
              awslogs-group: !Ref LogGroup
              awslogs-region: !Ref AWS::Region
              awslogs-stream-prefix: ecs

  # ECS Service
  ECSService:
    Type: AWS::ECS::Service
    Properties:
      ServiceName: !Sub '${Environment}-bindplane-collector-service'
      Cluster: !Ref ECSCluster
      TaskDefinition: !Ref TaskDefinition
      DesiredCount: !Ref DesiredCapacity
      LaunchType: EC2

Outputs:
  VPCId:
    Description: VPC ID
    Value: !Ref VPC
    Export:
      Name: !Sub '${Environment}-bindplane-collector-vpc-id'

  ECSClusterName:
    Description: ECS Cluster Name
    Value: !Ref ECSCluster
    Export:
      Name: !Sub '${Environment}-bindplane-collector-cluster-name'

  ServiceName:
    Description: ECS Service Name
    Value: !Ref ECSService
    Export:
      Name: !Sub '${Environment}-bindplane-collector-service-name'

  TaskDefinitionArn:
    Description: ECS Task Definition ARN
    Value: !Ref TaskDefinition
    Export:
      Name: !Sub '${Environment}-bindplane-collector-task-definition-arn'

  AutoScalingGroupName:
    Description: Auto Scaling Group Name
    Value: !Ref AutoScalingGroup
    Export:
      Name: !Sub '${Environment}-bindplane-collector-asg-name'
```

#### Deploy with CloudFormation

Save the template above as `bindplane-collector-ecs-ec2.yaml` and deploy it:

```bash
aws cloudformation create-stack \
  --stack-name bindplane-collector-ecs-ec2 \
  --template-body file://bindplane-collector-ecs-ec2.yaml \
  --parameters \
    ParameterKey=CollectorSecretKey,ParameterValue=YOUR_SECRET_KEY \
    ParameterKey=OpampEndpoint,ParameterValue=wss://app.bindplane.com/v1/opamp \
    ParameterKey=CollectorImage,ParameterValue=ghcr.io/observiq/bindplane-agent:1.84.0 \
    ParameterKey=Environment,ParameterValue=prod \
    ParameterKey=InstanceType,ParameterValue=t3.medium \
    ParameterKey=MinSize,ParameterValue=1 \
    ParameterKey=MaxSize,ParameterValue=5 \
    ParameterKey=DesiredCapacity,ParameterValue=2 \
  --capabilities CAPABILITY_IAM
```

### Architecture Overview

The deployment includes:

* **ECS EC2 Cluster**: Managed EC2 instances running BDOT Collector
* **Auto Scaling Group**: Manages EC2 instances for the cluster
* **VPC with Public Subnets**: Network isolation with internet access
* **Host Networking**: Containers use EC2 instance's network interface directly
* **Security Groups**: Controlled access to collector ports
* **CloudWatch**: Monitoring and logging
* **Auto Scaling**: Configurable number of collector instances

#### Container Architecture

The ECS task runs a single container:

**BDOT Collector** (`ghcr.io/observiq/bindplane-agent:1.84.0`)

* OpenTelemetry collector on ports 4317 (gRPC), 4318 (HTTP), 13133 (health), 55679 (ZPages)
* Connects to Bindplane Server via OpAMP protocol
* Automatically receives configurations from Bindplane Server
* Persistent storage for manager.yaml configuration

### Manual Deployment Steps

If you prefer to understand each component or need custom configurations, you can follow the manual deployment steps below.

#### Step 1: Set Up AWS Infrastructure

**Important**: Follow these steps in order, as later steps depend on resources created in earlier steps.

**1.1 Create VPC and Networking**

```bash
# Create VPC
VPC_ID=$(aws ec2 create-vpc \
  --cidr-block 10.0.0.0/16 \
  --tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=bindplane-collector-vpc}]' \
  --query 'Vpc.VpcId' --output text)

# Enable DNS hostnames
aws ec2 modify-vpc-attribute --vpc-id $VPC_ID --enable-dns-hostnames

# Create Internet Gateway
IGW_ID=$(aws ec2 create-internet-gateway \
  --tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=bindplane-collector-igw}]' \
  --query 'InternetGateway.InternetGatewayId' --output text)

# Attach Internet Gateway to VPC
aws ec2 attach-internet-gateway --vpc-id $VPC_ID --internet-gateway-id $IGW_ID

# Get Availability Zones
AZ1=$(aws ec2 describe-availability-zones --query 'AvailabilityZones[0].ZoneName' --output text)
AZ2=$(aws ec2 describe-availability-zones --query 'AvailabilityZones[1].ZoneName' --output text)

# Create Public Subnets
PUBLIC_SUBNET_1=$(aws ec2 create-subnet \
  --vpc-id $VPC_ID \
  --availability-zone $AZ1 \
  --cidr-block 10.0.1.0/24 \
  --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=bindplane-collector-public-1a}]' \
  --query 'Subnet.SubnetId' --output text)

PUBLIC_SUBNET_2=$(aws ec2 create-subnet \
  --vpc-id $VPC_ID \
  --availability-zone $AZ2 \
  --cidr-block 10.0.2.0/24 \
  --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=bindplane-collector-public-1b}]' \
  --query 'Subnet.SubnetId' --output text)

# Enable auto-assign public IP
aws ec2 modify-subnet-attribute --subnet-id $PUBLIC_SUBNET_1 --map-public-ip-on-launch
aws ec2 modify-subnet-attribute --subnet-id $PUBLIC_SUBNET_2 --map-public-ip-on-launch

# Create Route Table
ROUTE_TABLE_ID=$(aws ec2 create-route-table \
  --vpc-id $VPC_ID \
  --tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=bindplane-collector-public-rt}]' \
  --query 'RouteTable.RouteTableId' --output text)

# Create default route
aws ec2 create-route \
  --route-table-id $ROUTE_TABLE_ID \
  --destination-cidr-block 0.0.0.0/0 \
  --gateway-id $IGW_ID

# Associate subnets with route table
aws ec2 associate-route-table --subnet-id $PUBLIC_SUBNET_1 --route-table-id $ROUTE_TABLE_ID
aws ec2 associate-route-table --subnet-id $PUBLIC_SUBNET_2 --route-table-id $ROUTE_TABLE_ID
```

**1.2 Create Security Group**

```bash
# Create Security Group
SECURITY_GROUP_ID=$(aws ec2 create-security-group \
  --group-name bindplane-collector-sg \
  --description "Security group for BDOT Collector" \
  --vpc-id $VPC_ID \
  --query 'GroupId' --output text)

# Allow OTLP gRPC (4317)
aws ec2 authorize-security-group-ingress \
  --group-id $SECURITY_GROUP_ID \
  --protocol tcp \
  --port 4317 \
  --cidr 0.0.0.0/0

# Allow OTLP HTTP (4318)
aws ec2 authorize-security-group-ingress \
  --group-id $SECURITY_GROUP_ID \
  --protocol tcp \
  --port 4318 \
  --cidr 0.0.0.0/0

# Allow Health Check (13133)
aws ec2 authorize-security-group-ingress \
  --group-id $SECURITY_GROUP_ID \
  --protocol tcp \
  --port 13133 \
  --cidr 0.0.0.0/0

# Allow ZPages (55679)
aws ec2 authorize-security-group-ingress \
  --group-id $SECURITY_GROUP_ID \
  --protocol tcp \
  --port 55679 \
  --cidr 0.0.0.0/0

# Allow SSH (22) - optional, for debugging
aws ec2 authorize-security-group-ingress \
  --group-id $SECURITY_GROUP_ID \
  --protocol tcp \
  --port 22 \
  --cidr 0.0.0.0/0
```

#### Step 2: Create ECS Resources

**2.1 Create IAM Roles**

```bash
# Create Task Execution Role
cat > task-execution-role-trust-policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ecs-tasks.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF

TASK_EXECUTION_ROLE_ARN=$(aws iam create-role \
  --role-name bindplane-collector-execution-role \
  --assume-role-policy-document file://task-execution-role-trust-policy.json \
  --query 'Role.Arn' --output text)

# Attach managed policy
aws iam attach-role-policy \
  --role-name bindplane-collector-execution-role \
  --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

# Create Task Role
cat > task-role-trust-policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ecs-tasks.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF

TASK_ROLE_ARN=$(aws iam create-role \
  --role-name bindplane-collector-task-role \
  --assume-role-policy-document file://task-role-trust-policy.json \
  --query 'Role.Arn' --output text)

# Create ECS Instance Role
cat > ecs-instance-role-trust-policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF

ECS_INSTANCE_ROLE_ARN=$(aws iam create-role \
  --role-name bindplane-collector-instance-role \
  --assume-role-policy-document file://ecs-instance-role-trust-policy.json \
  --query 'Role.Arn' --output text)

# Attach managed policy
aws iam attach-role-policy \
  --role-name bindplane-collector-instance-role \
  --policy-arn arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role

# Create Instance Profile
INSTANCE_PROFILE_ARN=$(aws iam create-instance-profile \
  --instance-profile-name bindplane-collector-instance-profile \
  --query 'InstanceProfile.Arn' --output text)

aws iam add-role-to-instance-profile \
  --instance-profile-name bindplane-collector-instance-profile \
  --role-name bindplane-collector-instance-role
```

**2.2 Create CloudWatch Log Group**

```bash
# Create Log Group
aws logs create-log-group --log-group-name /ecs/bindplane-collector
```

**2.3 Create ECS Cluster**

```bash
# Create ECS Cluster
CLUSTER_NAME="bindplane-collector-cluster"
aws ecs create-cluster --cluster-name $CLUSTER_NAME
```

#### Step 3: Create Launch Template and Auto Scaling Group

**3.1 Get Latest ECS-Optimized AMI**

```bash
# Get latest ECS-optimized AMI ID
AMI_ID=$(aws ssm get-parameters \
  --names /aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id \
  --query 'Parameters[0].Value' --output text)
```

**3.2 Create Launch Template**

```bash
# Create Launch Template
cat > launch-template-data.json << EOF
{
  "ImageId": "$AMI_ID",
  "InstanceType": "t3.medium",
  "IamInstanceProfile": {
    "Arn": "$INSTANCE_PROFILE_ARN"
  },
  "SecurityGroupIds": ["$SECURITY_GROUP_ID"],
  "UserData": "$(echo '#!/bin/bash\necho ECS_CLUSTER=bindplane-collector-cluster >> /etc/ecs/ecs.config\necho ECS_ENABLE_TASK_ENI=true >> /etc/ecs/ecs.config' | base64 -w 0)",
  "BlockDeviceMappings": [
    {
      "DeviceName": "/dev/xvda",
      "Ebs": {
        "VolumeSize": 30,
        "VolumeType": "gp3"
      }
    }
  ]
}
EOF

LAUNCH_TEMPLATE_ID=$(aws ec2 create-launch-template \
  --launch-template-name bindplane-collector-lt \
  --launch-template-data file://launch-template-data.json \
  --query 'LaunchTemplate.LaunchTemplateId' --output text)
```

**3.3 Create Auto Scaling Group**

```bash
# Create Auto Scaling Group
aws autoscaling create-auto-scaling-group \
  --auto-scaling-group-name bindplane-collector-asg \
  --launch-template LaunchTemplateId=$LAUNCH_TEMPLATE_ID,Version='$Latest' \
  --min-size 1 \
  --max-size 5 \
  --desired-capacity 2 \
  --vpc-zone-identifier "$PUBLIC_SUBNET_1,$PUBLIC_SUBNET_2" \
  --health-check-type EC2 \
  --health-check-grace-period 300
```

#### Step 4: Create Task Definition

```bash
# Create Task Definition
cat > task-definition.json << EOF
{
  "family": "bindplane-collector",
  "networkMode": "host",
  "requiresCompatibilities": ["EC2"],
  "cpu": "512",
  "memory": "1024",
  "executionRoleArn": "$TASK_EXECUTION_ROLE_ARN",
  "taskRoleArn": "$TASK_ROLE_ARN",
  "containerDefinitions": [
    {
      "name": "bdot-collector",
      "image": "ghcr.io/observiq/bindplane-agent:1.84.0",
      "portMappings": [
        {
          "containerPort": 4317,
          "protocol": "tcp"
        },
        {
          "containerPort": 4318,
          "protocol": "tcp"
        },
        {
          "containerPort": 13133,
          "protocol": "tcp"
        },
        {
          "containerPort": 55679,
          "protocol": "tcp"
        }
      ],
      "environment": [
        {
          "name": "OPAMP_ENDPOINT",
          "value": "wss://app.bindplane.com/v1/opamp"
        },
        {
          "name": "OPAMP_SECRET_KEY",
          "value": "YOUR_SECRET_KEY"
        },
        {
          "name": "OPAMP_LABELS",
          "value": "environment=prod,platform=aws-ecs-ec2"
        },
        {
          "name": "MANAGER_YAML_PATH",
          "value": "/etc/otel/storage/manager.yaml"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/bindplane-collector",
          "awslogs-region": "$(aws configure get region)",
          "awslogs-stream-prefix": "ecs"
        }
      },
      "healthCheck": {
        "command": [
          "CMD-SHELL",
          "curl -f http://localhost:13133/ || exit 1"
        ],
        "interval": 30,
        "timeout": 5,
        "retries": 3,
        "startPeriod": 60
      }
    }
  ]
}
EOF

TASK_DEFINITION_ARN=$(aws ecs register-task-definition \
  --cli-input-json file://task-definition.json \
  --query 'taskDefinition.taskDefinitionArn' --output text)
```

#### Step 5: Create ECS Service

```bash
# Create ECS Service
aws ecs create-service \
  --cluster $CLUSTER_NAME \
  --service-name bindplane-collector-service \
  --task-definition $TASK_DEFINITION_ARN \
  --desired-count 2 \
  --launch-type EC2
```

### Configuration and Management

#### Connecting to Bindplane Server

1. **Get your collector secret key** from your Bindplane Server:
   * Navigate to **Agents** → **Install Agent**
   * Choose **Linux** platform
   * Copy the `secret-key`
2. **Update the OpAMP endpoint** in your task definition:
   * For Bindplane Cloud: `wss://app.bindplane.com/v1/opamp`
   * For self-hosted: `ws://your-server:3001/v1/opamp` (or `wss://` with TLS)
3. **Update the task definition** with your secret key:

   ```bash
   # Update the environment variable in task-definition.json
   # Replace "YOUR_SECRET_KEY" with your actual secret key
   ```

#### Scaling Collectors

**Manual Scaling**

```bash
# Update desired count
aws ecs update-service \
  --cluster $CLUSTER_NAME \
  --service bindplane-collector-service \
  --desired-count 3
```

**Auto Scaling with Application Auto Scaling**

```bash
# Register scalable target
aws application-autoscaling register-scalable-target \
  --service-namespace ecs \
  --resource-id service/$CLUSTER_NAME/bindplane-collector-service \
  --scalable-dimension ecs:service:DesiredCount \
  --min-capacity 1 \
  --max-capacity 10

# Create scaling policy
aws application-autoscaling put-scaling-policy \
  --service-namespace ecs \
  --resource-id service/$CLUSTER_NAME/bindplane-collector-service \
  --scalable-dimension ecs:service:DesiredCount \
  --policy-name collector-cpu-scaling \
  --policy-type TargetTrackingScaling \
  --target-tracking-scaling-policy-configuration '{
    "TargetValue": 70.0,
    "PredefinedMetricSpecification": {
      "PredefinedMetricType": "ECSServiceAverageCPUUtilization"
    }
  }'
```

#### Monitoring and Logging

**CloudWatch Logs**

```bash
# View logs
aws logs tail /ecs/bindplane-collector --follow

# Filter logs by container
aws logs filter-log-events \
  --log-group-name /ecs/bindplane-collector \
  --log-stream-name-prefix ecs/bdot-collector
```

**CloudWatch Metrics**

The ECS service automatically sends metrics to CloudWatch:

* CPU and Memory utilization
* Task count and health
* Network I/O

**Health Checks**

The collector includes health checks on port 13133:

* **Health endpoint**: `http://localhost:13133/`
* **ZPages debugging**: `http://localhost:55679/`

#### TLS Configuration

**For Self-Hosted Bindplane with TLS**

If your Bindplane Server uses TLS with a custom CA:

```bash
# Create a secret for the CA certificate
aws secretsmanager create-secret \
  --name collector-ca-cert \
  --secret-string file://ca.crt

# Update task role to access the secret
cat > task-role-policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "secretsmanager:GetSecretValue"
      ],
      "Resource": "arn:aws:secretsmanager:*:*:secret:collector-ca-cert*"
    }
  ]
}
EOF

aws iam put-role-policy \
  --role-name collector-task-role \
  --policy-name SecretsManagerAccess \
  --policy-document file://task-role-policy.json
```

Then update your task definition to include:

```json
{
  "name": "OPAMP_TLS_CA",
  "value": "/etc/otel/certs/ca.crt"
}
```

### Troubleshooting

#### Common Issues

**Collector Not Appearing in Bindplane**

1. **Check OpAMP endpoint**: Ensure the endpoint URL is correct
2. **Verify secret key**: Make sure the secret key matches your Bindplane Server
3. **Check network connectivity**: Ensure the collector can reach the Bindplane Server
4. **Review logs**: Check CloudWatch logs for connection errors

```bash
# Check service status
aws ecs describe-services \
  --cluster $CLUSTER_NAME \
  --services bindplane-collector-service

# Check task logs
aws logs tail /ecs/bindplane-collector --follow
```

**High CPU/Memory Usage**

1. **Scale up resources**: Increase CPU/memory in task definition
2. **Scale out**: Add more collector instances
3. **Optimize configuration**: Review collector configuration for efficiency

#### Best Practices

1. **Resource Sizing**: Start with 512 CPU / 1024 Memory, adjust based on load
2. **Scaling**: Use Application Auto Scaling for automatic scaling
3. **Monitoring**: Set up CloudWatch alarms for key metrics
4. **Security**: Use IAM roles with minimal required permissions
5. **Logging**: Enable detailed logging for troubleshooting
6. **Updates**: Regularly update collector image versions

### Cleanup

To remove all resources created by this guide:

```bash
# Delete ECS Service
aws ecs update-service \
  --cluster $CLUSTER_NAME \
  --service bindplane-collector-service \
  --desired-count 0

aws ecs delete-service \
  --cluster $CLUSTER_NAME \
  --service bindplane-collector-service


# Delete Task Definition
aws ecs deregister-task-definition \
  --task-definition $TASK_DEFINITION_ARN

# Delete ECS Cluster
aws ecs delete-cluster --cluster $CLUSTER_NAME

# Delete CloudWatch Log Group
aws logs delete-log-group --log-group-name /ecs/bindplane-collector

# Delete IAM Roles
aws iam detach-role-policy \
  --role-name bindplane-collector-execution-role \
  --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

aws iam delete-role --role-name bindplane-collector-execution-role
aws iam delete-role --role-name bindplane-collector-task-role

# Delete Security Group
aws ec2 delete-security-group --group-id $SECURITY_GROUP_ID

# Delete Subnets
aws ec2 delete-subnet --subnet-id $PUBLIC_SUBNET_1
aws ec2 delete-subnet --subnet-id $PUBLIC_SUBNET_2

# Delete Route Table
aws ec2 delete-route-table --route-table-id $ROUTE_TABLE_ID

# Detach and Delete Internet Gateway
aws ec2 detach-internet-gateway --vpc-id $VPC_ID --internet-gateway-id $IGW_ID
aws ec2 delete-internet-gateway --internet-gateway-id $IGW_ID

# Delete VPC
aws ec2 delete-vpc --vpc-id $VPC_ID
```

### Next Steps

After successfully deploying your BDOT Collector:

1. **Verify connection** in your Bindplane Server UI
2. **Create configurations** for your collectors
3. **Set up monitoring** and alerting
4. **Configure auto-scaling** based on your needs
5. **Review security** settings and access controls


# Google Marketplace

Bindplane Enterprise Edition can be deployed from the Google Marketplace

This guide will walk you through deploying Bindplane Enterprise on a GCE instance using the Google Cloud Deployment Manager.

## Deploying and Configuring Bindplane Enterprise

Navigate to Bindplane Enterprise offering in the Google Marketplace [here](https://console.cloud.google.com/marketplace/product/bluemedora/bindplane-enterprise-edition). From the Overview tab, click ‘Launch’ to start configuring your deployment.

{% hint style="info" %}
**NOTE**

Bindplane Enterprise requires an Enterprise license. Contact the [sales team](mailto:sales@bindplane.com) for more information.
{% endhint %}

### Configure your Deployment

From the New Bindplane Enterprise deployment page, provide a friendly Deployment name. Modify any other settings as needed. The license key recommended but not required. After the deployment is created, you will need to configure the license key on the instance if not provided here.

<figure><img src="/files/hk6bZPbzpgIY8jBpEs1j" alt="Bindplane docs - Google Marketplace Deployments - image 1"><figcaption></figcaption></figure>

### Deploy the Bindplane Enterprise Image

Deploy the image with the deploy button. This will kick off the deployment using Terraform, automatically within Google Cloud Marketplace. A typical Bindplane Enterprise deployment takes about 5 minutes.

<figure><img src="/files/96axTvoHPq0whB6weYCu" alt="Bindplane docs - Google Marketplace Deployments - image 2"><figcaption></figcaption></figure>

### Accessing Bindplane Enterprise

* **License Configuration**: If a license was not provided during deployment, SSH into the machine and execute the following command:\
  `sudo BINDPLANE_CONFIG_HOME=/var/lib/bindplane /usr/local/bin/bindplane init license --config /etc/bindplane/config.yaml`.\
  Confirm the restart prompt by selecting 'yes' at the end of the command.
* **Service Management**: For those who have already provided a license, enable and start the Bindplane service via SSH with these commands:\
  `sudo systemctl enable bindplane`\
  `sudo systemctl start bindplane`
* **Firewall Settings**: To enhance security, adjust the firewall rules by navigating to VPC Network and selecting Firewall.
* **Password Retrieval**: Access the password by checking the `auth.password` field in the `/etc/bindplane/config.yaml` file.
* **Web Interface Access**: Log into the Bindplane web interface by entering the instance's public IP address followed by port 3001 in your browser. Use the username `admin` and the password obtained from the configuration file.

After completing these steps, the Bindplane interface will be accessible with the configured ports. For further instructions, proceed with our Quickstart guide, starting at [Step 2 for Accessing the Bindplane UI](/readme/access-bindplane-ui).


# Ansible

Install and manage Bindplane Collectors at scale with an Ansible Role, integrated directly into your playbooks for automated deployment.

## Quick Start

1. [Bindplane Collector Ansible Role](/deployment/ansible/bindplane-otel-collector) - Install BDOT Collector with Ansible.


# Bindplane OTel Collector

[Ansible](https://www.ansible.com/) can be used as an alternative to the collector install script. The [Bindplane Collector Ansible Role](https://github.com/observIQ/bindplane-agent-ansible) can be integrated into your Ansible playbooks to manage the installation of Bindplane-managed collectors.

Ansible is useful for installing collectors at scale, where the installation script would be cumbersome to manage on hundreds or thousands of systems.

#### Usage

The Bindplane Collector role must be cloned to your workstation and added to your playbook before it can be deployed.

**Clone Repo**

Clone the Ansible Role Git repository to your `roles` directory.

The following command will clone the [repository](https://github.com/observIQ/bindplane-agent-ansible) to the directory `roles/bindplane_agent`.

```bash
git clone https://github.com/observIQ/bindplane-agent-ansible.git roles/bindplane_agent
```

**Update Playbook**

Update your Ansible Playbook to include the `bindplane_agent` role. The role requires the following parameters:

* version: Bindplane Collector version
* endpoint: The [remote URL](/configuration/bindplane#remote-url) of the Bindplane server
* secret\_key: The secret key of the Bindplane server. You can find the secret key on the install agent page, or with the CLI command `bindplane secret get`.

```yaml
- name: my-playbook
  hosts: my-hosts
  become: yes
  roles:
    - role: bindplane_agent
      version: '1.39.1'
      endpoint: 'wss://app.bindplane.com/v1/opamp'
      secret_key: 'xxxx-xxxx-xxxxx-xxxx'
```

**Deploy**

Once the role is configured in your playbook, you can deploy the collectors to your host group. For example:

```bash
ansible-playbook playbook.yml -i ./site.yml
```

This command assumes you have a playbook file `playbook.yml` and a site file `site.yml` in your working directory, along with the `roles/bindplane_agent` directory.

#### Additional Documentation

A comprehensive list of configuration options can be found in the [Bindplane Collector Role](https://github.com/observIQ/bindplane-agent-ansible) Github repository.


# Production Checklist

Key requirements and best practices for production Bindplane deployments

A guide for deploying Bindplane in production environments.

## Components

### [Bindplane Cloud](/production-checklist/bindplane-cloud/networking-requirements)

* Networking requirements

### [Bindplane Server (Self-Hosted)](/production-checklist/bindplane)

* High availability configuration
* Security hardening
* Monitoring and alerting
* Backup and recovery
* Performance optimization
* Networking requirements

### [Bindplane OTel Collector](/production-checklist/bindplane-otel-collector)

* Redundancy and failover
* Resource allocation
* Health monitoring
* Secure communication
* Operational procedures

## Core Requirements

### Infrastructure

* Compute and storage resources
* Network setup
* Persistent storage and backups
* Security and access controls

### Security

* Authentication and authorization
* Encryption and secrets management
* Network segmentation

### Monitoring

* Health checks and metrics
* Logging and alerts

### Networking

* Firewall
* Traffic routing
* Required ports and outbound endpoints

## Next Steps

* Core requirements
  * [Bindplane Server requirements](/production-checklist/bindplane)
  * [Bindplane Collector requirements](/production-checklist/bindplane-otel-collector)
* Configure monitoring
  * [Bindplane Server monitoring](/production-checklist/bindplane/monitoring-bindplane)
  * [Bindplane Collector monitoring](/production-checklist/bindplane-otel-collector/monitoring)
* Set up high availability
  * [Bindplane Server HA](/production-checklist/bindplane/high-availability)
  * [Bindplane Collector HA](/production-checklist/bindplane-otel-collector/high-availability)
* [Implement security](/configuration/bindplane/authentication)
* Configure networking
  * [Bindplane Server](/production-checklist/bindplane/networking-requirements)
  * [Bindplane Collector](/production-checklist/bindplane-otel-collector/networking-requirements)


# Bindplane Cloud

Bindplane Cloud Documentation


# Networking Requirements

This document describes the minimum outbound network access required for Bindplane Cloud usage, including collector connectivity and management traffic.

## Firewall Requirements

The following firewall rules are required for accessing Bindplane Cloud. This includes user browsers, API clients, and collectors.

### app.bindplane.com

The primary endpoint for Bindplane Cloud is `https://app.bindplane.com`. This endpoint serves all user traffic including browsers, API clients, and managed collectors.

#### Endpoints

Bindplane provides an [Open API spec](/cli-and-api/api) with programmatic access to all Bindplane functionality.

* REST API — `https://app.bindplane.com/v1/<endpoint>`
* OpAMP — `wss://app.bindplane.com/v1/opamp`

#### Protocols

The following operations access `app.bindplane.com` over port `443`:

* API requests (HTTPS REST) — `/v1/<endpoint>`
* User browsers (HTTPS and WebSocket)
* Collectors (OpAMP WebSocket) — `/v1/opamp`

Your firewall and/or proxy must allow WebSocket upgrades.

#### Egress

Allow outbound access to Bindplane Cloud:

* **Host:** `https://app.bindplane.com` (TLS)
* **IP:** `34.120.255.184`
* **Port**: `443/tcp`

Note: IP addresses associated with `app.bindplane.com` can change in the future. If your environment supports it, prefer allowing outbound access by hostname (SNI/explicit proxy allowlist) rather than pinning a single IP. If you must pin IPs, ensure you have a process to update allowlists when the resolved IP changes.

Outbound access to Bindplane Cloud is required to support collector management.

#### Ingress

Bindplane Cloud does not require inbound access into customer networks. Collectors initiate outbound connections to Bindplane Cloud; Bindplane Cloud does not initiate inbound connections to collectors.

### Other Endpoints

#### bdot.bindplane.com

Collector installation scripts utilize this endpoint for collector downloads. This endpoint uses HTTPS and does not require websockets.

Allow outbound access to Bindplane Cloud:

* **Host:** `https://bdot.bindplane.com` (TLS)
* **IP:** `34.36.182.107`
* **Port**: `443/tcp`

## FAQ

**Q**: Does Bindplane use Transport Layer Security (TLS)?\
**A**: All connections to Bindplane cloud utilize Transport Layer Security (TLS).


# Bindplane Server (Self-Hosted)

Bindplane is made up of several components. The store, measurements database, and event bus. Bindplane can be configured as a single instance or high availability mode. By default, a Bindplane Server operates in the single instance mode where all components are included in the installation.

Optionally, users can operate Bindplane in high availability mode. This documentation will cover each component and where they fit within both operation modes.

### Single Instance

Single instance is suitable for small, medium, and large deployments of Bindplane. This mode\
is the easiest way to get started as it requires a single Linux server or virtual machine.

Single instance mode is the recommended deployment model for users who prefer simplicity at the expense of fault tolerance. When fault tolerance is required, Bindplane can be configured in high availability mode.

{% hint style="info" %}
**NOTE**

When Bindplane is down due to maintenance or an outage, managed collectors will continue to operate\
like normal. Collectors do not depend on Bindplane to be available.
{% endhint %}

When operating in single instance mode, Bindplane does not depend on third-party systems such as a remote database.

For more details, see the [Single Instance](/production-checklist/bindplane/single-instance) documentation.

### High Availability

High availability is a great choice for users who can support a more complex deployment to gain\
fault tolerance. When operating Bindplane in high availability mode, an individual Bindplane server\
can go offline for maintenance without causing an outage.

The high availability architecture is significantly more complex, as it requires the following\
supporting systems:

* 2 or more Bindplane servers
* Load balancer
* PostgreSQL database
* Dedicated Prometheus deployment
* Event bus

For more details, see the [High Availability](/production-checklist/bindplane/high-availability) documentation.


# Single Instance

Bindplane server's default architecture is monolithic. In this mode, Bindplane depends only on a PostgreSQL database. All other components are bundled with the Bindplane server installation.

Bindplane manages several sub-processes:

* Prometheus: For recording collector throughput metrics
* Transform Agent: For [Live Preview](broken://pages/QeJXTHAiy3fbDC0oMrLz)

The Prometheus and Transform Agent software are included with the Bindplane server installation and do not require configuration by the user.

Installing Bindplane on Linux is as simple as running the installation script and following the initialization prompts.

```bash
curl -fsSlL https://storage.googleapis.com/bindplane-op-releases/bindplane/latest/install-linux.sh -o install-linux.sh && bash install-linux.sh --init && rm install-linux.sh
```

Read more by checking out the [Quick Start Guide](broken://pages/kXB12Z4O8j140j2AElhL).

### Event Bus

#### Local

The Local event bus is the default event bus used by Bindplane. Unless operating Bindplane in high availability mode, the Local event bus is sufficient.

The configuration will look like this by default:

```yaml
eventBus:
  type: local
```

### Store

#### PostgreSQL

PostgreSQL is the storage backend used for all Bindplane installations. When operating Bindplane as a single instance, it is safe to install PostgreSQL on the same server as Bindplane.

Follow the [PostgreSQL installation instructions](/deployment/virtual-machine/bindplane/postgresql) to install PostgreSQL.

You can avoid using username and password credentials by configuring PostgreSQL to allow processes owned by the `bindplane` user to connect to the database over localhost without a password. Update your `pg_hba.conf` configuration with the following entries:

```pg_hba.conf
host    all   bindplane   ::1/128        trust
host    all   bindplane   127.0.0.1/32   trust
```

### Prometheus

All Bindplane installations include a bundled version of Prometheus. Bindplane will use the bundled Prometheus as its default measurement metrics storage backend.

It is unnecessary to configure Prometheus when using the bundled option. This documentation can be used as a reference for the default Prometheus installation.

#### Configuration

The configuration file at `/etc/bindplane/config.yaml` will contain the following `prometheus`\
block after the installation is configured.

```yaml
prometheus:
  localFolder: /var/lib/bindplane/prometheus
  host: localhost
  port: '9090'
  remoteWrite:
    endpoint: /api/v1/write
  auth:
    type: none
```

#### Directory Structure

Once Bindplane is started, the `/var/lib/bindplane/prometheus`directory structure will look like this:

```
/var/lib/bindplane/prometheus
├── console_libraries
│   ├── menu.lib
│   └── prom.lib
├── consoles
│   ├── index.html.example
│   ├── node-cpu.html
│   ├── node-disk.html
│   ├── node.html
│   ├── node-overview.html
│   ├── prometheus.html
│   └── prometheus-overview.html
├── data
│   ├── chunks_head
│   ├── lock
│   ├── queries.active
│   └── wal
│       └── 00000000
├── LICENSE
├── NOTICE
├── prometheus
├── prometheus.yml
├── promtool
├── rules.yml
└── web.yml
```

Prometheus's configuration and storage are located at `/var/lib/bindplane/prometheus`.

#### Process

Bindplane manages the Prometheus process directly as a subprocess. When viewing the process list\
with `ps`, you will notice the following:

```
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
bindplane  143936  0.0  0.0 1319104 64000 ?       Sl   12:20   0:00 /var/lib/bindplane/prometheus/prometheus --config.file prometheus.yml --web.config.file web.yml --storage.tsdb.retention.time 2d --web.listen-address :9090 --web.enable-remote-write-receiver
```

The Prometheus process is executed with the following flags:

* `--config.file prometheus.yml`: The main Prometheus configuration file, managed by Bindplane.
* `--web.config.file web.yml`: The Prometheus web configuration file, managed by Bindplane.
* `--storage.tsdb.retention.time 2d`: The retention time, managed by Bindplane. Bindplane uses rollup metrics for tracking collector measurements over time and does not require Prometheus to store data for longer than two days.
* `--web.listen-address localhost:9090`: Listen address, managed by Bindplane. Prometheus is not reachable outside of the Bindplane system.
* `--web.enable-remote-write-receiver`: Bindplane uses remote write to push metrics to Prometheus.


# High Availability

Bindplane is capable of running in high availability (HA) mode. Bindplane runs in an **active-active** HA mode, meaning that the workload of the application is spread across all nodes in the cluster.

<figure><img src="/files/o0Sl3hBl9ZJVDWvoGo0K" alt="Bindplane docs - High Availability - image 1"><figcaption></figcaption></figure>

When operating Bindplane in high availability, several user-managed components are\
required.

* [Load balancer](/production-checklist/bindplane/high-availability/load-balancer)
* [PostgreSQL](/production-checklist/bindplane/high-availability/postgresql)
* [Prometheus Measurement Database](/production-checklist/bindplane/high-availability/prometheus)
* [Event Bus](/production-checklist/bindplane/high-availability/event-bus)

One or more Bindplane servers can be installed. Each server is stateless. All data is stored in the Postgres and Prometheus databases. Communication between servers is handled by the event bus. The configuration between all Bindplane servers should be the same.

### Example Implementations

#### Google Cloud

See the [Multi Node Architecture On Google Cloud](broken://pages/3Fc7OnBWxDIVttFF4qKI) guide for details on how to deploy Bindplane server's distributed architecture on Google Cloud using services such as Cloud Load Balancer, Pub/Sub, and CloudSQL.


# Event Bus

Bindplane uses an event bus to communicate between components within Bindplane. When operating Bindplane in high availability mode, the event bus can be used to send events between Bindplane servers.

When operating in high availability, the following event bus options are available:

* [NATS](#nats)
* [Google Pub/Sub](#google-pub-sub)

### NATS

The NATS event bus is Bindplane's embedded event bus, suitable for high availability without\
the need for external infrastructure.

See the [NATS Configuration](/configuration/bindplane/nats-as-event-bus) documentation for more information.

### Google Pub/Sub

[Google Cloud Pub/Sub](https://cloud.google.com/pubsub) is an excellent event bus choice for users with access to Google Cloud. Setup is simple, and the maintenance overhead of Pub/Sub is very low.

```yaml
eventBus:
  type: googlePubSub
  googlePubSub:
    projectID: myproject
    credentialsFile: operation-service-account-credentials.json
    topic: bindplane
```

For a list of supported options, see the [Google Pub/Sub](/configuration/bindplane) section in the configuration documentation.


# Load Balancer

A load balancer is required when operating Bindplane in high availability mode. Incoming collector and client requests will be distributed among all Bindplane servers.

### Prerequisites

The following requirements must be met by your load balancer choice:

* Support WebSocket connections
* Support TCP or HTTP load balancing
* Support TCP or HTTP health checks

### Installation

It is up to the user to deploy and manage the load balancer. If operating in a cloud environment, it is recommended that you use one of the following services.

* [Google Cloud Load Balancing](https://cloud.google.com/load-balancing?hl=en)
* [Amazon Elastic Load Balancing](https://aws.amazon.com/elasticloadbalancing/)
* [Azure Load Balancer](https://learn.microsoft.com/en-us/azure/load-balancer/load-balancer-overview)

If running on-premise, we recommend:

* [HAProxy](https://www.haproxy.org/)
* [NGINX](https://www.nginx.com/)

### Configuration

The load balancer should be configured to balance requests between all of your Bindplane servers on port `3001`. If your load balancer supports sticky connections, enable it. If not, round-robin load balancing is supported.

Configure the health checks to target `/health` on port `3001`. When Bindplane is healthy, it will return a status `200 OK`.


# PostgreSQL

PostgreSQL allows multiple Bindplane servers to share and access data concurrently, enabling the ability to operate Bindplane in high availability.

See the [PostgreSQL setup](/deployment/virtual-machine/bindplane/postgresql) documentation for more information.


# Prometheus

Prometheus is required when operating Bindplane in high availability.

Bindplane stores time series metrics in [Prometheus](https://prometheus.io/docs/prometheus/latest/storage/). These time series metrics allow Bindplane to track collector throughput measurements over time. When viewing the summary page or a specific configuration, the measurement data being displayed is the work of the measurement database.

When operating Bindplane in single instance mode, a bundled version of Prometheus will be used. The user does not need to install or configure Prometheus.

### Prerequisites

#### Sizing

Prometheus can be scaled vertically based on the number of managed collectors. The volume of time series metrics being pushed to Prometheus will scale linearly with the number of collectors.

The following table provides a general guideline for sizing your Prometheus instance based on the number of collectors. This table should service as a starting point for sizing your Prometheus instance.

<table><thead><tr><th width="364.875">Collector Count</th><th>CPU Cores</th><th>Memory</th><th width="122.37890625">Disk (GB)</th></tr></thead><tbody><tr><td>1-25,000</td><td>2</td><td>8GB</td><td>80</td></tr><tr><td>25,000-250,000</td><td>4</td><td>16GB</td><td>300</td></tr><tr><td>250,000-500,000</td><td>8</td><td>32GB</td><td>600</td></tr><tr><td>500,000-1,000,000</td><td>16</td><td>64GB</td><td>1200</td></tr></tbody></table>

{% hint style="info" %}
**NOTE**

Complicated configurations with many sources, processor nodes, and destinations will output more time series metrics.
{% endhint %}

### Installation

Prometheus should be installed on a dedicated system. The installation will be accessed by each Bindplane server in your environment.

Follow the [installation](/production-checklist/bindplane/high-availability/prometheus/installation) documentation for instructions for deploying a shared Prometheus instance.

### Configuration

Bindplane will use a bundled version of Prometheus by default. The configuration must be updated\
to use a remote Prometheus instance. See the [configuration](/production-checklist/bindplane/high-availability/prometheus/configuration) documentation for instructions on configuring your Bindplane servers to use the shared Prometheus instance.


# Installation

Each Bindplane release includes a matching version of Prometheus that can be used to deploy\
a dedicated Prometheus server. The package simplifies installation because it handles user creation\
and configuration management. If you wish to configure install and configure Prometheus on your own, you can follow the [manual installation](/production-checklist/bindplane/high-availability/prometheus/manual-install) documentation. The recommended approach is to use the provided Linux package.

### Download

Each Bindplane release includes packages for Debian and RHEL based distributions.

{% tabs %}
{% tab title="Debian/AMD64" %}

```bash
curl -L \
  -o bindplane-prometheus.deb \
  https://downloads.bindplane.com/bindplane/latest/bindplane-prometheus_linux_amd64.deb
```

{% endtab %}

{% tab title="Debian/ARM64" %}

```bash
curl -L \
  -o bindplane-prometheus.deb \
  https://downloads.bindplane.com/bindplane/latest/bindplane-prometheus_linux_arm64.deb
```

{% endtab %}

{% tab title="RHEL/AMD64" %}

```bash
curl -L \
  -o bindplane-prometheus.rpm \
  https://downloads.bindplane.com/bindplane/latest/bindplane-prometheus_linux_amd64.rpm
```

{% endtab %}

{% tab title="RHEM/ARM64" %}

```bash
curl -L \
  -o bindplane-prometheus.rpm \
  https://downloads.bindplane.com/bindplane/latest/bindplane-prometheus_linux_arm64.rpm
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
**NOTE**

Ubuntu and CentOS users should use the deb and rpm packages, respectively.
{% endhint %}

### Install

Install the package with your package manager.

{% tabs %}
{% tab title="Debian" %}

```bash
sudo apt-get install -f ./bindplane-prometheus.deb
```

{% endtab %}

{% tab title="RHEL" %}

```bash
sudo yum install bindplane-prometheus.rpm
```

{% endtab %}
{% endtabs %}

Once the package is installed, it must be enabled and started.

```bash
sudo systemctl enable --now prometheus
```

### Configuration

See the [configuration](/production-checklist/bindplane/high-availability/prometheus/configuration) documentation for configuration details.

### Uninstall

The package can be removed using the package manager.

{% tabs %}
{% tab title="Debian" %}

```bash
sudo apt-get remove bindplane-prometheus
sudo apt-get purge bindplane-prometheus
```

{% endtab %}

{% tab title="RHEL" %}

```bash
sudo yum remove bindplane-prometheus
```

{% endtab %}
{% endtabs %}


# Manual Install

Installing Prometheus manually is accomplished by following the steps outlined on this page. The\
recommended approach is to install Prometheus using a Linux package. See the [Linux Package](/production-checklist/bindplane/high-availability/prometheus/installation)\
documentation for details.

### Prerequisites

#### Version

Prometheus version 2.47.2 or newer.

### Create User and Group

Create a Prometheus user and group. This user will be used to execute the Prometheus process.

```bash
sudo groupadd --system prometheus
sudo useradd -s /sbin/nologin --system -g prometheus prometheus
```

### Download Release

Download the [v2.47.2 release](https://github.com/prometheus/prometheus/releases/tag/v2.47.2).

{% tabs %}
{% tab title="AMD64" %}

```bash
curl -L \
    -o prometheus.tar.gz \
    https://github.com/prometheus/prometheus/releases/download/v2.47.2/prometheus-2.47.2.linux-amd64.tar.gz
```

{% endtab %}

{% tab title="ARM64" %}

```bash
curl -L \
    -o prometheus.tar.gz \
    https://github.com/prometheus/prometheus/releases/download/v2.47.2/prometheus-2.47.2.linux-arm64.tar.gz
```

{% endtab %}
{% endtabs %}

Extract the archive to your working directory.

```bash
mkdir prometheus
tar -xf prometheus.tar.gz --strip-components=1 -C prometheus
```

### Binary Installation

Install binaries to `/usr/bin`.

```bash
sudo cp prometheus/prometheus /usr/bin/prometheus
sudo cp prometheus/promtool /usr/bin/promtool
```

### Configuration

Configure the Prometheus configuration directories and files.

```bash
sudo mkdir /etc/prometheus

sudo touch \
    /etc/prometheus/prometheus.yml \
    /etc/prometheus/rules.yml \
    /etc/prometheus/web.yml

sudo chmod 0750 /etc/prometheus
sudo chmod 0600 /etc/prometheus/prometheus.yml
sudo chmod 0600 /etc/prometheus/rules.yml
sudo chmod 0600 /etc/prometheus/web.yml
sudo chown -R prometheus:prometheus /etc/prometheus
```

Configure the Prometheus storage directories and files.

```bash
sudo mkdir /var/lib/prometheus
sudo mkdir /var/lib/prometheus/tsdb

sudo mv prometheus/console_libraries /var/lib/prometheus
sudo mv prometheus/consoles /var/lib/prometheus

sudo chmod 0750 /var/lib/prometheus
sudo chown -R prometheus:prometheus /var/lib/prometheus
```

Populate `prometheus.yml`.

```bash
sudo tee /etc/prometheus/prometheus.yml <<'EOF'
scrape_configs: []
rule_files: [/etc/prometheus/rules.yml]
EOF
```

Populate `rules.yml`.

```bash
sudo tee /etc/prometheus/rules.yml <<'EOF'
groups:
- name: configuration-rollups
  interval: 1m
  rules:
  - record: bindplane_agent_measurements:rollup:rate:1m
    expr: sum without (agent) (rate(bindplane_agent_measurements{}[1m9s999ms] offset 10s))
- name: 5m-configuration-rollups
  interval: 5m
  rules:
  - record: bindplane_agent_measurements:rollup:rate:5m
    expr: sum without (agent) (rate(bindplane_agent_measurements:1m{}[5m59s999ms] offset 10s))
- name: 1h-configuration-rollups
  interval: 1h
  rules:
  - record: bindplane_agent_measurements:rollup:rate:1h
    expr: sum without (agent) (rate(bindplane_agent_measurements:15m{}[1h14m59s999ms] offset 10s))
EOF
```

Leave `web.yml` alone for now. See the [TLS](/production-checklist/bindplane/high-availability/prometheus/configuration#transport-layer-security-tls) section for details on how to secure communication between Bindplane and Prometheus.

### Systemd Service

Create the Systemd service.

```bash
sudo touch /usr/lib/systemd/system/prometheus.service
sudo chmod 0640 /usr/lib/systemd/system/prometheus.service

sudo tee /usr/lib/systemd/system/prometheus.service <<'EOF'
[Unit]
Description=Prometheus
Documentation=https://prometheus.io/docs/introduction/overview/
Wants=network-online.target
After=network-online.target
[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/bin/prometheus \
--config.file /etc/prometheus/prometheus.yml \
--web.config.file /etc/prometheus/web.yml \
--storage.tsdb.retention.time 2d \
--web.enable-remote-write-receiver \
--web.listen-address :9090 \
--storage.tsdb.path /var/lib/prometheus/tsdb \
--web.console.templates=/var/lib/prometheus/consoles \
--web.console.libraries=/var/lib/prometheus/console_libraries

[Install]
WantedBy=multi-user.target
EOF
```

Enable and start Prometheus.

```bash
sudo systemctl enable prometheus
sudo systemctl start prometheus
sudo systemctl status prometheus
```

### Validate

You can validate that Prometheus is running with the following curl command.

```bash
curl -v -s localhost:9090/metrics
```


# Configuration

When operating a self-managed Prometheus instance, Bindplane's server configuration must be updated to connect to the remote Prometheus instance.

### Bindplane Configuration

After installing Bindplane, update the configuration file at `/etc/bindplane/config.yaml`using the editor of your choice.

* Set `prometheus.enableRemote` to `true`
* Set `prometheus.host` to the IP address or Hostname of your Prometheus server.

```yaml
prometheus:
  enableRemote: true
  localFolder: /var/lib/bindplane/prometheus
  host: prometheus.c.project.internal
  port: '9090'
  remoteWrite:
    endpoint: /api/v1/write
  auth:
    type: none
```

Once `enableRemote` and `host` are configured, restart the Bindplane server process.

```bash
sudo systemctl restart bindplane
```

At this point, Bindplane is installed and configured to use the remote Prometheus instance.

### Security

Prometheus supports several options for security. Basic authentication (Basic auth), Transport Layer\
Security (TLS), and Mutual TLS (mTLS).

#### Basic Authentication

Follow the Prometheus [Basic Auth Password Hashing](https://prometheus.io/docs/guides/basic-auth/#hashing-a-password) documentation to generate a password hash.

Once you have your hash, update `/etc/prometheus/web.yml` with your basic auth username and password hash.

// cspell:ignore maOicLymWgsIQleRCm604ePbaaavp9cKj3bJUg0IrcVXCHB3terLa

```yaml
# Example use only: admin:password
basic_auth_users:
  admin: $2b$12$maOicLymWgsIQleRCm604ePbaaavp9cKj3bJUg0IrcVXCHB3terLa
```

Restart the Prometheus service.

```bash
sudo systemctl restart prometheus
```

Test by making a curl request, without basic auth. You should expect a "401 Unauthorized" response.

```bash
curl -v -s localhost:9090/metrics > /dev/null
```

Test by making a curl request with your username and password.

```bash
curl -v -s -u 'admin:password' localhost:9090/metrics > /dev/null
```

You should expect a "200 OK" response. This will indicate that basic auth is working correctly.

Next, we need to update Bindplane with the new credentials. Edit `/etc/bindplane/config.yaml` on all of your Bindplane servers.

```yaml
prometheus:
  enableRemote: true
  localFolder: /var/lib/bindplane/prometheus
  host: prometheus.c.bpcli-dev.internal
  port: '9090'
  remoteWrite:
    endpoint: /api/v1/write
  auth:
    type: basic
    username: admin
    password: password
```

Restart the Bindplane service.

```bash
sudo systemctl restart bindplane
```

#### Transport Layer Security (TLS)

Copy the certificate keypair to `/etc/prometheus/tls`. The example commands assume that you have a certificate key pair in your working directory named `prometheus.crt` and `prometheus.key`

```bash
sudo mkdir /etc/prometheus/tls

sudo mv prometheus.crt prometheus.key /etc/prometheus/tls

sudo chown -R prometheus:prometheus /etc/prometheus/tls
sudo chmod 0600 \
  /etc/prometheus/tls/prometheus.crt \
  /etc/prometheus/tls/prometheus.key
```

Server side TLS can be configured by editing the web configuration file at `/etc/prometheus/web.yml` and configuring the certificate file and private key file paths.

```yaml
tls_server_config:
  cert_file: /etc/prometheus/tls/prometheus.crt
  key_file: /etc/prometheus/tls/prometheus.key
```

Restart the Prometheus service.

```bash
sudo systemctl restart prometheus
```

You can test if Prometheus is using TLS by using curl.

```bash
curl -kvs https://localhost:9090/metrics > /dev/null
```

You should expect a "200 OK" response. This will indicate that server side TLS is working correctly.

Next, we need to update Bindplane to use TLS when communicating with Prometheus. On all of your servers, perform the following steps.

Copy the certificate authority to `/etc/bindplane/tls`. The example commands assume that you have a certificate authority public key named `ca.crt` in your working directory.

```bash
sudo mkdir /etc/bindplane/tls
sudo mv ca.crt /etc/bindplane/tls

sudo chown -R bindplane:bindplane /etc/bindplane/tls
sudo chmod 0600 /etc/bindplane/tls/ca.crt
```

Edit `/etc/bindplane/config.yaml` on all of your Bindplane servers and add the `tls.tlsCa`\
parameter.

```yaml
prometheus:
  enableRemote: true
  localFolder: /var/lib/bindplane/prometheus
  host: prometheus.c.bpcli-dev.internal
  port: '9090'
  remoteWrite:
    endpoint: /api/v1/write
  auth:
    type: none
  enableTLS: true
  tls:
    tlsSkipVerify: false
    tlsCa:
      - /etc/bindplane/tls/ca.crt
```

{% hint style="info" %}
**NOTE**

Make sure `prometheus.host` matches the hostname of the Prometheus server's certificate. If the\
hostname does not match, you can set `prometheus.tls.tlsSkipVerify` to `true` to skip TLS verification. Skipping TLS verification is not recommended in a production environment.
{% endhint %}

Restart the Bindplane service.

```bash
sudo systemctl restart bindplane
```

#### Mutual TLS

Copy the certificate keypair and certificate authority to`/etc/prometheus/tls`. The example commands assume that you have a certificate key pair in your working directory named `prometheus.crt` and `prometheus.key` and a certificate authority named `ca.crt`.

```bash
sudo mkdir /etc/prometheus/tls

sudo mv prometheus.crt prometheus.key ca.crt /etc/prometheus/tls

sudo chown -R prometheus:prometheus /etc/prometheus/tls
sudo chmod 0600 \
  /etc/prometheus/tls/prometheus.crt \
  /etc/prometheus/tls/prometheus.key \
  /etc/prometheus/tls/ca.crt
```

Mutual TLS can be configured by editing the web configuration file at `/etc/prometheus/web.yml` and configuring the certificate file, private key file paths and certificate authority paths.

```yaml
tls_server_config:
  client_auth_type: RequireAndVerifyClientCert
  client_ca_file: /etc/prometheus/tls/ca.crt
  cert_file: /etc/prometheus/tls/prometheus.crt
  key_file: /etc/prometheus/tls/prometheus.key
```

Restart the Prometheus service.

```bash
sudo systemctl restart prometheus
```

You can test if Prometheus is using TLS by using curl on the Prometheus system.

```bash
# Sudo is required to read the TLS certificate files
# in /etc/prometheus/tls.
# Replace $(hostname -f) with the hostname that matches
# the prometheus server and certificate.
sudo curl -vs \
  --cacert /etc/prometheus/tls/ca.crt \
  --cert /etc/prometheus/tls/prometheus.crt \
  --key /etc/prometheus/tls/prometheus.key \
  "https://$(hostname -f):9090/metrics" > /dev/null
```

You should expect a "200 OK" response. This will indicate that mutual TLS is working correctly.

Next, we need to update Bindplane to use mutual TLS when communicating with Prometheus. On all of your servers, perform the following steps.

Copy the certificate authority and client keypair to `/etc/bindplane/tls`. The example commands assume that you have a certificate key pair in your working directory named `bindplane.crt` and `bindplane.key` and a certficate authority named `ca.crt`.

```bash
sudo mkdir /etc/bindplane/tls
sudo mv bindplane.crt bindplane.key ca.crt /etc/bindplane/tls

sudo chown -R bindplane:bindplane /etc/bindplane/tls
sudo chmod 0600 \
  /etc/bindplane/tls/bindplane.crt \
  /etc/bindplane/tls/bindplane.key \
  /etc/bindplane/tls/ca.crt
```

Edit `/etc/bindplane/config.yaml` on all of your Bindplane servers and add the `tls` parameters.

```yaml
prometheus:
  enableRemote: true
  localFolder: /var/lib/bindplane/prometheus
  host: prometheus.c.bpcli-dev.internal
  port: '9090'
  remoteWrite:
    endpoint: /api/v1/write
  auth:
    type: none
  enableTLS: true
  tls:
    tlsSkipVerify: false
    tlsCa:
      - /etc/bindplane/tls/ca.crt
    tlsCert: /etc/bindplane/tls/bindplane.crt
    tlsKey: /etc/bindplane/tls/bindplane.key
```

{% hint style="info" %}
**NOTE**

Make sure `prometheus.host` matches the hostname of the Prometheus server's certificate. If the\
hostname does not match, you can set `prometheus.tls.tlsSkipVerify` to `true` to skip TLS verification. Skipping TLS verification is not recommended in a production environment.
{% endhint %}

Restart the Bindplane service.

```bash
sudo systemctl restart bindplane
```


# Secrets Management

Manage Secrets with Bindplane

Managing sensitive information securely is critical when deploying monitoring solutions. Bindplane provides several approaches to help you protect credentials and other secrets used in your OpenTelemetry configurations. This guide outlines the available options and best practices for securing your sensitive data.

{% hint style="warning" %}
**IMPORTANT**

Bindplane Cloud automatically encrypts all Library Resources, Configurations, Snapshot Recordings, and Agent State information using Envelope Encryption, regardless of whether they contain sensitive data.

For self-hosted Bindplane deployments, encryption is not enabled by default. To enable encryption of sensitive data, you must configure your instance to integrate with Google KMS. Directions for this can be found [here](/production-checklist/bindplane/secrets-management/envelope-encryption#self-hosted-encryption-implementation). Customers must be using Postgres to enable this option. Encryption is not supported when using Boltstore, which is being deprecated.
{% endhint %}

### Available Methods

Bindplane offers multiple approaches to secure your secrets, with more options being developed:

<table><thead><tr><th width="129.7578125">Method</th><th width="101.26953125">Status</th><th>Description</th><th width="166.25390625">Bindplane Access</th></tr></thead><tbody><tr><td>Environment Variables</td><td>Available</td><td>Reference environment variables in Configurations</td><td>No Access</td></tr><tr><td>Envelope Encryption</td><td>Available</td><td>Use a managed KEK (Key Encryption Key) and an encrypted DEK (Data Encryption Key) to protect secrets</td><td>Limited Access *</td></tr></tbody></table>

{% hint style="info" %}
**NOTE**

* When using Envelope Encryption, the Bindplane Platform will need to decrypt the secret before transmitting the configuration to the selected Agents. AES encryption can be used to symmetrically encrypt the secret before transmission using the [AES provider](/configuration/bindplane-otel-collector/configuration-encryption).
  {% endhint %}

{% hint style="info" %}
**NOTE**

When using Environment Variables, the Bindplane Platform does not access any secrets in the configuration. Only the Agent will have access.
{% endhint %}

### Choosing the Right Approach

The right secrets management approach depends on your security requirements, operational constraints, and existing infrastructure:

#### Environment Variables

Best for: Organizations with established environment management practices or simpler deployments. Kubernetes based deployments with integrated KMS in a Kubernetes cluster.

**Benefits**

* Secrets never leave customer premises
* Secrets are not in the collector pipeline YAML
* Works Out of the Box in Cloud or in a self-hosted deployment

**Drawbacks**

* More complex to manage at scale

#### Envelope Encryption

Best for: Organizations requiring enhanced security while maintaining operational simplicity.

**Benefits**

* Works out of the box in Bindplane Cloud
* Securely stores secrets in all Library Resources, Configurations, and Snapshot Recordings.
* Supports end-to-end encryption through integration with the [AES Provider](/configuration/bindplane-otel-collector/configuration-encryption) for enhanced security during configuration transmission

**Drawbacks**

* Requires configuration to work in a self-hosted scenario.
* Pipeline YAML in Collector will still contain secret values if [AES Provider](/configuration/bindplane-otel-collector/configuration-encryption) is not used.

### Getting Started

Explore our detailed guides for each method:

* [Using Environment Variables](/production-checklist/bindplane/secrets-management/using-environment-variables)
* [Envelope Encryption](/production-checklist/bindplane/secrets-management/envelope-encryption)


# Using Environment Variables

Using Environment Variables in Bindplane

Environment variables enable secure credential management in Bindplane by leveraging the OpenTelemetry Collector's environment variable substitution capabilities. This approach ensures sensitive values remain outside of the platform's storage.

### Overview

Bindplane supports environment variable references in collector configurations through the standard `${ENV_VAR}` syntax. During deployment, these references are automatically resolved to their corresponding values in the collector agent's runtime environment.

{% hint style="info" %}
**NOTE**

Environment variable values remain exclusively within your deployment environment and are not persisted in Bindplane's database.
{% endhint %}

{% hint style="info" %}
**NOTE**

Proper configuration of environment variables on agent hosts is essential. Misconfigured variable names or values may lead to deployment failures or pipeline execution errors.
{% endhint %}

### Implementation Guide

#### Step 1: Configuration Setup

Create or modify collector configurations in the Bindplane UI by incorporating environment variable references for sensitive values.

<figure><img src="/files/ZS9SWjeygrNWw02K4lR9" alt="Bindplane docs - Using Environment Variables - image 1"><figcaption></figcaption></figure>

#### Step 2: Environment Configuration

Configure the required environment variables on all systems hosting OpenTelemetry collectors.

For Linux systems:

```bash
# This will set the Environment Variables for the scope of your shell session.
# To persist them, you will need to add them to your .bashrc or .zshrc files.
export DB_HOST=db.example.com
export DB_USER=collector_user
export DB_PASSWORD=your-secure-password
export DB_NAME=metrics_db
```

For Windows systems:

```powershell
# To set scoped environment variables to the powershell session
$env:DB_HOST="db.example.com"
$env:DB_USER="collector_user"
$env:DB_PASSWORD="your-secure-password"
$env:DB_NAME="metrics_db"

# To set machine scoped environment variables permanently
[Environment]::SetEnvironmentVariable('DB_HOST', 'db.example.com', 'Machine')
[Environment]::SetEnvironmentVariable('DB_USER', 'collector_user', 'Machine')
[Environment]::SetEnvironmentVariable('DB_PASSWORD', 'your-secure-password', 'Machine')
[Environment]::SetEnvironmentVariable('DB_NAME', 'metrics_db', 'Machine')

# To set the Environment Variable via the Registry, you can use the following:
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\observiq-otel-collector" /v Environment /t REG_MULTI_SZ /d "DB_HOST="db.example.com" /f
```

For additional information about Windows Environment Variables in PowerShell, consult the [Microsoft PowerShell documentation](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables?view=powershell-7.5).

#### Step 3: Deployment and Validation

Deploy the configuration through Bindplane and validate collector functionality with the configured environment variables.

### Implementation Best Practices

1. **Naming Conventions**: Implement clear, descriptive environment variable names (e.g., `DB_MYSQL_PASSWORD` rather than `PASSWORD`)
2. **Documentation**: Maintain comprehensive documentation of required environment variables for each collector configuration
3. **Access Control**: Implement appropriate permissions to restrict environment variable access to authorized collector service accounts
4. **Deployment Automation**: Incorporate environment variable configuration into deployment automation or service definitions
5. **Security Integration**: Consider integrating with enterprise secrets management solutions for automated environment variable population


# Envelope Encryption

### Overview

Bindplane implements envelope encryption to provide robust security for sensitive data while maintaining optimal performance. This document outlines the envelope encryption implementation in both Bindplane's hosted Cloud environment and self-hosted deployments.

{% hint style="info" %}
**NOTE**

Envelope Encryption is enabled by default in the Cloud environment. For self-hosted installations, this feature requires explicit configuration.
{% endhint %}

#### Key Concepts and Terminology

**Encryption Components**

* **DEK (Data Encryption Key)**: A symmetric encryption key generated per account that encrypts and decrypts customer data. DEKs are stored in encrypted form within the database.
* **KEK (Key Encryption Key)**: A master key managed through Google Cloud KMS that encrypts and decrypts DEKs. Each project maintains its own KEK within the organization's key ring.
* **Envelope Encryption**: A security architecture where data is encrypted with a DEK, and the DEK itself is encrypted with a KEK. This approach provides enhanced security and flexible key management capabilities.

**Google Cloud KMS Components**

* **KMS (Key Management Service)**: A managed service from Google Cloud that provides cryptographic key creation, storage, and control.
* **Key Ring**: A logical collection of cryptographic keys in Google Cloud KMS. Each Bindplane organization is assigned a dedicated key ring.

**Bindplane Organizational Structure**

* **Organization**: The highest-level entity in the Bindplane hierarchy, associated with a unique KMS key ring.
* **Project**: A logical container within an organization for grouping related resources. Organizations can contain multiple projects.
* **Customer Secret**: Any resource within Bindplane that may contain sensitive customer data, including Configurations, Sources, Destinations, and Snapshot Recordings.

#### Initial Setup Process

The system establishes a key ring for each organization and generates individual keys for each project within that organization. New projects automatically receive their own dedicated key.

```mermaid
sequenceDiagram
    participant BP as Bindplane Cloud
    participant KMS as Google Cloud KMS
    participant PG as Database

    Note over BP,KMS: Organization Setup
    BP->>KMS: Create Key Ring for Organization
    KMS-->>BP: Organization Key Ring Created

    Note over BP,KMS: Account Setup (per account in organization)
    loop For each Account
        BP->>KMS: Create KEK for Account
        KMS-->>BP: Account KEK Ready
        BP->>BP: Generate DEK for Account
        BP->>KMS: Encrypt DEK with Account KEK
        KMS-->>BP: Return encrypted DEK
        BP->>PG: Store encrypted DEK for Account
    end

    Note over BP,KMS: Setup Complete - Ready for Customer Secrets
```

#### Customer Secret Storage Flow

When objects that can contain customer secrets are stored, they are first encrypted with the project's DEK, which must be decrypted with the project's KEK. In order to provide good performance, the decrpyted DEK may be cached, but is never written to persistent disk.

```mermaid
sequenceDiagram
    participant Client as Client Application
    participant BP as Bindplane Cloud
    participant Redis as Cache
    participant PG as Database
    participant KMS as Google Cloud KMS

    Client->>BP: Store Customer Secret (Account Context)

    alt Account DEK not in cache
        BP->>Redis: Check for cached Account DEK
        Redis-->>BP: Account DEK not found

        BP->>PG: Query for encrypted Account DEK
        PG-->>BP: Return encrypted Account DEK
        BP->>KMS: Decrypt Account DEK using Account KEK
        KMS-->>BP: Return plaintext Account DEK

        BP->>Redis: Cache plaintext Account DEK
        Redis-->>BP: Account DEK cached
    else Account DEK in cache
        BP->>Redis: Retrieve cached Account DEK
        Redis-->>BP: Return plaintext Account DEK
    end

    BP->>BP: Encrypt customer secret with Account DEK
    BP->>PG: Store encrypted customer secret
    PG-->>BP: Secret stored
    BP-->>Client: Success response
```

#### Customer Secret Retrieval Flow

When retrieving objects that may contain customer sensitive data, the data must be decrypted using the project's DEK before the actual value can be used by the platform.

```mermaid
sequenceDiagram
    participant Client as Client Application
    participant BP as Bindplane SaaS
    participant Redis as Cache
    participant PG as Database
    participant KMS as Google Cloud KMS

    Client->>BP: Retrieve Customer Secret (Account Context)

    alt Account DEK in cache
        BP->>Redis: Get cached Account DEK
        Redis-->>BP: Return plaintext Account DEK
    else Account DEK not in cache
        BP->>PG: Query for encrypted Account DEK
        PG-->>BP: Return encrypted Account DEK
        BP->>KMS: Decrypt Account DEK using Account KEK
        KMS-->>BP: Return plaintext Account DEK
        BP->>Redis: Cache plaintext Account DEK
        Redis-->>BP: Account DEK cached
    end

    BP->>PG: Retrieve encrypted customer secret
    PG-->>BP: Return encrypted secret
    BP->>BP: Decrypt secret using Account DEK
    BP-->>Client: Return plaintext secret
```

### Hardware Security Module (HSM) Integration

Organizations can enhance their security posture by enabling HSM-backed keys for their projects' KEKs. This configuration is available through the Organization Settings interface by enabling the "Use Hardware Key Encryption" option. Upon activation, the system generates new KEKs and re-encrypts all DEKs using the HSM-backed keys.

{% hint style="info" %}
**NOTE**

* HSM backed keys are more costly than Software backed keys.
* HSM keys can be toggled off, which will re-encrypt again with a Software backed key.
* This feature is only available to Bindplane Enterprise and Bindplane Enterprise (Google Edition) licenses.
  {% endhint %}

<figure><img src="/files/GUFH7X0Nl6N5XHwZG2ti" alt="Bindplane docs - Envelope Encryption - image 1"><figcaption></figcaption></figure>

### Self-Hosted Encryption Implementation

For self-hosted Bindplane deployments version 1.91.2 or higher, encryption can be enabled by meeting the following requirements:

#### Prerequisites

* Google Cloud subscription with Google KMS APIs enabled
* Bindplane deployment setup with authentication to Google Cloud
* Service Account with `Cloud KMS Admin` role assigned.

{% hint style="info" %}
**NOTE**

The `Cloud KMS Admin` role requirement enables Bindplane to perform essential key management operations, including creation, rotation, and deletion of keys and key rings, as well as encryption and decryption operations.
{% endhint %}

#### Configuration

To enable encryption in your self-hosted Bindplane environment, configure the encryption settings using one of the following methods:

**Using YAML Configuration**

Add the following configuration to your Bindplane server configuration YAML file:

```yaml
store:
    encryptionProvider:
        type: googleKMS
        googleKMS:
            projectID: <projectID> (example: bindplane-dev)
            location: <location> (example:us)
            keyRotationPeriod: <rotation duration> (example: 720h)
```

**Using Environment Variables**

Alternatively, configure encryption using the following environment variables:

* `BINDPLANE_ENCRYPTIONPROVIDER_TYPE`
* `BINDPLANE_ENCRYPTIONPROVIDER_GOOGLEKMS_PROJECTID`
* `BINDPLANE_ENCRYPTIONPROVIDER_GOOGLEKMS_LOCATION`
* `BINDPLANE_ENCRYPTIONPROVIDER_GOOGLEKMS_KEY_ROTATION_PERIOD`


# Monitoring Bindplane

Monitoring Bindplane and Bindplane Collectors provides visibility into the health of your Observability Pipeline. We will walk through a few steps to easily set up sources that will forward the Bindplane server logs and the Bindplane Collector logs to the destination of your choice.

### Bindplane Monitoring

1. The first step is to deploy a collector on the Bindplane server itself. This will deploy like any collector, please follow the [Quickstart Guide](/readme/install-your-first-collector) if you have any questions.
2. Create a separate [configuration](/readme/build-your-first-configuration) for the Bindplane server as well.
3. When a collector is running on the Bindplane server and it is added to a configuration, we will select a source like in the image below:

<figure><img src="/files/amqNSXvmg7UrlYHUS1kY" alt="Bindplane docs - Monitoring Bindplane - image 1"><figcaption></figcaption></figure>

We can leave the settings default for this example:

<figure><img src="/files/BcL98tZeyNO4wfc1VXRl" alt="Bindplane docs - Monitoring Bindplane - image 2"><figcaption></figcaption></figure>

4. After we hit the 'Save' button we can click the 'Start Rollout' to push the configuration to the collector. All of your Bindplane logs will flow into the destination that you have configured. Next, we can set up [collector monitoring](/production-checklist/bindplane-otel-collector/monitoring).


# Networking Requirements

Bindplane Server can run fully offline, but certain optional features such as version detection, analytics, or LLM integrations require network connectivity to specific endpoints.

No outbound internet connectivity is required for running Bindplane Server (Self-Hosted).

However, several optional features and integrations may require access to external endpoints.

| Feature                                                     | Outbound Internet Connection Required | Description                      |
| ----------------------------------------------------------- | ------------------------------------- | -------------------------------- |
| Bindplane Server                                            | No                                    | Operates fully offline           |
| [Collector Version Detection](#collector-version-detection) | Optional                              | Checks for new BDOT releases     |
| [Analytics](#analytics)                                     | Optional                              | Sends anonymized usage metrics   |
| [Google SecOps Integration](#google-secops-integration)     | Optional                              | Enables SecOps-specific features |

***

### Bindplane API Endpoints

{% hint style="info" %}
**NOTE**

For self-hosted Bindplane, the UI can be accessed with your browser on port `3001`. The URL will be `http://<IP_ADDRESS>:3001`, with IP Address being that of the Bindplane Server. To log in, use the credentials you specified when running the `init` command.
{% endhint %}

Bindplane provides an [Open API spec](/cli-and-api/api) with programmatic access to all Bindplane functionality.

* REST API — `http://<IP_ADDRESS>:3001/v1/<endpoint>`
* OpAMP — `wss://<IP_ADDRESS>:3001/v1/opamp`

### GitHub Endpoints (for legacy or custom configurations)

* `https://api.github.com/`
* `https://github.com/observIQ/bindplane-otel-collector/`
* `https://raw.githubusercontent.com/observIQ/bindplane-otel-collector/`

***

### Collector Version Detection

Bindplane periodically checks for new versions of the Bindplane Collector (BDOT). Depending on your deployment type and version, it uses the following endpoints:

| Deployment Type       | Version / Date                                     | Default Endpoint             | Notes                             |
| --------------------- | -------------------------------------------------- | ---------------------------- | --------------------------------- |
| Bindplane Cloud       | Since 2025-08-12                                   | `https://bdot.bindplane.com` | Current default                   |
| Bindplane Self-Hosted | Since v1.94.0                                      | `https://bdot.bindplane.com` | Can be reconfigured to use GitHub |
| Earlier versions      | Before 2025-08-12 (Cloud) or v1.94.0 (Self-Hosted) | GitHub only                  | Deprecated behavior               |

***

### Analytics

If analytics are enabled, Bindplane Server may send anonymized usage metrics to `https://api.segment.io/`

{% hint style="info" %}
**NOTE**

Analytics are optional and can be fully disabled in the Bindplane configuration file.
{% endhint %}

***

### Google SecOps Integration

If you plan to use the [Google SecOps Partner Integration](https://docs.bindplane.com/feature-guides/partner-integrations/google-secops), the Bindplane server must be able to reach the following endpoints over outbound HTTPS (port `443`):

| Endpoint                                    | Purpose                                 |
| ------------------------------------------- | --------------------------------------- |
| `oauth2.googleapis.com:443`                 | OAuth Token Exchange                    |
| `chronicle.<region>.rep.googleapis.com:443` | Data Processing Pipeline Management API |

Replace `<region>` above with the region of your Google SecOps instance.


# Bindplane OTel Collector

Learn about the deployment architecture of OpenTelemetry Collectors.

{% hint style="info" %}
**NOTE**

Linux collectors are installed to run as the `root` user by default. See [Downgrade Collector Privileges](broken://pages/5H8a3xd8FJSvIrHNyRXV) for information on why this is the default and how to change it.
{% endhint %}

The Bindplane OTel Collector supports operating in two modes:

* Agent
* Gateway

The mode is not configurable, it is implicit based on the sources configured. For example, a collector configured with the Nginx source is running in agent mode, while a collector configured with the OTLP source (receiving telemetry from multiple collectors) is running in aggregation (gateway) mode.

### Agent

Agent mode is used for collecting telemetry from an individual system (e.g. Database host, API server). Collectors are used for collecting, processing, and shipping telemetry from an individual host to a destination. This destination may be your monitoring backend or an additional set of collectors (Gateways) which may perform additional processing and routing.

Collectors running in agent mode do not require additional configuration. Once a collector is installed, you can attach a configuration which gathers local logs, metrics, and traces from the system.

#### Use Cases

A collector is running in agent mode anytime it is deployed to an endpoint system. The following are examples, and do not cover all use cases.

* NGINX web server
* PostgreSQL database server

### Gateway

Gateway mode is used for receiving telemetry from one or more collectors over the network, optionally performing additional processing, and routing to a destination. Gateway collectors are optional, as agent collectors can ship telemetry directly to your telemetry backend.

#### Use Cases

**1. Isolating Backend Credentials**

Instead of deploying credentials to all of your agent collectors, you can keep credentials exclusively on the gateway collectors. This simplifies credential rotation and reduces the security attack surface as credentials are deployed to a subset of your systems.

**2. Offloading Processing Overhead**

Generally, you want your agent collectors to perform as little work as possible. If you have heavy processing requirements, it can be useful to offload that processing to a fleet of gateway collectors.

For example, instead of filtering telemetry with an expensive regex operation, you can have the gateway collectors perform that task. Generally, gateway collectors are running on a dedicated system. The processing overhead can be justified because it does not rob the compute power of other services running on the same system, unlike a collector that may be running on a database server.

**3. Network Security**

Gateway collectors could be located within a DMZ, firewalled from the internal network. You can configure your network to allow your agent collectors to forward to the gateway collectors while blocking the gateway collectors from reaching into your application network. This will allow you to send telemetry to a cloud-based backend without granting your endpoints access to the internet.

### Supported Source Types

Collectors are running in gateway mode when they are configured with a source type that receives telemetry from multiple remote systems.

Gateway source examples:

* OTLP
* Syslog
* TCP / UDP

Any source type which handles telemetry from one or more remote collectors is considered to be a gateway.


# Agents v. Gateways

Learn when and why to use gateways in your telemetry pipeline, and how to architect them for production environments.

A collector can run as either an agent or a gateway. An agent sits on the same host, container, or node as the workload it monitors. A gateway is a standalone collector that receives telemetry from agents, processes it, and forwards it to your destinations. Both use the same binary – the only difference is where they deploy and how they're configured.

For most production deployments, the agent-gateway pattern is the recommended architecture. This guide covers when gateways are the right choice, when you can skip them, how to size and scale them, and the architecture patterns that fit common deployment scenarios.

<figure><img src="/files/DppSpbBzQAwu4H7Z7HTk" alt=""><figcaption></figcaption></figure>

## When to Use Gateways

Gateways solve three problems that come up in most production environments.

* **Credential isolation.** Without gateways, every server that sends telemetry needs credentials to your destination, whether that's Google SecOps, Splunk, Datadog, or anything else. With gateways, only a small number of gateway nodes hold those credentials. If you have 1,000 servers, you may not want all 1,000 to need API keys for your SIEM.
* **Network traffic control.** Gateways let you funnel outbound traffic through a controlled point in your network. Many environments restrict which machines can make outbound internet requests. Rather than opening direct egress for every host, route telemetry through gateways that sit in a DMZ or a network zone with permitted outbound access.
* **Offloading processing.** Filtering, parsing, sampling, and enrichment all consume CPU and memory, and running that work on the same host as your application can starve your workload. Gateways are dedicated, well-provisioned machines built specifically for this job. Move heavy processing to gateways so your agents stay lightweight.

There are secondary benefits as well. Gateways batch telemetry into fewer, larger API requests, which can help stay within rate limits and reduce overhead on your destinations. They also give you a single, centralized place to change destinations, add processors, or adjust routing without touching every agent in your fleet.

## When You Can Skip Gateways

Gateways add infrastructure, and infrastructure isn't free. There are cases where sending telemetry directly from agents to your destination is a reasonable choice:

* **Small or simple environments.** If you have a handful of servers, minimal processing needs, and your agents can reach your destination directly, a gateway may add complexity without meaningful benefit.
* **Cloud-native sources already flowing to your destination.** If you're already ingesting data into your destination through a managed service (for example, a SaaS integration or cloud-native pipeline) and don't need additional processing, filtering, or multi-destination routing, there may not be a reason to insert a gateway into that path.
* **Infrastructure cost outweighs the benefit.** At scale, the cost of running gateway infrastructure can be significant. If your telemetry doesn't require processing, credential isolation, or network control, and your destination can handle direct ingest from your agents, the infrastructure savings may be worth the trade-off.

That said, the problems gateways solve (credential sprawl, egress costs, processing overhead) tend to emerge gradually and become harder to address retroactively. It's worth revisiting the decision as your environment scales.

## Setting Up Gateways in Bindplane

Adding gateways to an existing Bindplane deployment requires three steps.

1. **Install gateway collectors.** Deploy one or more collectors on dedicated hosts to serve as gateways. Install the BDOT Collector the same way you would for an agent. See the [Collector Install](https://docs.bindplane.com/deployment) documentation for platform-specific steps.
2. **Create a gateway configuration.** Create a new configuration with a [Bindplane Gateway source](https://docs.bindplane.com/integrations/sources/bindplane-gateway), which listens for OTLP traffic on ports 4317 (gRPC) and 4318 (HTTP) by default. Add your destinations and any processors you want to run centrally. This is where you move processing that was previously running on your agents. Roll out this configuration to your gateway collectors.
3. **Point agents to the gateway.** Update your agent configurations to replace their current destinations with a [Bindplane Gateway destination](https://docs.bindplane.com/integrations/destinations/bindplane-gateway) that points to the gateway's address (or the load balancer in front of your gateway group).

<figure><img src="/files/Looh1CocInBlxL1jvOXc" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/eWQ638Aq1S4HLS8SBkUc" alt=""><figcaption></figcaption></figure>

## Sizing and Scaling Considerations

For specific resource requirements and throughput tables for both agents and gateways, see the [Sizing and Scaling](https://docs.bindplane.com/production-checklist/bindplane-otel-collector/sizing-and-scaling) documentation.

When planning your gateway fleet, size for both failure and maintenance. If one gateway goes down or is taken offline for an upgrade, the remaining gateways need enough capacity to handle the full load. Your network architecture also affects how many gateways you need. If your servers are spread across multiple cloud providers or data centers, you will need gateways in each environment. Deploy them close to the sources they serve to minimize latency and reduce egress costs.

If a gateway is struggling under load, adding another node is often more effective than increasing the instance size. Vertical scaling can hit diminishing returns where additional CPU and memory don't translate to higher throughput. That said, vertical scaling can still help when you're working with a fixed number of collectors.

Most gateway operations are stateless, which makes auto-scaling straightforward. Place your gateways behind a load balancer and scale the group based on CPU, memory, and network I/O. For details on health checks, internal collector metrics, and scaling configuration, see the [High Availability](https://docs.bindplane.com/production-checklist/bindplane-otel-collector/high-availability) documentation.

## Architecture Patterns

A single gateway is the simplest setup. Agents export to one gateway, which handles processing and forwards telemetry to your destinations. This works for small environments but offers no redundancy.

For production, use two or more gateway nodes behind a load balancer. If a node fails, the load balancer routes traffic to the remaining nodes automatically.

As your environment grows, you may want to split telemetry across multiple gateway groups. Common approaches include segmenting by region or data center (to reduce egress costs and latency), by application or team (to simplify processing rules and enable chargeback), or by telemetry type (to tune scaling for each signal independently). These patterns can be combined. A large enterprise might have gateway groups segmented by region, with separate pipelines per telemetry type within each group.

## Additional Considerations

### Push vs. Pull Sources on Gateways

In addition to receiving forwarded telemetry from agents, gateways may also collect directly from push-based sources like syslog or firewall logs on the same nodes. However, adding pull-based sources to a gateway group requires more care. With a push-based source, the sender decides which gateway to hit. With a pull-based source, every gateway independently reaches out to collect data. If you add an API-based source to a group of five gateways, each gateway may pull from that API independently, which could result in duplicate data.

Before adding any pull-based source to a gateway cluster, verify that it supports being consumed by multiple collectors simultaneously without duplication.

### Publicly Exposed Gateways

If you're collecting telemetry from endpoints that go on and off your corporate network, such as employee laptops, you may need gateways that are publicly accessible. This allows collectors to fail over to an external gateway when they're off-network rather than queuing data locally with no guarantee of delivery.

This introduces standard concerns around securing a public-facing service: authentication (the collector supports mTLS for certificate-based validation), DDoS protection, and appropriate load balancing. Every cloud provider offers tools for this, but specific recommendations will depend on your network and security requirements.

### Further Reading

* [Sizing and Scaling](https://docs.bindplane.com/production-checklist/bindplane-otel-collector/sizing-and-scaling)
* [High Availability](https://docs.bindplane.com/production-checklist/bindplane-otel-collector/high-availability)
* [Gateway Source](https://docs.bindplane.com/integrations/sources/bindplane-gateway)
* [Gateway Destination](https://docs.bindplane.com/integrations/destinations/bindplane-gateway)
* [GKE Gateway Load Balancer Guide](https://docs.bindplane.com/how-to-guides/kubernetes/google-kubernetes-engine-gateway-collector-load-balancer)


# High Availability

Learn how to set up a highly available OpenTelemetry Collector deployment for production environments.

### What Is High Availability (HA)?

Ensure telemetry collection and processing infrastructure works even if individual Collector instances fail.

### Why High Availability for the Collector?

* **Avoid data loss** from agent-mode collectors when exporting to a dead backend.
* **Ensure telemetry continuity** during rolling updates or infrastructure failures.
* **Enable horizontal scalability** for load-balancing traces, logs, and metrics.

{% hint style="info" %}
**NOTE**

Using **Agent-Gateway Architecture** is the recommended deployment pattern for high availability.
{% endhint %}

### Agent-Gateway Architecture

* Agent Collectors run on every host, container, or node.
* Gateway Collectors are centralized, scalable backend services receiving telemetry from agents.
* Each layer can be scaled independently and horizontally.
* For more on when to use agent-gateway architecture, see [Agents v. Gateways](https://docs.bindplane.com/~/revisions/computed_ZbjlSUvw6svhxVqnyLEy_e0db5f493e0ca00556b4d7b523ed53170f30d363/production-checklist/bindplane-otel-collector/agents-v.-gateways).

### Architecture

A typical high-availability OpenTelemetry Collector deployment consist of:

1. **Multiple Collector Instances**
   * Deployed across different availability zones/regions
   * Each instance capable of handling the full workload
   * Redundant storage for temporary data buffering
2. **Load Balancer**
   * Distributes incoming telemetry data
   * Health checks to detect collector availability
   * Session affinity for consistent routing
3. **Automatic Failover**
   * Occurs if a collector becomes unavailable
4. **Shared Storage Backend**
   * Persistent storage for collector state
   * Shared configuration management
   * Metrics and traces storage

### Sizing and Resource Requirements

View the [Sizing and Scaling](/production-checklist/bindplane-otel-collector/sizing-and-scaling) page for a more in-depth guide.

#### Gateway Collector Requirements

**Minimum Configuration**:

* 2 collectors behind a load balancer
* 2 CPU cores per collector
* 8GB memory per collector
* 60GB usable space for persistent queue per collector

#### Throughput-Based Sizing

The following table shows the number of collectors needed based on expected throughput. This assumes each collector has 4 CPU cores and 16GB of memory:

| Telemetry Throughput | Logs / second | Collectors |
| -------------------- | ------------- | ---------- |
| 5 GB/m               | 250,000       | 2          |
| 10 GB/m              | 500,000       | 3          |
| 20 GB/m              | 1,000,000     | 5          |
| 100 GB/m             | 5,000,000     | 25         |

It's important to over-provision your collector fleet to provide fault tolerance. If one or more collector systems fail or are brought offline for maintenance, the remaining collectors must have enough available capacity to handle the telemetry throughput.

#### Scaling

1. Monitor these metrics to determine when to scale:
   * CPU utilization
   * Memory usage
   * Network throughput
   * Queue length
   * Error rates
2. Configure auto-scaling based on:
   * CPU utilization > 70%
   * Memory usage > 80%
   * Request rate per collector

#### Load Balancer Configuration

Configure a load balancer.

1. Health check endpoint: `/health`
2. Health check interval: 30 seconds
3. Unhealthy threshold: 3 failures
4. Healthy threshold: 2 successes

View the [Load Balancing Best Practices, here](/production-checklist/bindplane-otel-collector/resilience#load-balancing-best-practices).

### Resilience

View the [Resilience](/production-checklist/bindplane-otel-collector/resilience) page for a more in-depth guide.

Configure:

1. [Batching](/production-checklist/bindplane-otel-collector/resilience#batch) - Aggregates telemetry signals before exporting them
2. [Retry](/production-checklist/bindplane-otel-collector/resilience#retry) - Retry sending telemetry batches when there is an error or a network outage.
3. [Persistent Queue](/production-checklist/bindplane-otel-collector/resilience#persistent-queuing) - Retries are stored in a sending queue on disk to guarantee persistence if a collector crashes.

#### Retry

For workloads that cannot afford to have telemetry dropped, consider increasing the `max_elapsed_time` significantly. Keep in mind that a large max elapsed time combined with a large backend outage will cause the collector to "buffer" a significant amount of telemetry to disk.

#### Persistent Queue

The sending queue has three important options:

* **Number of consumers**: Determines how many batches will be retried in parallel
* **Queue size**: Determines how many batches are stored in the queue
* **Persistent queuing**: Allows the collector to buffer telemetry batches to disk

### Monitoring and Maintenance

View the [Monitoring](/production-checklist/bindplane-otel-collector/monitoring) page for a more in-depth guide.

#### Health Monitoring

1. Set up monitoring for:
   * Collector instance health
   * Load balancer health
   * Data throughput
   * Error rates
   * Resource utilization
2. Configure alerts for:
   * Collector failures
   * High latency
   * Error rate thresholds
   * Resource exhaustion

#### Monitoring the Collectors

To monitor collector logs, set up a Bindplane Collector source that will send log files from the Collector itself:

1. Add a "Bindplane Collector" source to your configuration
2. Configure the source with default settings
3. Push the configuration to your collectors
4. View the logs in your destination of choice

### Best Practices

1. **Resource Allocation**
   * Size collectors for peak load
   * Include buffer for traffic spikes
   * Monitor resource usage
2. **Network Configuration**
   * Use dedicated networks
   * Configure appropriate timeouts
   * Enable TLS for security
3. **Data Management**
   * Implement data buffering
   * Configure appropriate batch sizes
   * Set up retry policies
4. **Security**
   * Enable TLS encryption
   * Implement authentication
   * Use network policies
   * Regular security updates
5. **Load Balancing**
   * Configure health checks to ensure collectors are ready to receive traffic
   * Ensure even connection distribution among collectors
   * Support both TCP/UDP and HTTP/gRPC protocols

### Troubleshooting

#### Common Issues

1. **Load Balancer Issues**
   * Check health check configuration
   * Verify network connectivity
   * Review security groups/firewall rules
2. **Collector Failures**
   * Check resource utilization
   * Review error logs
   * Verify configuration
3. **Data Loss**
   * Check buffer configuration
   * Verify exporter settings
   * Review retry policies


# Sizing and Scaling

### Collector

When the collector is running as a collector, you must be mindful of resource consumption in order to\
avoid starving other services. Generally, collectors consume very little resources because they\
are handling the telemetry of an individual system.

You can reference this table as a starting point for collector system requirements. The resource\
recommendations do not consider multiple exporters or processors. The addition of processors can\
impact performance significantly.

| Telemetry Throughput | Logs / second | Cores | Process Memory (MB)\* |
| -------------------- | ------------- | ----- | --------------------- |
| 200 MiB/m            | 10,000        | 0.25  | 300                   |
| 400 MB/m             | 20,000        | 0.5   | 300                   |
| 1 GB/m               | 50,000        | 1     | 300                   |
| 2 GB/m               | 100,000       | 2     | 500                   |

\* Process memory is the amount of memory the collector is expected to consume. The host system should have enough memory to satisfy the collector and all other services.

### Gateway

Gateway collectors receive telemetry over the network. Pairing them with a load balancer is recommended in order to provide fault tolerance and the ability to scale horizontally. Horizontal scaling is preferable because it provides fault tolerance and can eliminate exporter bottlenecks.

Gateway best practices:

* Minimum two collectors behind a load balancer
* Minimum 2 cores per collector
* Minimum 8GB memory per collector
* 60GB usable space for persistent queue per collector

When deciding how many collectors your workload requires, take the expected throughput or log rate\
and use this table as a starting point.

The table assumes that each collector has four CPU cores and 16GB of memory. The table does not account for processors. When adding processors, the compute requirements will increase.

| Telemetry Throughput | Logs / second | Collectors |
| -------------------- | ------------- | ---------- |
| 5 GB/m               | 250,000       | 2          |
| 10 GB/m              | 500,000       | 3          |
| 20 GB/m              | 1,000,000     | 5          |
| 100 GB/m             | 5,000,000     | 25         |

It is important to over provision your collector fleet in order to provide fault tolerance. If one or more collector systems fail or are brought offline for maintenance, the remaining collectors must have enough available capacity to handle the telemetry throughput.

When dealing with a fixed number of collectors, you can scale their CPU and memory vertically in order to increase throughput. See collector sizing table at the beginning of this page.


# Resilience

Reliable collector architecture can be obtained with the combination of retry, queue, and load balancing.

### Batch <a href="#batch" id="batch"></a>

Batching aggregates telemetry signals before exporting them. This reduces the number of outbound requests, improving throughput and reducing load on both the collector and backend systems.

Batching helps with retry efficiency. If an export fails, retrying a batch is more efficient than retrying individual items.

#### Configuration

The batch processor can be configured with a timeout and a maximum batch size to prevent excessive memory usage.

<figure><img src="/files/ZwgL5KPG9DhM5MAu38sz" alt="Bindplane docs - Resilience - image 1"><figcaption></figcaption></figure>

### Retry

Bindplane destinations have the ability to retry sending telemetry batches when there is an error or a network outage.

#### Configuration

Retry is enabled by default on all destinations that support it. By default, failed requests will be retried after five seconds and progressively back off for up to 30 seconds. After five minutes, requests will be permanently dropped.

<figure><img src="/files/gilhAgtjTDhxAfs9Ahxo" alt="Bindplane docs - Resilience - image 2"><figcaption></figcaption></figure>

#### Best Practices

For workloads that cannot afford to have telemetry dropped, the five-minute maximum elapsed time should be increased significantly. Keep in mind that a large max elapsed time combined with a large backend outage will cause the collector to "buffer" a significant amount of telemetry to disk. Gateway collectors should be provisioned with disks large enough to sustain an outage lasting hours or days.

If overwhelming the backend during an outage recovery is not a concern, reducing the max interval to match the initial interval can decrease the time it will take to recover from an outage, as telemetry sending will be retried more frequently.

### Sending Queue

When telemetry requests are retried, they are first stored in a sending queue. This sending queue is stored on disk in order to guarantee persistence in the event of a collector system crash.

#### Configuration

The sending queue has three options

* Number of consumers
* Queue size
* Persistent queuing

<figure><img src="/files/UD7KBk3WIxi6ch7oru2J" alt="Bindplane docs - Resilience - image 3"><figcaption></figcaption></figure>

#### Number of Consumers

This option determines how many batches will be retried in parallel. For example, 10 consumers will retry 10 batches at a time. If each batch contains 100 logs, the collector will retry 1,000 logs.

Generally, the default value of 10 is suitable for low and high-volume systems. Decreasing this number will cause the collector to recover from large outages slower, but will keep resource consumption low. Alternatively, increasing this number will mean that the collector is going to put more strain on the backend because it will be retrying more batches in parallel.

#### Queue Size

The queue size option determines how many batches are stored in the queue. When the queue is at capacity, additional batches will be dropped.

Keep in mind that the queue size is the number of batches. You can calculate the number of metrics, traces, and logs by taking the batch size and multiplying it by the queue size. You can use the Batch processor to configure batch sizes.

#### Persistent Queuing

Persistent queue is a feature that allows the Bindplane Collector to buffer telemetry batches to disk when a request to the backend fails. The Bindplane Collector supports persistent queue by default and it is recommended that it be enabled at all times. Persistent queue protects against data loss if the collector system is suddenly shut down due to a crash or other outside factors.

If persistent queue is disabled, failed telemetry batches will be buffered in memory. This will increase performance on high throughput systems, at the expense of reliability. During an outage, memory buffering will increase memory consumption drastically and can cause the Bindplane Collector to crash if the system runs out of memory.

### Load Balancing

Load balancing allows you to operate a fleet of gateway agents for increased performance and redundancy. Load balancers allow you to scale your gateway fleet horizontally and sustain failures without ensuring an outage.

The Bindplane collector can work with a wide range of load balancers when operating in gateway mode. This documentation will not discuss any particular option, as most popular load-balancing solutions support the required options for operating multiple collectors reliably.

### Load balancing best practices

* Health checks. The load balancer should be configured to ensure the collector is ready to receive traffic.
* Even connection distribution. Connections should be distributed evenly among collectors.
* Protocol support: OpenTelemetry has a wide range of network-based receivers. In order to support all of them, the load balancer should support transport protocols TCP and UDP as well as application protocols HTTP and gRPC.

### Use Cases

The following source types can be used with a load balancer:

* OTLP
* Syslog
* TCP / UDP
* Splunk HEC
* Fluent Forward

Any source type that receives telemetry from remote systems over the network is a suitable candidate for load balancing.


# Monitoring

To monitor collector logs, we will set up the Bindplane Distro for OpenTelemetry (BDOT) Collector source that will send log files from the Collector itself. These logs contain information about the health of your BDOT Collector.

For this, we will need an already deployed collector from any existing configuration you already have set up. No additional server configuration is needed, we will just go into any of the configurations you would like to gather Collector logs from and click 'Add Source'. From there select the 'Bindplane Collector' source like in the example below:

<figure><img src="/files/HCRArmQQeWY4p89lzCLt" alt="Bindplane docs - Monitoring - image 1"><figcaption></figcaption></figure>

We can leave this on default as well for this example, and simply click 'Save':

<figure><img src="/files/exL3rIMTVF6jtZ4RQk5v" alt="Bindplane docs - Monitoring - image 2"><figcaption></figcaption></figure>

All that is left is to push out the configuration to the Collectors by running a "Start Rollout". With that source rolled out to the Collector machines, your Bindplane Collector logs will now be sent to the destination of your choice. Below is an example of those logs on a Google Cloud Destination:

<figure><img src="/files/cdVBuEtnmwqZE99Q5CgK" alt="Bindplane docs - Monitoring - image 3"><figcaption></figcaption></figure>

{% hint style="info" %}
**NOTE**

📘 Adding processors to this collector could cause problems, as it would create entries in this same log file, which could lead to infinite error messages. Add any processors sparingly and thoroughly test afterward to ensure it is following the intended behavior.
{% endhint %}

If you haven't yet, you can also set up [monitoring of the Bindplane server itself.](/production-checklist/bindplane/monitoring-bindplane)


# Networking Requirements

The Bindplane OTel Collector requires network access to the Bindplane Server, as well as any telemetry sources and destinations you configure.

The Bindplane OTel Collector (BDOT) requires network connectivity to the Bindplane Server and any telemetry sources or destinations it interacts with.

Most environments can operate with a minimal set of required connections, but certain optional features may use additional endpoints.

### Required Connections

#### 1. Connection to Bindplane Server

The collector must be able to communicate with the Bindplane Server over the management port.

| Deployment Type       | Default Port | Protocols                | Notes                      |
| --------------------- | ------------ | ------------------------ | -------------------------- |
| Bindplane Self-Hosted | `3001`       | HTTP(S), WebSocket, gRPC | User-configurable port     |
| Bindplane Cloud       | `443`        | HTTP(S), WebSocket, gRPC | Secure connection required |

{% hint style="warning" %}
**IMPORTANT!**

The Bindplane server management port supports multiple protocols on a single port. Since WebSocket and gRPC both require connection upgrades from HTTP/1 to HTTP/2, any proxy or load balancer in front of the server must support these upgrades.
{% endhint %}

#### 2. Connection to Telemetry Destinations

Collectors must have outbound network access to any telemetry destinations configured in their pipelines (for example, Google Cloud Logging, Splunk, or Prometheus).

* The specific ports, protocols, and endpoints depend on the destination.
* Each integration’s documentation provides detailed network requirements.

{% hint style="info" %}
**NOTE**

See the [Destinations](/integrations/destinations) section for destination-specific networking details.
{% endhint %}

#### 3. Connection to Remote Telemetry Sources

Some sources pull data from remote services over HTTP or other network APIs.

In these cases, outbound connectivity to the remote service endpoints is required.

* Examples include REST API sources, cloud monitoring APIs, or other remote ingestion endpoints.
* Each source’s configuration guide documents its own networking prerequisites.

{% hint style="info" %}
**NOTE**

See the [Sources](/integrations/sources) section for source-specific networking details.
{% endhint %}

### Optional Connections

#### Collector Version Updates

Collectors may optionally connect to the Bindplane update service to check for newer releases.

| Purpose                     | Endpoint                                                                                                                 | Port  | Notes                 |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ----- | --------------------- |
| Collector Version Detection | `https://bdot.bindplane.com`                                                                                             | `443` | Default since v1.94.0 |
| Legacy (Older Versions)     | GitHub endpoints as documented in [Server Network Requirements](/production-checklist/bindplane/networking-requirements) | `443` | Deprecated behavior   |

{% hint style="info" %}
**NOTE**\
This connection is optional and only used when update checks are initiated from the Bindplane Server.
{% endhint %}

### Summary

| Connection Type           | Required          | Endpoint / Port                                                                    | Protocols                | Notes                    |
| ------------------------- | ----------------- | ---------------------------------------------------------------------------------- | ------------------------ | ------------------------ |
| Bindplane Server          | ✅                 | https\://\<bindplane-server>:3001 (Self-Hosted) or <https://app.bindplane.com:443> | HTTP(S), WebSocket, gRPC | Core communication       |
| Telemetry Destinations    | ✅                 | Varies per integration                                                             | Varies                   | See integration docs     |
| Remote Sources            | ✅ (if configured) | Varies per source                                                                  | Varies                   | Outbound access required |
| Collector Version Updates | Optional          | <https://bdot.bindplane.com> (or GitHub legacy)                                    | HTTPS                    | For update checks        |


# Secret Management

Best practices for managing the secrets used to connect to your sources, destinations, and the Bindplane Control Plane.

The Bindplane Collector relies on the following configuration files:

* **manager.yaml** - Used to configure connectivity to the Bindplane server over OpAMP
  * When the collector runs for the first time, the `Manager.yaml` will be bootstrapped. When the `OPAMP_SECRET_KEY` and `OPAMP_ENDPOINT` environment variables are present, the collector will write the `manager.yaml` file to disk, automatically injecting the `${env:..}` mapping for you.
* **config.yaml -** Used to define what sources, processors, destinations, and other OTel components are used by the Bindplane Distro for OpenTelemetry Collector (BDOT) at runtime.

#### Choose an Approach

The following approaches allow for secure secret management of collector secret values.

| Approach                                                                                                                                                      | Mechanism                                                           | Use When                                                                                   |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| [**ENV Provider**](https://docs.bindplane.com/production-checklist/bindplane/secrets-management/using-environment-variables#step-2-environment-configuration) | `${env:VAR}` in `manager.yaml` / `config.yaml`, resolved at startup | You inject secrets at runtime                                                              |
| [**AES Provider** ](https://docs.bindplane.com/configuration/bindplane-otel-collector/configuration-encryption)(recommended)                                  | `${aes:CIPHER_TEXT}` + `OTEL_AES_CREDENTIAL_PROVIDER`               | You must persist or commit `manager.yaml`, or environment-variable leakage is a high risk. |

#### Configure the collector environment

Set the collector's environment variables on each platform. The collector reads `OPAMP_SECRET_KEY`, `OTEL_AES_CREDENTIAL_PROVIDER`, and any `${env:...}` pipeline variables from its service environment at startup.

{% tabs %}
{% tab title="Windows" %}
This can be done via PowerShell:

**Run Powershell as Administrator:**

{% code overflow="wrap" lineNumbers="true" %}

```powershell
# set-collector-env.ps1
# Usage: .\set-collector-env.ps1 "OPAMP_SECRET_KEY=<secret>" "OTEL_AES_CREDENTIAL_PROVIDER=<key>"

param(
    [Parameter(Mandatory, ValueFromRemainingArguments)]
    [string[]]$Variables
)

$service = "observiq-otel-collector"
$regPath = "HKLM:\SYSTEM\CurrentControlSet\Services\$service"

Set-ItemProperty -Path $regPath -Name Environment -Value $Variables -Type MultiString
Restart-Service $service

Write-Host "Set $($Variables.Count) variable(s) and restarted $service."
```

{% endcode %}

Or using the Registry Editor:

**Open the service's registry key.**

1. Press `Win + R`, type `regedit`, and press Enter.
2. Approve the User Account Control prompt.
3. Navigate to `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\observiq-otel-collector`.

**Create or open the Environment value.**

1. Right-click the `observiq-otel-collector` key and choose New > Multi-String Value.
2. Name it `Environment`. If the value already exists, skip to editing it.
3. Double-click `Environment` to open the editor.

**Add your variables.**

1. Enter each variable on its own line as `NAME=value` — for example, `OPAMP_SECRET_KEY=<secret>`.
2. Add additional variables (such as `OTEL_AES_CREDENTIAL_PROVIDER=<key>`) on separate lines.
3. Click OK.

**Restart the service.**

1. Press `Win + R`, type `services.msc`, and press Enter.
2. Right-click Bindplane OTel Collector and choose Restart.
3. Confirm the variables took effect by checking the collector logs.
   {% endtab %}

{% tab title="Systemd" %}
**Open a drop-in override for the service.**

1. Run `sudo systemctl edit observiq-otel-collector`.
2. This creates an override at `/etc/systemd/system/observiq-otel-collector.service.d/override.conf` without touching the packaged unit.

#### Add your variables

For static values, add them directly under `[Service]`:

```ini
[Service]
Environment=OPAMP_SECRET_KEY=<secret>
Environment=OTEL_AES_CREDENTIAL_PROVIDER=<key>
```

To inject secrets from a manager at startup:

```ini
[Service]
ExecStartPre=/usr/local/bin/fetch-secrets.sh
EnvironmentFile=/run/secrets/collector.env
```

**Apply the changes.**

1. Reload the unit files: `sudo systemctl daemon-reload`.
2. Restart the collector: `sudo systemctl restart observiq-otel-collector`.
3. Confirm the variables took effect by checking the collector logs.
   {% endtab %}

{% tab title="macOS" %}
**Open the collector's launchd service file.**

1. Open `/Library/LaunchDaemons/com.observiq.collector.plist` in a text editor with `sudo`.
2. Locate the `EnvironmentVariables` dict, or add one if it isn't present.

**Add your variables.**

Add each variable as a `key`/`string` pair inside the dict:

```xml
<key>EnvironmentVariables</key>
<dict>
    <key>OPAMP_SECRET_KEY</key>
    <string>secret</string>
    <key>OTEL_AES_CREDENTIAL_PROVIDER</key>
    <string>Encryption key</string>
</dict>
```

**Reload the service.**

1. Unload it: `sudo launchctl unload /Library/LaunchDaemons/com.observiq.collector.plist`.
2. Load it again: `sudo launchctl load /Library/LaunchDaemons/com.observiq.collector.plist`.
3. Confirm the variables took effect by checking the collector logs.
   {% endtab %}
   {% endtabs %}

### Resulting file contents

The recommended patterns resolve secrets at startup instead of storing them in plaintext on disk. Here's what each file looks like before and after.

#### **manager.yaml**

Before - the secret key is written in plaintext:

```yaml
endpoint: wss://bindplane.example.com/v1/opamp
secret_key: 3d83f0cb-2567-42c7-ada6-960842924d11
labels: "configuration=linux-hosts"
```

After - the value resolves from the environment at startup:

***ENV provider:***

```yaml
endpoint: wss://bindplane.example.com/v1/opamp
secret_key: ${env:OPAMP_SECRET_KEY}
labels: "configuration=linux-hosts"
```

***AES Provider:***

```yaml
endpoint: wss://bindplane.example.com/v1/opamp
secret_key: ${aes:YTgzZjBjYjI1Njc0MmM3YWRhNjk2MDg0MjkyNGQxMQ}
labels: "configuration=linux-hosts"
```

**config.yaml**

Before - a destination credential is written in plaintext:

```yaml
exporters:
  otlphttp/backend:
    endpoint: https://ingest.example.com
    headers:
      authorization: "Bearer sk_live_abcd1234..."
```

After - the credential resolves from the environment at startup:

***ENV provider:***

```yaml
exporters:
  otlphttp/backend:
    endpoint: https://ingest.example.com
    headers:
      authorization: "Bearer ${env:BACKEND_API_TOKEN}"
```

***AES Provider:***

```yaml
exporters:
  otlphttp/backend:
    endpoint: https://ingest.example.com
    headers:
      authorization: ${aes:YTgzZjBjYjI1Njc0MmM3YWRhNjk2MDg0MjkyNGQxMQ}
```


# Configuration

Configuration guides for Bindplane Server, OpenTelemetry Collectors, and CLI components.

## [Bindplane Server (Self-Hosted)](/configuration/bindplane)

Configure core server settings including:

* Authentication (Active Directory, OpenID Connect)
* Storage (PostgreSQL, Bolt)
* Networking (TLS, proxy, NATS)
* Monitoring and backup
* Version migration

## [Bindplane OTel Collector](/configuration/bindplane-otel-collector)

Configure the Bindplane OpenTelemetry Collector:

* Agent lifecycle management
* Extensions and health checks
* Security and encryption
* Data buffering and retries
* Version updates

## Next Steps

* [Configure Server](/configuration/bindplane)
* [Set up Collectors](/configuration/bindplane-otel-collector)
* [Configure Authentication](/configuration/bindplane/authentication)
* [Set up Monitoring](/production-checklist/bindplane/monitoring-bindplane)


# Bindplane Server (Self-Hosted)

Complete configuration reference for a self-hosted Bindplane Server.

## Options

Bindplane server configuration can be found at `/etc/bindplane/config.yaml`.

Bindplane will look for flags, environment variables, and a configuration file, with precedence: flags > environment variables > configuration file.

Server and client configurations can be bootstrapped using the `init` command. See the [initialization section](#initialization).

For detailed examples, see the [configurations section](#example-configurations).

### License

The Bindplane license key. This option is required for server startup. If you do not have a license, you can request one [here](https://bindplane.com/download).

<table><thead><tr><th width="156.9296875">Option</th><th>Environment Variable</th></tr></thead><tbody><tr><td>license</td><td>BINDPLANE_LICENSE</td></tr></tbody></table>

### Host

IP Address the Bindplane server binds to. This can be a single address or `0.0.0.0` for all interfaces.

| Option       | Flag   | Environment Variable | Default     |
| ------------ | ------ | -------------------- | ----------- |
| network.host | --host | BINDPLANE\_HOST      | `127.0.0.1` |

### Port

TCP port the Bindplane server binds to. This must be an unprivileged port when running Bindplane as a non-root user.

| Option       | Flag   | Environment Variable | Default |
| ------------ | ------ | -------------------- | ------- |
| network.port | --port | BINDPLANE\_PORT      | `3001`  |

### Remote URL

URL used to reach the Bindplane server. This must be set in all client and server configurations\
and must be a valid URL with a protocol (HTTP / HTTPS), hostname or IP address, and port.

If the server is behind a proxy or load balancer, the proxy URL can be used.

<table><thead><tr><th width="173.24609375">Option</th><th width="116.00390625">Flag</th><th width="235.5546875">Environment Variable</th><th>Default</th></tr></thead><tbody><tr><td>network.remoteURL</td><td>--remote-url</td><td>BINDPLANE_REMOTE_URL</td><td><code>http://127.0.0.1:3001</code></td></tr></tbody></table>

### Web URL

Optional URL used to override the [Remote URL](#remote-url) for interactions with the web interface. When set, some features will use the Web URL instead of the Remote URL. For example, invitation links will use Web URL.

When Web URL is not set, Remote URL is used.

<table><thead><tr><th width="175.6796875">Option</th><th width="102.67578125">Flag</th><th>Environment Variable</th><th>Default</th></tr></thead><tbody><tr><td>network.webURL</td><td>--web-url</td><td>BINDPLANE_WEB_URL</td><td><code>http://127.0.0.1:3001</code></td></tr></tbody></table>

#### **Kubernetes Example**

Bindplane is deployed to a Kubernetes cluster. Bindplane is configured with the following:

* Remote URL: `http://bindplane.default.svc.cluster.local:3001`
* Web URL: `https://bindplane.my-corp.net`

In this case, agents will connect to Bindplane using the remote URL. This allows agents to connect\
directly to Bindplane without traversing over ingress.

Invitation links for web users will use the external endpoint, `https://bindplane.my-corp.net`.

### CorsAllowedOrigins

A list of origin domains allowed to make requests to Bindplane. It should at least contain the domain of the hosted UI. An empty or null value matches all origins. A wildcard "\*" is also allowed to match all origins.

In most cases, this value can be the same as `network.remoteURL`.

<table><thead><tr><th width="232.43359375">Option</th><th width="82.421875">Flag</th><th>Environment Variable</th><th width="100">Default</th></tr></thead><tbody><tr><td>network.corsAllowedOrigins</td><td>--cors-allowed-origins</td><td>BINDPLANE_CORS_ALLOWED_ORIGINS</td><td><code>*</code></td></tr></tbody></table>

### Logging

Log output (`file` or `stdout`). When log output is set to `file`, a log file path can be specified.

<table><thead><tr><th width="150.765625">Option</th><th width="100">Flag</th><th>Environment Variable</th><th width="145.0859375">Default</th></tr></thead><tbody><tr><td>logging.output</td><td>--logging-output</td><td>BINDPLANE_LOGGING_OUTPUT</td><td><code>file</code></td></tr><tr><td>logging.filePath</td><td>--logging-file-path</td><td>BINDPLANE_LOGGING_FILE_PATH</td><td><code>~/.bindplane/bindplane.log</code></td></tr><tr><td>logging.level</td><td>--logging-level</td><td>BINDPLANE_LOGGING_LEVEL</td><td><code>info</code></td></tr></tbody></table>

Server installations will use `/var/log/bindplane/bindplane.log`, which is set using an environment variable in the `systemd` service configuration.

Log files are rotated and gzip compressed, and cleaned up automatically by Bindplane. Log files have a max size of 100mb and up to 10 rotates or 30 days of age, whichever comes first. Using an external utility such as `logrotate` is not recommended.

### Metrics

Bindplane can be configured to forward metrics to an OpenTelemetry collector. The easiest way to get up and running is to deploy a collector on the same machine Bindplane is installed on. The collector should be configuted with the OpenTelemetry source. Configure Bindplane to send metrics over localhost.

```yaml
metrics:
  interval: 1m
  type: otlp
  otlp:
    endpoint: 127.0.0.1:4317
    insecure: true
```

Once configured, the managed collector can forward the metrics to the destination of your choice.

Metrics are sent to OpenTelemetry collectors using the `gRPC` protocol.

<table><thead><tr><th width="186.7265625">Option</th><th width="118.96875">Flag</th><th>Environment Variable</th><th width="102.140625">Default</th></tr></thead><tbody><tr><td>metrics.type</td><td>--metrics-type</td><td>BINDPLANE_METRICS_TYPE</td><td></td></tr><tr><td>metrics.interval</td><td>--metrics-interval</td><td>BINDPLANE_METRICS_INTERVAL</td><td><code>1m0s</code></td></tr><tr><td>metrics.otlp.endpoint</td><td>--metrics-otlp-endpoint</td><td>BINDPLANE_METRICS_OTLP_ENDPOINT</td><td></td></tr><tr><td>metrics.otlp.insecure</td><td>--metrics-otlp-insecure</td><td>BINDPLANE_METRICS_OTLP_INSECURE</td><td></td></tr></tbody></table>

### Tracing

Bindplane supports configuration to enable tracing. `tracing.type` can be set to `google` or `otlp`.

<table><thead><tr><th width="123.29296875">Option</th><th width="137.2109375">Flag</th><th>Environment Variable</th><th width="134.4921875">Default</th></tr></thead><tbody><tr><td>tracing.type</td><td>--tracing-type</td><td>BINDPLANE_TRACING_TYPE</td><td></td></tr></tbody></table>

When `tracing.type` is set to `otlp`, some more configuration is possible.

<table><thead><tr><th width="180.6015625">Option</th><th width="126.23046875">Flag</th><th>Environment Variable</th><th width="99.39453125">Default</th></tr></thead><tbody><tr><td>tracing.otlp.endpoint</td><td>--tracing-otlp-endpoint</td><td>BINDPLANE_TRACING_OTLP_ENDPOINT</td><td></td></tr><tr><td>tracing.otlp.insecure</td><td>--tracing-otlp-insecure</td><td>BINDPLANE_TRACING_OTLP_INSECURE</td><td><code>FALSE</code></td></tr></tbody></table>

## TLS

Bindplane supports server side TLS and mutual TLS. See [the tls examples](#tls) for detailed usage.

<table><thead><tr><th width="220.12109375">Option</th><th width="178.42578125">Flag</th><th>Environment Variable</th></tr></thead><tbody><tr><td>network.tlsCert</td><td>--tls-cert</td><td>BINDPLANE_TLS_CERT</td></tr><tr><td>network.tlsKey</td><td>--tls-key</td><td>BINDPLANE_TLS_KEY</td></tr><tr><td>network.tlsCA</td><td>--tls-ca</td><td>BINDPLANE_TLS_CA</td></tr><tr><td>network.tlsSkipVerify</td><td>--tls-skip-verify</td><td>BINDPLANE_TLS_SKIP_VERIFY</td></tr><tr><td>network.tlsMinVersion</td><td>--tls-min-version</td><td>BINDPLANE_TLS_MIN_VERSION</td></tr></tbody></table>

### Server

* `network.tlsCert`: Enables server-side TLS
* `network.tlsKey`: Enables server-side TLS
* `network.tlsCA`: Enables mutual TLS

### Client

* `network.tlsCA`: Allows the client to trust the server certificate. Not required if the host operating system already trusts the server certificate.
* `network.tlsCert`: Enables mutual TLS
* `network.tlsKey`: Enables mutual TLS
* `network.tlsSkipVerify`: Skip server certificate verification

## Storage Backend

Bindplane supports two storage backends,`postgres` and `bbolt`. Bbolt is deprecated and should\
not be used for new installations of Bindplane.

<table><thead><tr><th width="128.34375">Option</th><th width="163.8203125">Flag</th><th>Environment Variable</th><th width="100">Default</th></tr></thead><tbody><tr><td>store.type</td><td>--store-type</td><td>BINDPLANE_STORE_TYPE</td><td><code>postgres</code></td></tr></tbody></table>

### Postgres

Postgres can be used as a local or remote storage backend. Postgres storage is enabled\
when `store.type` is set to `postgres`. Configuring both authentication and TLS for Postgres is recommended.

**Postgres is a Bindplane Enterprise feature.**

<table><thead><tr><th width="226.9140625">Option</th><th width="100">Flag</th><th>Environment Variable</th><th width="109.75">Default</th></tr></thead><tbody><tr><td>store.postgres.host</td><td>--postgres-host</td><td>BINDPLANE_POSTGRES_HOST</td><td><code>localhost</code></td></tr><tr><td>store.postgres.port</td><td>--postgres-port</td><td>BINDPLANE_POSTGRES_PORT</td><td><code>5432</code></td></tr><tr><td>store.postgres.database</td><td>--postgres-database</td><td>BINDPLANE_POSTGRES_DATABASE</td><td><code>bindplane</code></td></tr><tr><td>store.postgres.sslmode</td><td>--postgres-ssl-mode</td><td>BINDPLANE_POSTGRES_SSL_MODE</td><td><code>disable</code></td></tr><tr><td>store.postgres.sslrootcert</td><td>--postgres-ssl-root-cert</td><td>BINDPLANE_POSTGRES_SSL_ROOT_CERT</td><td>Optional</td></tr><tr><td>store.postgres.sslcert</td><td>--postgres-ssl-cert</td><td>BINDPLANE_POSTGRES_SSL_CERT</td><td>Optional</td></tr><tr><td>store.postgres.sslkey</td><td>--postgres-ssl-key</td><td>BINDPLANE_POSTGRES_SSL_KEY</td><td>Optional</td></tr><tr><td>store.postgres.username</td><td>--postgres-username</td><td>BINDPLANE_POSTGRES_USERNAME</td><td></td></tr><tr><td>store.postgres.password</td><td>--postgres-password</td><td>BINDPLANE_POSTGRES_PASSWORD</td><td></td></tr><tr><td>postgres.maxConnections</td><td>--postgres-max-connections</td><td>BINDPLANE_POSTGRES_MAX_CONNECTIONS</td><td><code>100</code></td></tr><tr><td>postgres.maxIdleConnections</td><td>--postgres-max-idle-connections</td><td>BINDPLANE_POSTGRES_MAX_IDLE_CONNECTIONS</td><td><code>50</code></td></tr><tr><td>postgres.maxIdleTime</td><td>--postgres-max-idle-time</td><td>BINDPLANE_POSTGRES_MAX_IDLE_TIME</td><td><code>1m0s</code></td></tr><tr><td>postgres.maxLifetime</td><td>--postgres-max-lifetime</td><td>BINDPLANE_POSTGRES_MAX_LIFETIME</td><td><code>6h</code></td></tr><tr><td>postgres.schema</td><td>--postgres-schema</td><td>BINDPLANE_POSTGRES_SCHEMA</td><td><code>default</code></td></tr></tbody></table>

Example Postgres configuration:

```yaml
name: default
apiVersion: bindplane.observiq.com/v1
auth:
  username: user
  password: password
network:
  host: 0.0.0.0
  port: '3001'
  remoteURL: http://10.99.1.10:3001
store:
  type: postgres
  postgres:
    host: localhost
    port: '5432'
    database: bindplane
    sslmode: disable
    username: postgres
    password: password
    maxConnections: 200
```

#### **Connection Management**

Bindplane has several Postgres connection options. The most important option is max connections. You should ensure the value does not exceed the number of available connections your PostgreSQL server can accept. When operating Bindplane in [high availability](/production-checklist/bindplane/high-availability) it is important to consider the total number of connections that can be created across all Bindplane instances.

#### **Transport Layer Security (TLS)**

Bindplane supports connecting to Postgres using TLS. TLS can be enabled by configuring the SSL mode options.

<table><thead><tr><th width="142.83984375">SSL Mode</th><th>Description</th></tr></thead><tbody><tr><td>disable</td><td>No SSL; connection is made in plain text.</td></tr><tr><td>require</td><td>SSL is used, but the server's certificate is not verified.</td></tr><tr><td>verify-ca</td><td>SSL is used, and the server's certificate is verified against a trusted CA.</td></tr><tr><td>verify-full</td><td>SSL is used, and the server's certificate is fully verified, including hostname validation.</td></tr></tbody></table>

You can learn more about Postgres SSL modes [here](https://www.postgresql.org/docs/current/libpq-ssl.html).

When using `verify-ca` or `verify-full`, your server's operating system's trust store will be used\
to verify the Postgres certificate. Alternatively, you can configure the `store.postgres.sslrootcert`\
option.

```yaml
store:
  type: postgres
  postgres:
    host: localhost
    port: '5432'
    database: bindplane
    username: postgres
    password: password
    maxConnections: 200
    sslmode: verify-ca
    sslrootcert: /etc/bindplane/ca.crt
```

{% hint style="info" %}
**NOTE**

When configuring certificate file paths, ensure the `bindplane` user has filesystem permissions\
to read the files.
{% endhint %}

If your Postgres server is enforcing client certificate authentication (mutual TLS), you can configure\
the `sslcert` and `sslkey` options.

```yaml
store:
  type: postgres
  postgres:
    sslmode: verify-full
    sslrootcert: /etc/bindplane/ca.crt
    sslcert: /etc/bindplane/client.crt
    sslkey: /etc/bindplane/client.key
```

If you rotate your client certificates frequently, you can set the `maxLifetime` options to limit\
how long connections can live. The default value is six hours (`6h`). This means, every six hours\
connections will be replaced. When a connection is created, it reads the SSL files from disk. Make sure\
to rotate your SSL certificates before the previous certificate has expired.

## Event Bus

Bindplane uses an event bus to communicate between components within Bindplane. When operating Bindplane with multiple servers, the event bus can be used to send events between Bindplane servers.

<table><thead><tr><th width="174.8984375">Option</th><th width="188.09375">Flag</th><th>Environment Variable</th></tr></thead><tbody><tr><td>eventBus.type</td><td>--event-bus-type</td><td>BINDPLANE_EVENT_BUS_TYPE</td></tr></tbody></table>

The event bus type supports the following options:

* [local](#local-event-bus)
* [nats](#nats-event-bus)
* [googlePubSub](#google-pub-sub-event-bus)

### Local Event Bus

The local event bus is the default event bus used by Bindplane. The local event bus does not have\
a configuration. It can be used by setting the event bus type to `local`.

### Google Pub/Sub Event Bus

The [Google Pub/Sub](https://cloud.google.com/pubsub) event bus can be used when operating multiple Bindplane servers.

<table><thead><tr><th width="207.39453125">Option</th><th width="135.74609375">Flag</th><th>Environment Variable</th></tr></thead><tbody><tr><td>eventBus.googlePubSub.projectID</td><td>--event-bus-type</td><td>BINDPLANE_GOOGLE_PUB_SUB_PROJECT_ID</td></tr><tr><td>eventBus.googlePubSub.credentialsFile</td><td>--google-pub-sub-credentials-file</td><td>BINDPLANE_GOOGLE_PUB_SUB_CREDENTIALS_FILE</td></tr><tr><td>eventBus.googlePubSub.topic</td><td>--google-pub-sub-topic</td><td>BINDPLANE_GOOGLE_PUB_SUB_TOPIC</td></tr></tbody></table>

When operating Bindplane on Google Compute Engine with the [pub/sub" oath scopes](https://developers.google.com/identity/protocols/oauth2/scopes#pubsub) enabled, Bindplane will handle authentication automatically.

The configuration is simple and requires only the `projectID` and `topic` options.

```yaml
eventBus:
  type: googlePubSub
  googlePubSub:
    projectID: myproject
    topic: bindplane
```

When running outside of Google Cloud, or without the Pub/Sub oauth scopes, you can use a [Google Service Account Credential](https://cloud.google.com/iam/docs/keys-create-delete) by setting the `credentialsFile` option. This credentials file must be installed on the Bindplane server's filesystem and be readable by the `bindplane` user.

```yaml
eventBus:
  type: googlePubSub
  googlePubSub:
    projectID: myproject
    credentialsFile: /etc/bindplane/google-credentials.json
    topic: bindplane
```

Bindplane will manage its own Pub/Sub subscription. Subscriptions are created and named based on\
the server's hostname. Bindplane will attempt to clean up its subscription on shutdown. Subscriptions\
are automatically cleaned up by Google Cloud if they have been disconnected for more than one day.

### NATS Event Bus

[NATS](https://github.com/nats-io/nats-server) can be used as the event bus for Bindplane Enterprise and is a good option for distributed on-prem deployments. NATS is embedded into Bindplane and does not require external infrastructure.

See the [NATS Configuration](/configuration/bindplane/nats-as-event-bus) documentation for more information.

## Server Session Secret

A UUIDv4 is used for encoding web UI login cookies. This should be a new random UUIDv4. This value should be different than `auth.secretKey`.

<table><thead><tr><th width="179.5234375">Option</th><th width="164.81640625">Flag</th><th>Environment Variable</th></tr></thead><tbody><tr><td>auth.sessionSecret</td><td>--session-secret</td><td>BINDPLANE_SESSION_SECRET</td></tr></tbody></table>

## Prometheus

{% hint style="info" %}
**NOTE**

It is not necessary to make changes to the Bindplane Prometheus configuration when using Bindplane's bundled Prometheus.
{% endhint %}

### Base Configuration

<table><thead><tr><th width="262.03515625">Option</th><th>Description</th></tr></thead><tbody><tr><td><code>prometheus.enable</code></td><td>Whether or not to enable Prometheus as the measurement backend.</td></tr><tr><td><code>prometheus.enableRemote</code></td><td>Whether or not to use a remote Prometheus instance. When disabled, Bindplane will manage a local Prometheus child process.</td></tr><tr><td><code>prometheus.localFolder</code></td><td>The directory where the Prometheus binary and dependencies are located.</td></tr><tr><td><code>prometheus.host</code></td><td>The hostname or ip address of the Prometheus instance.</td></tr><tr><td><code>prometheus.port</code></td><td>The port of the Prometheus instance's API.</td></tr><tr><td><code>prometheus.queryPathPrefix</code></td><td>The path prefix of the query endpoint. This parameter is useful if using a Prometheus compatible system such as Mimir.</td></tr></tbody></table>

### Authentication

{% hint style="info" %}
**NOTE**

Authentication is supported for remote Prometheus deployments.
{% endhint %}

Bindplane supports two authentication modes.

* No authentication
* Basic authentication

Prometheus does not use authentication by default. Follow the Prometheus [Basic Auth Password Hashing](https://prometheus.io/docs/guides/basic-auth/#hashing-a-password) documentation for more information.

<table><thead><tr><th width="254.6796875">Option</th><th>Description</th></tr></thead><tbody><tr><td><code>prometheus.auth.type</code></td><td>The authentication type to use. Supported options are <code>none</code> and <code>basic</code> (Basic Authentication).</td></tr><tr><td><code>prometheus.auth.username</code></td><td>The username to use when basic authentication is enabled.</td></tr><tr><td><code>prometheus.auth.password</code></td><td>The password to use when basic authentication is enabled.</td></tr></tbody></table>

### TLS

Bindplane supports connecting to Prometheus with TLS and Mutual TLS.

<table><thead><tr><th width="281.4296875">Option</th><th>Description</th></tr></thead><tbody><tr><td><code>prometheus.enableTLS</code></td><td>Whether or not to use TLS when communicating with Prometheus.</td></tr><tr><td><code>prometheus.tls.tlsSkipVerify</code></td><td>Whether or not to skip verification of the Prometheus server's TLS certificate. It is not recommended to enable this option.</td></tr><tr><td><code>prometheus.tls.tlsCa</code></td><td>The x509 PEM encoded certificate authority file to use to verify the Prometheus server's TLS certificate. Alternatively, the CA certificate can be imported into the host's trust store, instead of configuring this option.</td></tr><tr><td><code>prometheus.tls.tlsCert</code></td><td>The x509 PEM encoded client certificate file to use for mutual TLS.</td></tr><tr><td><code>prometheus.tls.tlsKey</code></td><td>The x509 PEM encoded client private key file to use for mutual TLS.</td></tr></tbody></table>

TLS example configuration.

```yaml
prometheus:
  tls:
    tlsSkipVerify: false
    tlsCA: [/etc/bindplane/tls/ca.crt]
```

Mutual TLS example configuration.

```yaml
prometheus:
  tls:
    tlsSkipVerify: false
    tlsCA: [/etc/bindplane/tls/ca.crt]
    tlsCert: /etc/bindplane/tls/bindplane.crt
    tlsKey: /etc/bindplane/tls/bindplane.key
```

### Remote Write

When using Prometheus compatible systems, such as [Mimir](https://grafana.com/oss/mimir/), you may need to define the remote write host and port, if it differs from the main host and port. Bindplane will use the remote write host and port for pushing metrics to Prometheus, and the main host and port for querying Prometheus.

If using vanilla Prometheus, these options are not required.

<table><thead><tr><th width="300.48828125">Option</th><th>Description</th></tr></thead><tbody><tr><td><code>prometheus.remoteWrite.host</code></td><td>The hostname or ip address of the Prometheus instance for remote write. If not set, the value of <code>prometheus.host</code> will be used.</td></tr><tr><td><code>prometheus.remoteWrite.port</code></td><td>The port of the Prometheus instance for remote write. If not set, the value of <code>prometheus.port</code> will be used.</td></tr><tr><td><code>prometheus.remoteWrite.endpoint</code></td><td>The API path to use for remote write.</td></tr></tbody></table>

## Authentication

{% hint style="info" %}
Single Sign-On (SSO) Authentication is only available on Bindplane Cloud. [Read more here](broken://pages/I0GiHA3xd9AwaqTmWDoS)
{% endhint %}

Bindplane supports several authentication options.

* System (Basic Auth)
* External Auth (Enterprise & Google Editions only)
  * [Active Directory](/configuration/bindplane/authentication/active-directory-authentication)
  * LDAP
  * [OIDC](/configuration/bindplane/authentication/openid-connect-authentication)

The configuration's `auth` section contains the following authentication options.

<table><thead><tr><th width="212.83984375">Option</th><th>Description</th></tr></thead><tbody><tr><td><code>auth.type</code></td><td>Authentication type to use (<code>system</code> / <code>active-directory</code> / <code>ldap</code> / <code>oidc</code>).</td></tr></tbody></table>

### System

<table><thead><tr><th width="230.53125">Option</th><th>Description</th></tr></thead><tbody><tr><td><code>auth.username</code></td><td>Basic authentication username.</td></tr><tr><td><code>auth.password</code></td><td>Basic authentication password.</td></tr></tbody></table>

### LDAP / Active Directory Configuration (Enterprise)

The configuration's `auth.ldap` section contains the following options for configuration LDAP and Active Directory.

<table><thead><tr><th width="215.0390625">Option</th><th>Description</th></tr></thead><tbody><tr><td>auth.ldap.server</td><td>Hostname or IP address of the LDAP or Active Directory server.</td></tr><tr><td>auth.ldap.port</td><td>The TCP port to use when connecting to the authentication server.</td></tr><tr><td>auth.ldap.searchFilter</td><td>LDAP Query for searching users based on mapping of username to a particular LDAP attribute as well as any applicable additional filters, (ex: groups in Active Directory).</td></tr><tr><td>auth.ldap.baseDN</td><td>The starting point an LDAP server uses when searching for users.</td></tr><tr><td>auth.ldap.bindUser</td><td>The username used to connect to the authentication server. For active directory, this is a username. For LDAP, this is the full DN to the user.</td></tr><tr><td>auth.ldap.bindPassword</td><td>The password used to connect to the authentication server.</td></tr><tr><td>auth.ldap.tls.tlsCA</td><td>Path to the TLS certificate authority.</td></tr><tr><td>auth.ldap.tls.tlsSkipVerify</td><td>Whether or not to skip TLS verification.</td></tr><tr><td>auth.ldap.tls.tlsCert</td><td>Path to TLS certificate when mutual TLS is required.</td></tr><tr><td>auth.ldap.tls.tlsKey</td><td>Path to TLS private key when mutual TLS is required.</td></tr></tbody></table>

See the [Active Directory documentation](/configuration/bindplane/authentication/active-directory-authentication) for detailed setup instructions.

### OIDC Configuration (Enterprise)

The configuration's `auth.oidc` section contains the following options for configuring an OpenID Connect provider.

<table><thead><tr><th width="271.734375">Option</th><th>Description</th></tr></thead><tbody><tr><td>auth.oidc.issuer</td><td>URL of your OIDC provider.</td></tr><tr><td>auth.oidc.oauth2ClientID</td><td>OAuth2 client ID provided by the OIDC provider.</td></tr><tr><td>auth.oidc.oauth2ClientSecret</td><td>OAuth2 client secret provided by the OIDC provider.</td></tr><tr><td>auth.oidc.scopes</td><td>List of scopes requested during authentication.</td></tr></tbody></table>

Environment variables can be used instead of the configuration file:

```
BINDPLANE_OIDC_ISSUER
BINDPLANE_OIDC_OAUTH2_CLIENT_ID
BINDPLANE_OIDC_OAUTH2_CLIENT_SECRET
BINDPLANE_OIDC_SCOPES
```

See the [OpenID Connect documentation](/configuration/bindplane/authentication/openid-connect-authentication) for detailed setup instructions.

#### **Active Directory Example**

Active Directory authentication is enabled by setting `auth.type` to `active-directory`.

In this example, the domain controller's hostname is `dc.corp.net`. The username `bindplane` is used to bind to Active Directory. The `searchFilter` is inserted by default when running `bindplane init server --config <path to bindplane config.yaml>`.

User login is restricted to the DN `CN=Users,DC=corp,DC=net`.

```yaml
auth:
  type: active-directory
  secretKey: e8bfcfe0-bbe6-4ee6-bf35-72ff182d2dc5
  username: admin
  password: admin
  sessionSecret: b84746f6-aca1-4b91-9ccd-d4da8d75fe4d
  ldap:
    server: dc.corp.net
    port: '389'
    baseDN: CN=Users,DC=corp,DC=net
    bindUser: bindplane@corp.net
    bindPassword: complexpassword
    searchFilter: (|(sAMAccountName=%s)(userPrincipalName=%s))
```

#### **Basic Example**

In this example, the domain controller's hostname is `ldap.corp.net`. The username `bindplane` is used to bind to LDAP. The `searchFilter` is inserted by default when running `bindplane init server --config <path to bindplane config.yaml>`.

User login is restricted to the DN `CN=Users,DC=corp,DC=net`.

```yaml
auth:
  type: ldap
  secretKey: e8bfcfe0-bbe6-4ee6-bf35-72ff182d2dc5
  username: admin
  password: admin
  sessionSecret: b84746f6-aca1-4b91-9ccd-d4da8d75fe4d
  ldap:
    server: ldap.corp.net
    port: '389'
    baseDN: CN=Users,DC=corp,DC=net
    bindUser: bindplane
    bindPassword: complexpassword
    searchFilter: (uid=%s)
```

#### **TLS**

This example is the same as the "basic" example, with TLS. The protocol has been set to `ldaps`, port to `636`, and a ca certificate is optionally\* configured.

```yaml
auth:
  type: ldap
  secretKey: e8bfcfe0-bbe6-4ee6-bf35-72ff182d2dc5
  username: admin
  password: admin
  sessionSecret: b84746f6-aca1-4b91-9ccd-d4da8d75fe4d
  ldap:
    server: ldap.corp.net
    port: '636'
    baseDN: CN=Users,DC=corp,DC=net
    bindUser: bindplane
    bindPassword: complexpassword
    searchFilter: (uid=%s)
    tls:
      tlsCa:
        - /etc/bindplane/tls/ca.crt
```

\*CA certificate is not required if the ca is already trusted by the underlying operating system. Alternatively, `auth.ldap.tls.tlsSkipVerify: true` could be set to skip TLS verification.

#### **Mutual TLS**

This example is the same as the "TLS" example, with client TLS authentication. The `auth.ldap.tls.tlsCert` and `auth.ldap.tls.tlsKey` fields have been set.

```yaml
auth:
  type: ldap
  secretKey: e8bfcfe0-bbe6-4ee6-bf35-72ff182d2dc5
  username: admin
  password: admin
  sessionSecret: b84746f6-aca1-4b91-9ccd-d4da8d75fe4d
  ldap:
    server: ldap.corp.net
    port: '636'
    baseDN: CN=Users,DC=corp,DC=net
    bindUser: bindplane
    bindPassword: complexpassword
    searchFilter: (uid=%s)
    tls:
      tlsCert: /etc/bindplane/tls/bindplane.crt
      tlsKey: /etc/bindplane/tls/bindplane.key
      tlsCa:
        - /etc/bindplane/tls/ca.crt
```

### Agent Versions

Bindplane can be configured to manage agent versions and upgrades. The `agentVersions` section controls how Bindplane synchronizes and manages agent version information.

<table><thead><tr><th width="200">Option</th><th width="150">Flag</th><th width="250">Environment Variable</th><th width="100">Default</th></tr></thead><tbody><tr><td>agentVersions.syncInterval</td><td>--agent-versions-sync-interval</td><td>BINDPLANE_AGENT_VERSIONS_SYNC_INTERVAL</td><td><code>1h</code></td></tr><tr><td>agentVersions.agentUpgradesFolder</td><td>--agent-versions-agent-upgrades-folder</td><td>BINDPLANE_AGENT_VERSIONS_AGENT_UPGRADES_FOLDER</td><td><code>/var/lib/bindplane/agent-upgrades</code></td></tr><tr><td>agentVersions.clients</td><td>--agent-versions-clients</td><td>BINDPLANE_AGENT_VERSIONS_CLIENTS</td><td><code>["bdot"]</code></td></tr></tbody></table>

#### Sync Interval

The interval at which Bindplane synchronizes agent version information from configured clients.

#### Agent Upgrades Folder

The path to the folder where Bindplane stores agent upgrade files. This folder is used to cache agent binaries and metadata for distribution to agents.

**Note:** This option is only used when offline agent upgrades are configured. In standard deployments, agents download updates directly from the configured clients.

#### Clients

List of version clients to use for synchronizing agent versions. Valid options are:

* `bdot` - Bindplane's official agent synchronization endpoint, `bdot.bindplane.com` (recommended)
* `github` - GitHub releases

Multiple clients can be configured by providing a comma-separated list. As of Bindplane v1.95.0, `bdot` is the default and only configured option. This is recommended for most deployments.

**Version History**

* **Bindplane v1.95.0+**: `bdot` is the default and only configured option. Bindplane syncs agent versions from `https://bdot.bindplane.com`.
* **Bindplane v1.94.0**: Introduced the Clients option and defaulted to `github`. Bindplane synced agent versions from `https://github.com/observiq/bindplane-otel-collector`.
* **Previous versions**: Used GitHub exclusively.

**Recommendations**

* **Default deployments**: Use `bdot` only. This simplifies firewall requirements by not requiring access to `github.com`.
* **Custom agent installs**: Use both `bdot` and `github` configured together to support custom agent installations while maintaining access to official releases.

The `bdot.bindplane.com` endpoint was introduced to make user firewall requirements simpler for default Bindplane installations.

**Example Configuration**

```yaml
agentVersions:
  syncInterval: 1h
  agentUpgradesFolder: /var/lib/bindplane/agent-upgrades
  clients:
    - bdot
    - github
```

## Initialization

The `init` command is useful for bootstrapping a server or client.

### Server

After installing Bindplane server, simply run the following command and follow the prompts.

```bash
sudo BINDPLANE_CONFIG_HOME=/var/lib/bindplane /usr/local/bin/bindplane init server \
  --config /etc/bindplane/config.yaml
```

Once finished, you will have the option to automatically restart the server. If the server is not\
automatically restarted, it must be restarted manually.

### Client

Client initialization will create a new profile if one is not already set. If an existing profile is in use, init will update that profile. You can learn more about profiles in the [client profiles](#client-profiles) section.

```bash
bindplane init client
```

Once finished, the client configuration will exist in `~/.bindplane/profiles`. You can also run the `profile` command:

```bash
bindplane profile --help
```

#### Client Profiles

The `profile` command offers a convenient way to create and use multiple client configurations.

In this example, it is assumed that the Bindplane server is running at `10.99.1.10` on port `3001`.

```bash
bindplane profile set remote --remote-url https://10.99.1.10:3001
bindplane profile use remote
```

See `bindplane profile help` for more profile sub-commands.

## Example Configurations

The following examples assume the use of [Bindplane collectors](https://github.com/observIQ/bindplane-otel-collector).

### Basic

This configuration assumes that the Bindplane server is running on IP address `192.168.1.10`.

#### Server Configuration

```yaml
auth:
  secretKey: e124852a-49db-4318-99a8-76bd4aa80ba5
  username: myuser
  password: mypassword
  sessionSecret: 99112c19-9d87-4460-958c-a9affa874e21
```

#### Client Profile

Create a profile named `basic`:

```bash
bindplane profile set basic \
  --username myuser \
  --password mypassword \
  --remote-url http://192.168.1.10:3001

bindplane profile use basic
```

A profile will be created at `~/.bindplane/profiles/basic.yaml`:

```yaml
name: basic
apiVersion: bindplane.observiq.com/v1
auth:
  username: myuser
  password: mypassword
network:
  remoteURL: http://192.168.1.10:3001
```

#### Collector Manager Configuration

```yaml
endpoint: http://192.168.1.10:3001/v1/opamp
secret_key: e124852a-49db-4318-99a8-76bd4aa80ba5
agent_id: ad3caa0c-ac90-4f8d-8691-2f43d9addc71
```

### TLS

Bindplane has support for server side TLS and mutual TLS.

What is a server? A server is the process running from the `bindplane serve` command.

What is a client?

* bindplane cli
* OpAMP collectors
* Web browsers

Keep in mind that all certificate files must be readable by the user running the bindplane, client,\
and collector processes.

#### Server Side TLS

**Server Configuration**

Server-side TLS is configured by setting `network.tlsCert` and `network.tlsKey` on the server.

```yaml
network:
  host: 0.0.0.0
  port: '3001'
  remoteURL: https://bindplane-op.mydomain.net:3001
  tlsCert: /etc/bindplane/tls/bindplane.crt
  tlsKey: /etc/bindplane/tls/bindplane.key
```

Note that remoteURL have a tls protocol set (`https`).

**Client Profile**

All clients must trust the certificate authority that signed the server's certificate. This can be accomplished by setting `tlsCa` on the client or by importing the certificate authority into your operating system's trust store.

Create a profile named `tls`:

```bash
bindplane profile set tls \
  --username myuser \
  --password mypassword \
  --remote-url http://192.168.1.10:3001 \
  --tls-ca /etc/bindplane/tls/my-corp-ca.crt

bindplane profile use tls
```

A profile will be created at `~/.bindplane/profiles/tls.yaml`:

```yaml
name: tls
apiVersion: bindplane.observiq.com/v1
auth:
  username: myuser
  password: mypassword
network:
  remoteURL: https://bindplane-op.mydomain.net:3001
  tlsCa:
    - /etc/bindplane/tls/my-corp-ca.crt
```

If the server's certificate authority is already imported into the client's operating system trust store, it is not required to be set in the configuration.

Browsers will show a TLS warning unless the certificate authority is trusted by your operating system.

**Collector Manager Configuration**

```yaml
endpoint: https://bindplane-op.mydomain.net:3001/v1/opamp
secret_key: e124852a-49db-4318-99a8-76bd4aa80ba5
agent_id: ad3caa0c-ac90-4f8d-8691-2f43d9addc71
tls_config:
  ca_file: /opt/observiq-otel-collector/tls/bindplane-ca.crt
```

If the server's certificate authority is already imported into the client's operating system trust store, it is not required to be set in the configuration.

#### Mutual TLS

In this example, three certificate authorities are referenced:

* `my-corp-ca.crt`: Signed the server's certificate, must be trusted by all clients/collectors
* `client-ca.crt`: Signed all client certificates, must be set in the server configuration
* `collector-ca.crt`: Signed all collector certificates, must be set in the server configuration

**Server Configuration**

Mutual TLS is configured by setting `network.tlsCert`, `network.tlsKey`, and `network.tlsCA` on the server.

```yaml
network:
  host: 0.0.0.0
  port: '3001'
  remoteURL: https://bindplane-op.mydomain.net:3001
  tlsCert: /etc/bindplane/tls/bindplane.crt
  tlsKey: /etc/bindplane/tls/bindplane.key
  # Any client / collector certificate signed by one of these
  # authorities will be trusted.
  tlsCa:
    - /etc/bindplane/tls/client-ca.crt
    - /etc/bindplane/tls/collector-ca.crt
```

Note that `remoteURL` has a TLS protocol set (`https`).

Note that multiple certificate authorities can be specified. This example will trust incoming connections from certificates signed by `client-ca` and `collector-ca`.

**Client Profile**

All clients must trust the certificate authority that signed the server's certificate. This can be accomplished by setting `network.tlsCA` on the client or by importing the certificate authority into your operating system's trust store.

Create a profile named `mtls`:

```bash
bindplane profile set mtls \
  --username myuser \
  --password mypassword \
  --remote-url http://192.168.1.10:3001 \
  --tls-cert /etc/bindplane/tls/client.crt \
  --tls-key /etc/bindplane/tls/client.key \
  --tls-ca /etc/bindplane/tls/my-corp-ca.crt

bindplane profile use mtls
```

A profile will be created at `~/.bindplane/profiles/mtls.yaml`:

```yaml
name: mtls
apiVersion: bindplane.observiq.com/v1
auth:
  username: myuser
  password: mypassword
network:
  remoteURL: https://bindplane-op.mydomain.net:3001
  tlsCert: /etc/bindplane/tls/client.crt
  tlsKey: /etc/bindplane/tls/client.key
  tlsCa:
    - /etc/bindplane/tls/my-corp-ca.crt
```

If the server's certificate authority is already imported into the client's operating system trust store, it is not required to be set in the configuration.

Browsers will show a TLS warning unless the certificate authority is trusted by your operating system.

**Collector Manager Configuration**

```yaml
endpoint: https://bindplane-op.mydomain.net:3001/v1/opamp
secret_key: e124852a-49db-4318-99a8-76bd4aa80ba5
agent_id: ad3caa0c-ac90-4f8d-8691-2f43d9addc71
tls_config:
  cert_file: /opt/observiq-otel-collector/tls/collector.crt
  key_file: /opt/observiq-otel-collector/tls/collector.crt
  ca_file: /opt/observiq-otel-collector/tls/bindplane-ca.crt
```

If the server's certificate authority is already imported into the client's operating system trust store, it is not required to be set in the configuration.

### Advanced Configuration

Bindplane has several advanced configuration options. It is unnecessary to modify advanced options unless explicitly called out in the [Prerequisites](/deployment/virtual-machine/bindplane/prerequisites) documentation or you are guided by Bindplane support.

#### Agent

**Telemetry Port**

Collectors managed by Bindplane expose metrics on TCP port `8888` by default. The port is now configurable globally. Modifying the port will affect all collectors connected to Bindplane.

The telemetry port can be configured under `advanced.agent.telemetryPort`.

```yaml
advanced:
  agent:
    telemetryPort: 8888
```

#### Store

**Stats**

The Prometheus measurements backend can be tuned with the options found under `advanced.store.stats`.

**Batch Flush Interval**

The batch flush interval is the duration used to batch collector management requests before flushing to the measurements backend. A higher interval will mean larger batches are published. At scale, a shorter interval can be used to reduce the payload size sent to Prometheus.

```yaml
advanced:
  store:
    stats:
      batchFlushInterval: 1s
```

**Worker Count**

The worker count is the number of workers used to publish measurement batches to Prometheus. Increasing the worker count can improve performance at high collector counts.

```yaml
advanced:
  store:
    stats:
      workerCount: 1
```


# Authentication

Bindplane must be configured to use LDAP, Active Directory, or another multi-user authentication mode. The default System authentication mode does not support multiple users.

{% hint style="info" %}
Single Sign-On (SSO) Authentication is only available on Bindplane Cloud. [Read more here​](broken://pages/I0GiHA3xd9AwaqTmWDoS)
{% endhint %}

## Auth Types

[Overview of all types and their configuration](/configuration/bindplane#authentication-1)

* System (default)
* [Active Directory](/configuration/bindplane/authentication/active-directory-authentication)
* [OpenID Connect](/configuration/bindplane/authentication/openid-connect-authentication)

## Guides

* [Role-Based Access Control (RBAC)](broken://pages/8eitcar3hNEEkmCtzl6g)
* [Changing Bindplane Authentication Type](broken://pages/YmbLtjNN8p7qZDCjAGps)


# Active Directory

How to configure Bindplane to use Active Directory for Authentication

{% hint style="info" %}
This feature is only available for Bindplane Enterprise and Google Editions.
{% endhint %}

Bindplane supports Active Directory for authentication. Active Directory allows users to offload\
authentication and authorization duties to their Active Directory server. Bindplane's [Role-Based Access Control](broken://pages/8eitcar3hNEEkmCtzl6g) works in conjunction with Active Directory.

### 1. Prerequisites

Before you begin, make sure the following requirements are met.

* You have a Bindplane Enterprise or Bindplane for Google License key
* The Bindplane server has network access to the Active Directory Server's Hostname or IP address
* You know the [Base Distinguished Name (base dn)](https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ldap/distinguished-names) of your Active Directory server.
* You understand that the first user to log into Bindplane will become the Bindplane administrator
  * Additional users will need to be invited by the administrator

### 2. Configuration

Active Directory configuration will differ depending on the platform Bindplane is deployed to. Linux\
users should follow the [Linux](#id-2.1.-linux) section. Kubernetes Helm users should follow the [Kubernetes](#id-2.2.-kubernetes) section.

#### 2.1. Linux

If you have not previously installed Bindplane, review the installation procedure [here](/deployment/virtual-machine).

On the Linux server hosting Bindplane, execute the `init` command to reconfigure Bindplane.

```bash
sudo BINDPLANE_CONFIG_HOME=/var/lib/bindplane \
  /usr/local/bin/bindplane init server \
  --config /etc/bindplane/config.yaml
```

Respond to the prompts until you reach the "Choose an authentication method" prompt. Select "Active Directory".

In this example, the Active Directory server's IP address is `192.168.1.2`. The Bind username is `bindplane-ldap`. For "Base DN", we are using `dc=corp,dc=net`, which will allow any Active Directory user to authenticate to Bindplane using their `sAMAccountName` or `userPrincipalName` name.

```bash
Configure authentication for the Bindplane server.
? Choose an authentication method Active Directory

Enter the IP Address of the Active Directory server.
? Authentication Server Address 192.168.1.2

Enter the port to connect to the Active Directory server over.
? Authentication Server Port 389

Configure TLS for communication with the Active Directory server.
? Enable TLS No

Enter the Base DN to use to search for your users.
? Base DN dc=corp,dc=net

Enter search filter to use for user look up.
? User Search Filter (|(sAMAccountName=%s)(userPrincipalName=%s))

Enter the DN and password of the user Bindplane will use to connect (bind) to the Active Directory server.
? Bind Username (leave empty for anonymous simple authentication) bindplane-ldap
? Bind Password (leave empty for anonymous simple authentication) *********
```

The configuration file at `/etc/bindplane/config.yaml` will look like this.

```yaml
auth:
  type: active-directory
  password: redacted
  sessionSecret: redacted
  ldap:
    protocol: ldap
    server: "192.168.1.2"
    port: "389"
    baseDN: dc=corp,dc=net
    bindUser: bindplane-ldap
    bindPassword: redacted
    searchFilter: (|(sAMAccountName=%s)(userPrincipalName=%s))
```

Once Bindplane is configured and restarted, log into Bindplane to become the Organization Administrator.

If you have trouble logging in, proceed to the [Troubleshooting](/configuration/bindplane/authentication/active-directory-authentication) section.

**2.1.1. TLS**

TLS is supported. When re-run the `init` command from step 2.1. Select yes when prompted to enable TLS.

#### 2.2. Kubernetes

Bindplane is deployed to Kubernetes using the [Bindplane Helm Chart](https://github.com/observIQ/bindplane-op-helm).

If you have not previously deployed Bindplane, review [Kubernetes Installation](/deployment/kubernetes/server/installation) guide before proceeding.

The Helm chart supports Active Directory by configuring the `auth.type` and `auth.ldap` value options. In this example, the values file contains the same values used in the [Linux](#id-2.1.-linux) example.

```yaml
auth:
  type: active-directory
  ldap:
    protocol: ldap
    server: "192.168.1.2"
    port: "389"
    baseDN: dc=corp,dc=net
    bindUser: bindplane-ldap
    bindPassword: redacted
    searchFilter: (|(sAMAccountName=%s)(userPrincipalName=%s))
```

Deploy or update your existing Helm deployment to include the new authentication options.

**2.2.1. TLS**

The Bindplane Helm chart supports TLS and mutual TLS. Before configuring TLS, you must create a\
Kubernetes secret containing the TLS certificate authority and optional mutual TLS client certificate\
key-pair.

In this example, the CA certificate is located at `ca.crt` and the (optional) client keypair is located at `client.crt` and `client.key`. Update the namespace and file names to match your environment.

```bash
kubectl -n default create secret generic ldap-tls \
  --from-file=ca.crt
  --from-file=client.crt \
  --from-file=client.key
```

Once the secret `ldap-tls` is created, update your values file to include the TLS options.

For TLS, configure the TLS certificate authority.

```yaml
auth:
  type: active-directory
  ldap:
    protocol: ldap
    server: "192.168.1.2"
    port: "389"
    baseDN: dc=corp,dc=net
    bindUser: bindplane-ldap
    bindPassword: redacted
    searchFilter: (|(sAMAccountName=%s)(userPrincipalName=%s))
    tls:
      insecure: false
      ca:
        secret: ldap-tls
        subPath: ca.crt
```

For mutual TLS, configure the TLS certificate authority and client key-pair.

```yaml
auth:
  type: active-directory
  ldap:
    protocol: ldap
    server: "192.168.1.2"
    port: "389"
    baseDN: dc=corp,dc=net
    bindUser: bindplane-ldap
    bindPassword: redacted
    searchFilter: (|(sAMAccountName=%s)(userPrincipalName=%s))
    tls:
      insecure: false
      ca:
        secret: ldap-tls
        subPath: ca.crt
      clientKeyPair:
        secret: ldap-tls
        crtSubPath: client.crt
        keySubPath: client.key
```

#### 2.3. Restrict Access

Despite being able to authenticate, users require an invitation before they can successfully log into Bindplane. This means you do not need to restrict which LDAP users and groups can authenticate.

If you wish to restrict the user base, you can do so by updating your search filter to include an Active\
Directory group.

The default search filter will attempt to match the user's username to `sAMAccountName` or `userPrincipalName`.

```yaml
searchFilter: "(|(sAMAccountName=%s)(userPrincipalName=%s))"
```

You can restrict the search filter by including a `memberOf` filter. In this example, we are requiring that the user be part of the `bindplane` group.

```yaml
searchFilter: "(&(memberOf=CN=bindplane,CN=Users,DC=bluemedora,DC=localnet)(|(sAMAccountName=%s)(userPrincipalName=%s)))"
```

Working with search filters can be difficult and error-prone, see the [Troubleshooting](#id-3.-troubleshooting) section for example usage of the `ldapsearch` command.

### 3. Troubleshooting

#### 3.1 LDAP Search

The [ldapsearch](https://docs.ldap.com/ldap-sdk/docs/tool-usages/ldapsearch.html) utility is useful for interacting with Active Directory. You can use it to describe a user or group.

```bash
ldapsearch -x \
  -H ldap://192.168.1.2 \
  -D bindplane-ldap \
  -w 'redacted' \
  -b dc=corp,dc=net
```

If you are using TLS, set the following environment variable.

```bash
export LDAPTLS_CACERT=ca.crt
```

If you are using mutual TLS, set the following environment variables in addition to `LDAPTLS_CACERT`.

```bash
export LDAPTLS_KEY=client.key
export LDAPTLS_CERT=client.crt
```

#### 3.2 Third Party Documentation

* Search filter names <https://learn.microsoft.com/en-us/windows/win32/ad/naming-properties>
* Understanding search filters <https://confluence.atlassian.com/kb/how-to-write-ldap-search-filters-792496933.html>


# OpenID Connect

How to configure Bindplane to use OpenID Connect for Authentication

{% hint style="info" %}
This feature is only available for Bindplane Enterprise, Google Enterprise and Google Editions.
{% endhint %}

{% hint style="warning" %}
Changing the Authentication type on the Bindplane server will automatically remove all existing users and permissions. The first user to log in after the change will become an Organization Admin and owner of all existing Projects. Subsequent users will need to be re-invited to their respective projects or provisioned properly via [custom claims](#id-4.-custom-claims-mapping).
{% endhint %}

### 1. Prerequisites

Before beginning, ensure you have the following:

* An OpenID Connect (OIDC) provider configured and available.
* OAuth2 Client ID and Client Secret from your OIDC provider.

### 2. Identity Provider Configuration

Each Identity Provider will have different steps for configuring an OIDC application. Below are details commonly needed for most configurations.

* Bindplane uses an **Authorization Code** flow
* **Redirect URI**: \<remoteURL/webURL>**/oidc/redirect**

### 3. Bindplane Server Configuration

#### Configuration Steps

1. Open the Bindplane configuration file (by default at `/etc/bindplane/config.yaml`).
2. Add or modify the following OIDC configuration settings:

```yaml
auth:
  type: oidc
  oidc:
    issuer: "https://your-oidc-provider.com"
    oauth2ClientID: "your-client-id"
    oauth2ClientSecret: "your-client-secret"
    scopes:
      - openid
      - profile
      - email
```

3. Replace the placeholder values:
   * `issuer`: Your OIDC provider's URL
   * `oauth2ClientID`: OAuth2 client ID from your OIDC provider
   * `oauth2ClientSecret`: OAuth2 client Secret from your OIDC provider

**Optional: Just-In-Time Provisioning with Custom Claims**

Enable `disableInvitations` to require users to have valid custom claims for provisioning. This enables just-in-time (JIT) provisioning without requiring manual invitations.

```yaml
auth:
  type: oidc
  oidc:
    issuer: "https://your-oidc-provider.com"
    oauth2ClientID: "your-client-id"
    oauth2ClientSecret: "your-client-secret"
    scopes:
      - openid
      - profile
      - email
    disableInvitations: true
```

When `disableInvitations` is enabled, users must provide valid custom claims in their OIDC token to be provisioned. When disabled (default), users can log in with an invitation code even without custom claims. See [Custom Claims Mapping](#id-4.-custom-claims-mapping) below.

4. Restart Bindplane to apply the changes:

```bash
systemctl restart bindplane
```

### Environment Variables

The same settings can also be provided using environment vairables:

```
BINDPLANE_OIDC_OAUTH2_CLIENT_ID=your-client-id
BINDPLANE_OIDC_OAUTH2_CLIENT_SECRET=your-client-secret
BINDPLANE_OIDC_ISSUER=https://your-oidc-provider.com
BINDPLANE_OIDC_SCOPES=openid,profile,email
BINDPLANE_OIDC_DISABLE_INVITATIONS=true
```

#### 4. Custom Claims Mapping

Custom claims in your OIDC token enable automatic role assignment and project access provisioning during login. Bindplane supports two approaches: **IdP groups/roles** and **direct token claims**.

**Supported Custom Claims**

| Claim                    | Type         | Description                                                                                    | Example                                                   |
| ------------------------ | ------------ | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| `bindplane_default_role` | string       | Default role for users when no project-specific role is set. Values: `admin`, `user`, `viewer` | `"admin"`                                                 |
| `bindplane_org_admin`    | string       | Whether the user is an organization administrator. Values: `"true"`, `"false"`                 | `"true"`                                                  |
| `bindplane_projects`     | string       | Comma-separated list of project/project IDs with optional per-project roles                    | `"project1,project2"` or `"admin:project1,user:project2"` |
| `groups` or `group_ids`  | array/string | IdP groups for role inference                                                                  | `["bindplane-admin", "bindplane-projects-<Project-1>"]`   |
| `roles`                  | array/string | IdP roles for role inference                                                                   | `["bindplane-user"]`                                      |

#### **Approach 1: Direct Token Claims**

Direct token claims provide explicit role assignments via custom claims in the OIDC token.

**Example token payload:**

```json
{
  "sub": "user123",
  "email": "user@example.com",
  "bindplane_default_role": "user",
  "bindplane_org_admin": "false",
  "bindplane_projects": "admin:<PROJECT-ID-1>,viewer:<PROJECT-ID-2>"
}
```

**Claims Behavior:**

* **bindplane\_default\_role**: Sets the default role for projects without a project-specific role. Defaults to `viewer` if not set.
* **bindplane\_org\_admin**: When `"true"`, the user becomes an organization administrator with `admin` role on all projects. Organization admins ignore `bindplane_projects` and `bindplane_default_role` claims as the user will gain admin access to all projects within the organization.
* **bindplane\_projects**: Comma-separated list of project IDs. Two formats are supported:
  * **Project IDs only** (e.g., `"<Project-ID-1,Project-ID-2>"`): User gets the role from `bindplane_default_role`, or `viewer` if not set.
  * **Per-project roles** (e.g., `"admin:<Project-ID-1>,user:<Project-ID-2>,viewer:<Project-ID-3>"`): User gets the specified role for each projects, overriding `bindplane_default_role`.

When `bindplane_projects` is set, the user only has access to listed projects. Existing access to unlisted projects are revoked.

#### **Approach 2: Groups-Based Role Inference**

If your OIDC provider doesn't support custom claims, you can use IdP groups or roles for role inference.

**Recognized group/role names** (case-insensitive):

* `bindplane-admin` → `admin` role
* `bindplane-user` → `user` role
* `bindplane-viewer` → `viewer` role
* `admin`, `user`, `viewer` → corresponding role

**Project membership via groups:** Use the prefix `bindplane-projects-<Project-ID>` to grant access to specific projects:

```
bindplane-projects-<Project-ID-1>
bindplane-projects-<Project-ID-2>
```

**Groups behavior:**

1. The first matching role name (case-insensitive) in groups sets the default role
2. If `bindplane-org-admin` group is present, the user becomes an organization admin and project admin across all the projects.
3. Groups matching `bindplane-projects-<Project-ID>` grant access to those projects

**Example token payload:**

```json
{
  "sub": "user123",
  "email": "user@example.com",
  "groups": [
    "bindplane-admin",
    "bindplane-projects-<PROJECT-1>",
    "bindplane-projects-<PROJECT-2>"
  ]
}
```

Result: User gets `admin` role access to `<PROJECT-1>` and `<PROJECT-2>`.

**Role Assignment Priority**

When both approaches are present:

1. **Explicit `bindplane_default_role` claim** → Uses this role (ignores groups/roles)
2. **Groups/roles inference** → Infers role from IdP groups (if `bindplane_default_role` not set)
3. **Per-project roles in `bindplane_projects`** → Uses specified role for each project

**Example with mixed claims:**

```json
{
  "sub": "user123",
  "email": "user@example.com",
  "bindplane_default_role": "admin",
  "groups": ["bindplane-viewer"],
  "bindplane_projects": "user:<PROJECT-ID-1>"
}
```

Result:

* User gets `admin` role for `<PROJECT-ID-1>` (explicit claim overrides everything)
* Groups are ignored (because `bindplane_default_role` is set)
* For any other project, user gets `admin` (from `bindplane_default_role`, not from groups)

**Least Privileged User (LPU) Principle**

When a user has multiple explicit role assignments across different projects (via `role:projectId` format), Bindplane applies the least privileged principle.

**Role hierarchy** (most to least privileged):

```
Admin > User > Viewer
```

**LPU behavior:** The minimum privilege from explicit assignments becomes the fallback role for projects without explicit role assignment. This ensures users don't inadvertently gain unintended access.

**Example:**

```
bindplane_projects: "admin:<PROJECT-ID-1>,user:<PROJECT-ID-2>,viewer:<PROJECT-ID-2>"
```

* User gets `admin` on `Project 1`
* User gets `viewer` on `Project 2`

**Organization Admin vs Project Access**

**Organization Admins** (`bindplane_org_admin: "true"`):

* User becomes an organization administrator
* User gets `admin` role on **all** projects in the organization
* `bindplane_projects` and `bindplane_default_role` claims are ignored

**Project-Level Access** (`bindplane_org_admin` unset or `"false"`):

* User gets access based on `bindplane_projects` and `bindplane_default_role`
* Access is scoped to projects listed in `bindplane_projects`
* Role defaults to `viewer` if not specified

**Conflicting Claims Resolution**

If a user's token contains conflicting information, Bindplane resolves it as follows:

* **Multiple role assignments**: LPU principle applies; the least privileged role is used as the fallback
* **Organization admin + project access**: Organization admin takes precedence; project claims are ignored
* **Invalid role names**: Unrecognized role values default to `viewer`
* **Malformed project IDs**: Invalid entries in `bindplane_projects` are skipped

**Note:** If the token/claims are incorrect or not parsed correctly then no provisioning changes are made and their logins retain their pre-existing permissions.

### 5. User Enrollment

After configuration, users will be redirected to your OIDC provider for authentication when accessing Bindplane.

The first user that logs in after configuration will be automatically created as the Organization Admin. Subsequent users will need to be invited or manually added to a Project before they are able to login using OIDC. For more details on adding additional users see:

* [Add Users using the Bindplane CLI](/cli-and-api/cli)

When `disableInvitations` is enabled, user role and project access are synced on every login, ensuring changes to IdP claims are reflected immediately in Bindplane.

### 6. Token claim name customizations

Starting in Bindplane version [v1.100.2](https://docs.bindplane.com/changelog/), within the server configuration you can modify the default names of `bindplane_default_role` , `bindplane_org_admin`, `bindplane_projects` to fit whatever schema/organizational naming policy limitations. Configure these under `auth.oidc.customClaims` .

Below are the fields that you can use to customize where Bindplane looks in the token to provision users.

| Field                                      | Default                  |
| ------------------------------------------ | ------------------------ |
| `auth.oidc.customClaims.groups`            | `groups`                 |
| `auth.oidc.customClaims.groupIds`          | `group_ids`              |
| `auth.oidc.customClaims.roles`             | `roles`                  |
| `auth.oidc.customClaims.organizationAdmin` | `bindplane_org_admin`    |
| `auth.oidc.customClaims.projects`          | `bindplane_projects`     |
| `auth.oidc.customClaims.defaultRole`       | `bindplane_default_role` |

```yaml
auth:
  type: oidc
  oidc:
    # Rename the claims Bindplane reads on the ID token. Omit a key to keep the default claim name.
    customClaims:
      # Default key: "groups"
      groups: "groups"

      # Default key: "group_ids"
      # Fallback list of group identifiers if groups is missing, empty, or parses to an empty list, Bindplane uses group_ids as a fallback.
      groupIds: "group_ids"

      # Default key: "roles"
      roles: "roles"

      # Default key: "bindplane_org_admin"
      organizationAdmin: "bindplane_org_admin"

      # Default key: "bindplane_projects"
      projects: "bindplane_projects"

      # Default key: "bindplane_default_role"
      defaultRole: "bindplane_default_role"
```

Use these to change the IdP group/role membership strings Bindplane matches (not JWT claim names). They apply to values in the [`groups`](#approach-2-groups-based-role-inference) claims configured above.

| Field                                        | Default               |
| -------------------------------------------- | --------------------- |
| `auth.oidc.customClaims.orgAdminGroupName`   | `bindplane-org-admin` |
| `auth.oidc.customClaims.projectsGroupPrefix` | `bindplane-projects-` |
| `auth.oidc.customClaims.adminGroupName`      | `bindplane-admin`     |
| `auth.oidc.customClaims.userGroupName`       | `bindplane-user`      |
| `auth.oidc.customClaims.viewerGroupName`     | `bindplane-viewer`    |

```yaml
auth:
  type: oidc
  oidc:
    # Strings Bindplane matches inside the groups and roles claims (after resolving claim names above).
    customClaims:
      # Default: "bindplane-org-admin"
      orgAdminGroupName: "bindplane-org-admin"

      # Default: "bindplane-projects-"
      # Prefix for group entries that encode project access, e.g. "bindplane-projects-<projectId>".
      # Also valid to supply in this format e.g. "bindplane-projects-<role>:<Project ID>" i.e. groups: ["bindplane-projects-admin:01PROJECTID", "bindplane-projects-viewer:01PROJECTID2"]
      projectsGroupPrefix: "bindplane-projects-"

      # Default: "bindplane-admin"
      adminGroupName: "bindplane-admin"

      # Default: "bindplane-user"
      userGroupName: "bindplane-user"

      # Default: "bindplane-viewer"
      viewerGroupName: "bindplane-viewer"
```


# Linux Package Configuration

Configure the Bindplane Linux package installation behavior

The Bindplane Linux packages can be configured before installation. This configuration is optional. Users with advanced requirements can use this configuration to customize the installation behavior.

### Configuration File Location

Before installing the Bindplane package, you can create a configuration file at one of the following locations:

* Debian-based distributions: `/etc/default/bindplane`
* RHEL-based distributions: `/etc/sysconfig/bindplane`

The package supports either file location on all platforms. Choose the location that best matches your distribution's conventions.

{% hint style="warning" %}
**IMPORTANT**

The configuration file must be created and configured **before** the initial package installation. Modifying the configuration file after installation may lead to undefined behavior.
{% endhint %}

### File Permissions

The configuration file should have the following permissions:

* Owner: `root`
* Group: `root`
* Permissions: `0640` (readable by root and group, writable only by root)

The configuration file is read by your package manager, not the Bindplane service. It unnecessary for it to be readable by unprivileged users.

### Configuration Options

#### BINDPLANE\_SKIP\_RUNTIME\_USER\_CREATION

Controls whether the package creates the `bindplane` user and group during installation. This option is useful if you have advanced user requirements, such as specific uid and gid or you are integrating with an external authentication system such as LDAP.

* **Default**: `false`
* **Values**: `true` or `false`

When set to `true`, the package will skip creating the `bindplane` user and group. In this case, you must create the user and group manually before installation.

The following commands create the `bindplane` user and group:

```bash
groupadd bindplane
useradd \
  --shell /sbin/nologin \
  --system bindplane \
  -g bindplane
```

You can verify this parameter is working correctly by inspecting the output from the package installation.

The following is logged when skipping user and group creation:

> BINDPLANE\_SKIP\_RUNTIME\_USER\_CREATION is set to true, skipping user and group creation

#### BINDPLANE\_CONFIG\_HOME

Specifies the directory where Bindplane stores its persistent data.

* **Default**: `/var/lib/bindplane`
* **Values**: Any valid directory path

This directory contains:

* Prometheus data
* Offline agent updates
* Other persistent state required by Bindplane

Choose a location that meets your storage and backup requirements before installation.

You can verify this parameter is working correctly by checking the Systemd service file for the Bindplane service.

Read the Systemd service file for the Bindplane service:

```bash
sudo systemctl cat bindplane
```

The output will contain an environment variable for `BINDPLANE_CONFIG_HOME` matching the value you set in the configuration file.

```ini
[Unit]
Description=Bindplane is an observability pipeline that gives you the ability to collect, refine, and ship metrics, logs, and traces to any destination.
After=network.target
Documentation=https://bindplane.com/docs/getting-started/quickstart-guide

[Service]
Type=simple
User=bindplane
Group=bindplane
WorkingDirectory=/opt/bindplane/data
Environment="BINDPLANE_CONFIG_HOME=/opt/bindplane/data"
ExecStart=/usr/local/bin/bindplane serve --config /etc/bindplane/config.yaml
LimitNOFILE=65000

Restart=always
TimeoutSec=120
RestartSec=5s

[Install]
WantedBy=multi-user.target
```

#### BINDPLANE\_USER and BINDPLANE\_GROUP

Controls the runtime user and group. Usually used in conjunction with `BDOT_UNPRIVILEGED`.

{% hint style="info" %}
**NOTE**

This configuration option is supported as of Bindplane version v1.94.0.
{% endhint %}

### Example Configuration

Here's an example configuration file:

```ini
# Skip user creation for LDAP integration
BINDPLANE_SKIP_RUNTIME_USER_CREATION=true

# Store Bindplane data in a custom location
BINDPLANE_CONFIG_HOME=/opt/bindplane/data

# Set runtime user and group to "bpserveru" and "bpserverg"
BINDPLANE_USER=bpserveru
BINDPLANE_GROUP=bpserverg
```


# TLS

Bindplane supports TLS. This guide will focus on using [Step CLI](https://smallstep.com/cli/) to create certificates, however, you can acquire certificates using your preferred method. Certificates must be x509 PEM encoded.

### TLS with Step CLI

[Step CLI](https://smallstep.com/cli/) can be used to create your own certificate authority and server certificates. Step provides an easy-to-use interface. Alternatively, you could use [OpenSSL](https://www.openssl.org/).

#### Prerequisites

This guide assumes you will be deploying Bindplane and its collectors to a network that has a working Domain Name System (DNS). It is expected that collector systems will be able to connect to Bindplane using its fully qualified domain name (FQDN).

If you do not have working DNS, it is possible to use `/etc/hosts` as a workaround. See [this guide](https://www.tecmint.com/setup-local-dns-using-etc-hosts-file-in-linux/) for details.

#### Environment

For this demonstration, we have four compute instances running on Google Cloud. The objective is to configure Bindplane to use a server TLS certificate, and have all clients and collectors connect using TLS.

The following instances are deployed:

* `bindplane`: Instance that hosts the Bindplane server.
* `collector-debian`: Debian-based instance that will host a Bindplane collector.
* `collector-centos`: CentOS-based instance that will host a Bindplane collector.
* `collector-windows`: Windows Server instance that will host a Bindplane collector.

<figure><img src="/files/ZgQjlgzPObeDFrev5gSG" alt="Bindplane docs - TLS - image 1"><figcaption></figcaption></figure>

Each instance belongs to a VPC in the project `bindplane`, which means each instance has a DNS name with the following format: `{{instance name}}.c.bindplane.internal`.

Each instance has the following fully qualified domain name (FQDN):

* bindplane: `bindplane.c.bindplane.internal`
* collector-debian: `collector-debian.c.bindplane.internal`
* collector-centos: `collector-centos.c.bindplane.internal`
* collector-windows: `collector-windows.c.bindplane.internal`

All instances within the network can resolve each other using their FQDN. DNS plays a critical role when using TLS, as it allows certificates to be verified against their hostname. If the hostname does not match the certificate, the connection will be rejected unless steps are taken to disable TLS verification.

### Deploy and Configure Bindplane

Follow the [Bindplane Server Install Guide](/deployment/virtual-machine/bindplane/install-bindplane-server) to install Bindplane.

Once installed, modify the `/etc/bindplane/config.yaml` to look like this:

```yaml
name: default
apiVersion: bindplane.observiq.com/v1
auth:
  # A random uuid which is used as a shared secret between bindplane and
  # deployed collectors.
  secretKey: ffb26038-5169-4496-b5fc-d5a185c33b96

  # Basic auth should use a username other than
  # admin along with a secure password.
  username: admin
  password: admin

  # A random uuid which is used for generating web ui session cookies.
  sessionSecret: 14dab09e-0ca5-4167-bde3-39c869f3fab4
network:
  # Listen on port 3001, all interfaces.
  host: 0.0.0.0
  port: '3001'

  # Endpoint for which clients and collectors will interface
  # with the server's http interface.
  remoteURL: http://bindplane.c.bindplane.internal:3001
store:
  type: postgres
  postgres:
    database: bindplane
logging:
  filePath: /var/log/bindplane/bindplane.log
```

Note that `auth.secretKey` and `auth.sessionSecret` should be random `uuid` values. You can generate your own with the `uuidgen` command.

Make sure `network.remoteURL` use the correct FQDN. You can check your server's FQDN using the\
hostname command:

```bash
$ hostname -f
bindplane.c.bindplane.internal
```

Once Bindplane is configured, restart the server.

```bash
sudo systemctl restart bindplane
```

Verify that Bindplane is working by connecting to the public IP address on port 3001. In this example, that would be <http://bindplane.c.bindplane.internal:3001>.

### Create Certificates with Step

On the instance running your Bindplane server, install the `step` command line. Instructions\
for installing `step` can be found [here](https://smallstep.com/docs/step-cli/installation).

**Create Certificate Authority**

The following commands will write a certificate and private key to `tls-ca/ca.crt` and `tls-ca/ca.key` in your working directory.

```bash
mkdir tls-ca

step certificate create \
	ca.c.bindplane.internal \
	tls-ca/ca.crt tls-ca/ca.key \
	--profile root-ca \
	--no-password \
	--insecure \
	--not-after=8760h
```

**Create Bindplane Server Certificate**

The following commands will generate a server certificate signed by the CA previously\
created. The certificate and private key will be written to `/etc/bindplane/tls/bindplane.crt`\
and `/etc/bindplane/tls/bindplane.key`

```bash
sudo mkdir /etc/bindplane/tls

sudo step certificate create \
    bindplane.c.bindplane.internal \
    /etc/bindplane/tls/bindplane.crt /etc/bindplane/tls/bindplane.key \
    --profile leaf \
    --not-after 2160h \
    --no-password \
    --insecure \
    --ca tls-ca/ca.crt \
    --ca-key tls-ca/ca.key

sudo chown -R bindplane:bindplane /etc/bindplane/tls
```

### Configure Bindplane to use TLS

With the server certificate created, make the following changes to `/etc/bindplane/config.yaml`:

1. Modify `network.remoteURL` to use `https`
2. Add `tlsCert` and `tlsKey`

Your configuration will look similar to this:

```yaml
name: default
apiVersion: bindplane.observiq.com/v1
auth:
  # A random uuid which is used as a shared secret between bindplane and
  # deployed collectors.
  secretKey: ffb26038-5169-4496-b5fc-d5a185c33b96

  # Basic auth should use a username other than
  # admin along with a secure password.
  username: admin
  password: admin

  # A random uuid which is used for generating web ui session cookies.
  sessionSecret: 14dab09e-0ca5-4167-bde3-39c869f3fab
network:
  # Listen on port 3001, all interfaces.
  host: 0.0.0.0
  port: '3001'

  # Endpoint for which clients and collectors will interface
  # with the server's http interface.
  remoteURL: https://bindplane.c.bindplane.internal:3001
  tlsCert: /etc/bindplane/tls/bindplane.crt
  tlsKey: /etc/bindplane/tls/bindplane.key
store:
  type: postgres
  postgres:
    database: bindplane
logging:
  filePath: /var/log/bindplane/bindplane.log
```

With the configuration updated, restart Bindplane:

```bash
sudo systemctl restart bindplane
```

To verify that Bindplane is using TLS, navigate to your server's IP address using `https`. For example, <https://bindplane.c.bindplane.internal:3001>.

You should expect your browser to present a warning screen. This is because your workstation does not trust the certificate. This is expected because you have not imported the certificate authority into your trust store. At this time, it is safe to skip the warning and continue. Note that this warning should never be ignored in production, or in areas where it is not expected.

### Import Certificate Authority on Collector Systems

In all instances that will be running a Bindplane collector, we need to import the certificate authority. This will allow the collector software to trust the Bindplane server certificate.

1. Copy `tls-ca/ca.crt` to all systems that will be running a Bindplane Collector
2. Import the `ca.crt` into the trust store on all collector systems
3. Install collectors

For instructions on how to import a certificate authority, see [this blog](https://manuals.gfi.com/en/kerio/connect/content/server-configuration/ssl-certificates/adding-trusted-root-certificates-to-the-server-1605.html).

Once all collector systems have the certificate authority imported, you can install collectors using\
the command generated in the Bindplane web interface.

Example Linux install command:

```bash
sudo sh -c "$(curl -fsSlL https://github.com/observIQ/bindplane-otel-collector/releases/download/v1.25.0/install_unix.sh)" install_unix.sh -e wss://bindplane.c.bindplane.internal:3001/v1/opamp -s ffb26038-5169-4496-b5fc-d5a185c33b96 -v 1.19.0
```

Note that the command uses the value from `server.remoteURL` in `/etc/bindplane/config.yaml` as the endpoint that the collector should connect to. The `wss` protocol indicates that TLS should be used.

Once installed, the `manager` configuration at `/opt/observiq-otel-collector/manager.yaml` will look something like this:

// cspell:ignore 01GTHN3HAD7QXFN4Z9FV625A3V

```yaml
endpoint: wss://bindplane.c.bindplane.internal:3001/v1/opamp
secret_key: ffb26038-5169-4496-b5fc-d5a185c33b96
agent_id: 01GTHN3HAD7QXFN4Z9FV625A3V
```

Finished! Collectors appear in the web interface, indicating that TLS is working.

<figure><img src="/files/ZbexNcIFYSTMkKp5qdfw" alt="Bindplane docs - TLS - image 2"><figcaption></figcaption></figure>


# Offline Collector Package Installation and Upgrades

How to set up Bindplane to host collector packages locally

{% hint style="warning" %}
**IMPORTANT**

🚧 This feature is only available in Bindplane Enterprise or Bindplane for Google. Learn more [here](https://bindplane.com/solutions/).
{% endhint %}

### Enable Offline Collector Package Hosting and Upgrades

This feature allows Bindplane to host the collector packages. This is used in environments where either Bindplane or the Collector system does not have external network access to GitHub.

#### Bindplane offline collector configuration

In order to use offline collector upgrades, the feature must first be enabled.

To enable offline collector upgrades, the `offline` option must be enabled. The folder where collector upgrade artifacts will be stored when uploaded may also be configured. By default, collector upgrade artifacts are stored in `/var/lib/bindplane/agent-upgrades`.

Here is an example config enabling offline mode, which has the 'offline: true' added right after the 'apiVersion' section.

```yaml
name: default
apiVersion: bindplane.observiq.com/v1

# Enables "offline" mode, which disables syncing collector versions with GitHub, and enables
# uploading upgrade packages for bindplane to host collector upgrade and install artifacts.
offline: true
auth:
  # A random uuid which is used as a shared secret between bindplane and
  # deployed collectors.
  secretKey: your-secret-key

  # Basic auth should use a username other than
  # admin along with a secure password.
  username: admin
  password: password

  # A random uuid which is used for generating web ui session cookies.
  sessionSecret: your-session-secret
network:
  # Listen on port 3001, all interfaces.
  host: 0.0.0.0
  port: '3001'

  # Endpoint for which clients and collectors will interface
  # with the server's http interface.
  remoteURL: http://bindplane.c.bindplane.internal:3001
agentVersions:
  # The path where collector upgrades are stored when uploading collector upgrade packages in offline mode.
  agentUpgradesFolder: /var/lib/bindplane/agent-upgrades
store:
  type: postgres
  postgres:
    database: bindplane
eventBus:
  type: local
logging:
  filePath: /var/log/bindplane/bindplane.log
```

### Upload a Collector Upgrade Artifact Package

Collector artifact packages can be uploaded to the Bindplane server to allow collectors to upgrade to new versions, as well as allow collectors to be installed through Bindplane while in offline mode. These packages can be found and downloaded from the [releases page of the Bindplane Distro for OpenTelemetry GitHub repository](https://github.com/observIQ/bindplane-otel-collector/releases). You can download the artifact package to the Bindplane server through SSH like the example below:

```shell
curl -LO https://github.com/observIQ/bindplane-otel-collector/releases/download/v1.59.1/observiq-otel-collector-v1.59.1-artifacts.tar.gz
```

To upload a collector upgrade artifact package, use the `bindplane upload agent-upgrade` command. This requires that you first set up the CLI. If you have not done so previously, you can set up a profile like the example below:

```shell
bindplane profile set "example" \
 --remote-url "http://192.168.1.10:3001" \
 --username "user" \
 --password "pass"

bindplane profile use "example"
```

The artifact package should be downloaded onto the machine from which you are running the `bindplane` cli, which may or may not be the Bindplane server. In this example, version 1.59.1 of the collector is being uploaded to Bindplane:

```shell
bindplane upload agent-upgrade ./observiq-otel-collector-v1.59.1-artifacts.tar.gz
```

If the file has been renamed, you must specify the `--version` flag with the version you are uploading:

```shell
bindplane upload agent-upgrade ./artifacts.tar.gz --version v1.59.1
```

### Delete Old Collector Artifact Packages

Collector versions and agent artifact packages can be removed using the `bindplane delete agent-version` command:

```shell
bindplane delete agent-version observiq-otel-collector-v1.59.1
```

This will delete the version from Bindplane and remove the unpacked artifact package from the disk of the Bindplane server.


# Collector Telemetry Port

Bindplane OTel collectors expose internal telemetry metrics using the Prometheus format. By default, these metrics are available on TCP port 8888.

{% hint style="info" %}
**NOTE**

[📗 Configure the per-organization telemetry port for a Bindplane, here.](/configuration/bindplane-otel-collector/internal-telemetry)
{% endhint %}

For self-hosted Bindplane server deployments, you can configure the collector's telemetry port globally, which affects all collectors managed by Bindplane.

## Configuration File

Add the `agent.telemetryPort` option to the `advanced` section of your Bindplane configuration file:

```yaml
advanced:
  agent:
    telemetryPort: 8888
```

{% hint style="info" %}
**NOTE**

See the [June 19, 2024 release notes](https://docs.bindplane.com/changelog/june-2024/2024-06-19-release#agent-metrics-port) for more information.
{% endhint %}

## Server Flag

When starting the Bindplane server, use the `--advanced-agent-telemetry-port` flag:

```bash
bindplane serve --advanced-agent-telemetry-port 8888
```

## Environment Variable

Set the `BINDPLANE_ADVANCED_AGENT_TELEMETRY_PORT` environment variable:

```bash
export BINDPLANE_ADVANCED_AGENT_TELEMETRY_PORT=8888
```


# NATS as Event Bus

How to setup Bindplane to use NATS as its event bus

{% hint style="warning" %}
**IMPORTANT**

🚧 This feature is only available in Bindplane Enterprise. Learn more [here](https://bindplane.com/solutions/).
{% endhint %}

[NATS](https://github.com/nats-io/nats-server) can be used as the event bus for Bindplane Enterprise and is a good option for distributed on-prem deployments. NATS is embedded into Bindplane and does not require external infrastructure.

## Configuration

In order to use NATS as the event bus the `eventBus.type` field must be set to `nats` and the `eventBus.nats`config must be filled out. On Linux, the path to the configuration file is `/etc/bindplane/config.yaml`.

Here is an example configuration snippet using NATS as the event bus. In this example, there are three Bindplane severs named `bindplane-0`, `bindplane-1`, and `bindplane-2`. Each Bindplane server is operating the NATS client and server. Each NATS client will connect to its local server over `localhost`. Each NATS server will connect to other servers using their hostname and port.

```yaml
eventBus:
  type: nats
  nats:
    # NATS client connects to the NATS server on the same
    # node. The client will publish and consume events
    # from the subject "bindplane-event-bus.
    client:
      endpoint: nats://localhost:4222
      subject: bindplane-event-bus

    # NATS server accepts client connections on localhost
    # and cluster connections on all interfaces.
    server:
      enable: true
      client:
        host: localhost
        port: 4222
      http:
        host: localhost
        port: 8222
      cluster:
        name: bindplane
        host: '0.0.0.0'
        port: 6222
        routes:
          - 'nats://bindplane-0.corp.net:6222'
          - 'nats://bindplane-1.corp.net:6222'
          - 'nats://bindplane-2.corp.net:6222'
```

### Configuration Parameters

NATS Event Bus can be configured with the following configuration options, flags, and environment variables.

<table><thead><tr><th width="283.015625">Option</th><th width="91.953125">Flag</th><th>Environment Variable</th></tr></thead><tbody><tr><td><a href="#client-name">eventBus.nats.client.name</a></td><td>--nats-client-name</td><td>BINDPLANE_NATS_CLIENT_NAME</td></tr><tr><td><a href="#client-endpoint">eventBus.nats.client.endpoint</a></td><td>--nats-client-endpoint</td><td>BINDPLANE_NATS_CLIENT_ENDPOINT</td></tr><tr><td><a href="#client-subject">eventBus.nats.client.subject</a></td><td>--nats-client-subject</td><td>BINDPLANE_NATS_CLIENT_SUBJECT</td></tr><tr><td><a href="#server-enable">eventBus.nats.server.enable</a></td><td>--nats-server-enable</td><td>BINDPLANE_NATS_SERVER_ENABLE</td></tr><tr><td><a href="#server-name">eventBus.nats.server.name</a></td><td>--nats-server-name</td><td>BINDPLANE_NATS_SERVER_NAME</td></tr><tr><td><a href="#server-client-host">eventBus.nats.server.client.host</a></td><td>--nats-server-client-host</td><td>BINDPLANE_NATS_SERVER_CLIENT_HOST</td></tr><tr><td><a href="#server-client-port">eventBus.nats.server.client.port</a></td><td>--nats-server-client-port</td><td>BINDPLANE_NATS_SERVER_CLIENT_PORT</td></tr><tr><td><a href="#server-http-host">eventBus.nats.server.http.host</a></td><td>--nats-server-http-host</td><td>BINDPLANE_NATS_SERVER_HTTP_HOST</td></tr><tr><td><a href="#server-http-port">eventBus.nats.server.http.port</a></td><td>--nats-server-http-port</td><td>BINDPLANE_NATS_SERVER_HTTP_PORT</td></tr><tr><td><a href="#server-cluster-name">eventBus.nats.server.cluster.name</a></td><td>--nats-server-cluster-name</td><td>BINDPLANE_NATS_SERVER_CLUSTER_NAME</td></tr><tr><td><a href="#server-cluster-host">eventBus.nats.server.cluster.host</a></td><td>--nats-server-cluster-host</td><td>BINDPLANE_NATS_SERVER_CLUSTER_HOST</td></tr><tr><td><a href="#server-cluster-port">eventBus.nats.server.cluster.port</a></td><td>--nats-server-cluster-port</td><td>BINDPLANE_NATS_SERVER_CLUSTER_PORT</td></tr><tr><td><a href="#server-cluster-a-dvertise">eventBus.nats.server.cluster.advertise</a></td><td>--nats-server-cluster-advertise</td><td>BINDPLANE_NATS_SERVER_CLUSTER_ADVERTISE</td></tr><tr><td><a href="#server-cluster-routes">eventBus.nats.server.cluster.routes</a></td><td>--nats-server-cluster-routes</td><td>BINDPLANE_NATS_SERVER_CLUSTER_ROUTES</td></tr><tr><td><a href="#tls-configuration">eventBus.nats.tls.enableTLS</a></td><td>--nats-enable-tls</td><td>BINDPLANE_NATS_ENABLE_TLS</td></tr><tr><td><a href="#tls-configuration">eventBus.nats.tls.tlsCert</a></td><td>--nats-tls-cert</td><td>BINDPLANE_NATS_TLS_CERT</td></tr><tr><td><a href="#tls-configuration">eventBus.nats.tls.tlsKey</a></td><td>--nats-tls-key</td><td>BINDPLANE_NATS_TLS_KEY</td></tr><tr><td><a href="#tls-configuration">eventBus.nats.tls.tlsCA</a></td><td>--nats-tls-ca</td><td>BINDPLANE_NATS_TLS_CA</td></tr><tr><td><a href="#tls-configuration">eventBus.nats.tls.tlsSkipVerify</a></td><td>--nats-tls-skip-verify</td><td>BINDPLANE_NATS_TLS_SKIP_VERIFY</td></tr></tbody></table>

Default installations of Bindplane will include the following configuration. Notice that the event bus\
type is `local`, NATS is disabled by default.

```yaml
eventBus:
  type: local
  nats:
    server:
      client:
        host: localhost
        port: 4222
      http:
        host: localhost
        port: 8222
      cluster:
        name: bindplane
        host: localhost
        port: 6222
    client:
      endpoint: nats://localhost:4222
      subject: bindplane-event-bus
```

#### Client Name

The NATS client name can be set with `eventBus.nats.client.name`. It is required that clients have unique names. It is safe for this value to match NATS server's name when Bindplane is operating the NATS client and server.

Default value: System's hostname.

#### Client Endpoint

The endpoint used by the client to connect to a NATS server can be set with `eventBus.nats.client.endpoint`. The endpoint should be a URI containing the `nats` scheme as well as the hostname and port of the NATS server. Generally, `localhost` is used to target the server operating on the same node.

Default value: `nats://localhost:4222`.

#### Client Subject

The `eventBus.nats.client.subject` option configures the NATS subject used to publish and consume events from the event bus. All clients should have the same subject.

Default value: `bindplane-event-bus`.

#### Server Enable

The `eventBus.nats.server.enable` option enables the embedded NATS server. For small Bindplane deployments (3 to 5 nodes), it is recommended to operate NATS client and server on all Bindplane nodes. For large deployments (> 5), it is recommended to enable NATS server on three nodes.

Default value: `false`.

#### Server Name

The NATS server name can be set with `eventBus.nats.server.name`. It is required that servers have unique names. It is safe for this value to match the NATS client's name when Bindplane is operating the NATS client and server.

Default value: System's hostname.

#### Server Client Host

The `eventBus.nats.server.client.host` option is used to configure the network interface used by the NATS server to receive incoming connections from clients. This can be `localhost` if the server is only receiving connections from the local NATS client, in situations where Bindplane is operating the client and server.

Default value: `localhost`.

#### Server Client Port

The `eventBus.nats.server.client.port` option is used to configure the TCP port used by the NATS server to receive incoming connections from clients.

Default value: `4222`

#### Server HTTP Host

The `eventBus.nats.server.http.host` option is used to configure the network interface used to expose the NATS server Monitoring API. You can find documentation for the API [here](https://docs.nats.io/running-a-nats-service/nats_admin/monitoring). This should be set to `localhost`, with any monitoring tools running on the server system.

Default value: `localhost`.

#### Server HTTP Port

The `eventBus.nats.server.http.port` option is used to configure the TCP port used by the NATS server to expose the Monitoring API.

Default value: `8222`.

#### Server Cluster Name

The `eventBus.nats.server.cluster.name` option sets the name of the NATS cluster. All nodes within\
the NATS cluster should have the same cluster name.

Default value: `bindplane`.

#### Server Cluster Host

The `eventBus.nats.server.cluster.host` option is used to configure the network interface used to expose the NATS server's cluster interface. When operating more than one NATS server, it should be set to`0.0.0.0` or a specific IP address that is reachable by all other NATS servers.

Default value: `localhost`.

#### Server Cluster Port

The `eventBus.nats.server.cluster.port`option is used to configure the TCP port used by the NATS server's cluster interface.

Default value: `6222`.

#### Server Cluster Advertise

The `eventBus.nats.server.cluster.advertise` option can be used to advertise the endpoint other servers in the cluster should use to reach the NATS server. This option should be considered advanced and is generally not required. The configured value should be of the form `host:port`, it should not contain a URI scheme.

Default value: Unset.

#### Server Cluster Routes

The `eventBus.nats.server.cluster.routes` option is used to define a list of servers that the NATS server should connect to. This list can contain the local server.

In this example, there are three Bindplane servers. All three servers will make connections to each\
endpoint in the list of routes. The servers will detect if they are connected to themselves, and\
automatically remove the route as it is unnecessary.

```yaml
nats:
  server:
    enable: true
    cluster:
      host: '0.0.0.0'
      routes:
        - 'nats://bindplane-0.corp.net:6222'
        - 'nats://bindplane-1.corp.net:6222'
        - 'nats://bindplane-2.corp.net:6222'
```

Default value: Unset.

### Authentication

Authentication is supported by configuring TLS. The NATS event bus uses mutual TLS to authenticate the client and server.

#### TLS Configuration

The following options can be set under `eventBus.nats.tls`. When TLS is enabled, NATS will use mutual TLS to authenticate the NATS clients and servers. A certificate authority file is required to enforce the use of mutual TLS.

<table><thead><tr><th width="120.5234375">Option</th><th>Description</th><th width="113.15625">Default</th></tr></thead><tbody><tr><td>enableTLS</td><td>Enable or disable TLS</td><td><code>false</code></td></tr><tr><td>tlsCert</td><td>File path to TLS x509 PEM encoded certificate</td><td>required</td></tr><tr><td>tlsKey</td><td>File path to TLS x509 PEM encoded private key</td><td>required</td></tr><tr><td>tlsCA</td><td>File path(s) to TLS x509 PEM encoded certificate authority</td><td>required</td></tr><tr><td>tlsSkipVerify</td><td>Enable or disable strict hostname verification</td><td><code>false</code></td></tr></tbody></table>

The following example enables TLS by setting `enableTLS`, `tlsCert`, `tlsKey`, and `tlsCa`.

```yaml
eventBus:
  type: nats
  nats:
    enableTLS: true
    tls:
      tlsCert: /etc/bindplane/nats.crt
      tlsKey: /etc/bindplane/nats.key
      tlsCa:
        - /etc/bindplane/ca.crt
```

**Generating Certificates**

You can use [Step CLI](https://smallstep.com/docs/step-cli/), OpenSSL, or other tools to generate certificates. Certificates do not need to be publicly signed.

The following examples will use `step` to generate a certificate authority and a signed certificate\
suitable for use with NATS.

Create the certificate authority:

```bash
step certificate create \
  ca.corp.net \
    ca.crt ca.key \
    --profile root-ca \
    --no-password \
    --insecure \
    --not-after=43800h
```

Modify the `san` flag values to the hostnames of your Bindplane servers. If you have more than three\
servers, add additional `san` flags. You can also issue unique certificates for each server.

```bash
step certificate create \
    nats \
    --san "bindplane-0.corp.net" \
    --san "bindplane-1.corp.net" \
    --san "bindplane-2.corp.net" \
    --san localhost \
    nats.crt nats.key \
    --profile leaf \
    --not-after 2160h \
    --no-password \
    --insecure \
    --ca ca.crt \
    --ca-key ca.key
```

Copy `ca.crt`, `nats.crt`, `nats.key` to `/etc/bindplane` on all of your servers. After copying them,\
set the filesystem permissions.

```bash
sudo chown bindplane:bindplane \
  /etc/bindplane/ca.crt \
  /etc/bindplane/nats.crt \
  /etc/bindplane/nats.key

sudo chmod 0400 bindplane:bindplane \
  /etc/bindplane/ca.crt \
  /etc/bindplane/nats.crt \
  /etc/bindplane/nats.key
```

Update your NATS configuration section to include the TLS options.

* `eventBus.nats.enableTLS`
* `eventBus.nats.tls.tlsCert`
* `eventBus.nats.tls.tlsKey`
* `eventBus.nats.tls.tlsCa`

```yaml
eventBus:
  type: nats
  nats:
    enableTLS: true
    tls:
      tlsCert: /etc/bindplane/nats.crt
      tlsKey: /etc/bindplane/nats.key
      tlsCa:
        - /etc/bindplane/ca.crt
```


# Increase Max Open Files Limit

### File Handles

Linux processes are limited to 1024 open file handles by default. Bindplane's file handles consist of network connections and open files.

You can use the following calculation to determine the estimated number of open file handles by Bindplane: `500 + (2 * Number of collectors)`. For example, if you have 200 collectors, you can expect to see up to 900 file handles.

The number of file handles will differ between Bindplane configurations. For example, when using PostgreSQL as a storage backend, Bindplane will use up to 100 network connections by default. When using Bolt Store, Bindplane will consume one file handle.

Using 500 file handles as a base allows the calculation to account for all Bindplane configurations.

### Configure Max File Handles

Bindplane relies on the systemd option `LimitNOFILE` to limit the maximum number of open files. By default, this value is `55000`.

You can configure the max open files by using a [Systemd override](https://wiki.archlinux.org/title/systemd). Run the following command:

```bash
sudo systemctl edit bindplane
```

Modify the unit file's override to look like this:

<figure><img src="/files/3DrDrVsYpnRDzGMqDFDI" alt="Bindplane docs - Increase Max Open Files Limit - image 1"><figcaption></figcaption></figure>

After saving the file, you can reload systemd and restart Bindplane.

```bash
sudo systemctl daemon-reload
sudo systemctl restart bindplane
```




---

[Next Page](/llms-full.txt/1)

