otel-hive
Self-hosted OpAMP management server for OpenTelemetry Collector fleets
What is otel-hive?
otel-hive is a self-hosted OpAMP management server — the missing control plane for OpenTelemetry Collector fleets. The OpAMP protocol (Open Agent Management Protocol) is an emerging CNCF standard that lets you remotely configure, health-check, and update running collectors over a persistent WebSocket connection.
Without a management plane you end up SSHing into VMs, running Ansible playbooks, or baking configs into container images — every config change is a deployment. otel-hive turns that into a Git push.
┌────────────────────────────────────────────────────┐
│ otel-hive (single Docker container) │
│ │
│ ┌──────────────┐ ┌────────────┐ ┌─────────────┐ │
│ │ UI + REST │ │ OpAMP WS │ │ Git Sync │ │
│ │ :8080 (Gin) │ │ :4320 │ │ Worker │ │
│ └──────┬───────┘ └─────┬──────┘ └──────┬──────┘ │
│ └────────────────┴─────────────────┘ │
│ SQLite (./data/app.db) │
│ agents | configs | groups | users | audit_log │
└────────────────────────────────────────────────────┘
↕ OpAMP WS ↕ HTTPS
OTel Collectors Git Repo
(Supervisor or (GitHub / GitLab
OpAMP extension) / Gitea / HTTP) Requirements
| Component | Requirement |
|---|---|
| otel-hive server | Docker 24+ or any Linux host (amd64/arm64). No external DB — SQLite is embedded. |
| Network | Collectors must reach :4320 (OpAMP WS) and otel-hive must reach :8080 from your browser. |
| Collector version | OTel Collector Contrib v0.96+ (OpAMP extension or Supervisor required). |
| Git provider | GitHub, GitLab, Gitea, or any raw HTTP URL. Token required only for private repos. |
| Resources (typical) | 128 MB RAM, 0.25 vCPU for < 20 collectors. Comfortable up to ~300 collectors on SQLite. |
Deploying otel-hive
Option A — Docker Compose (recommended)
Fastest path. One file, one command, UI at http://localhost:8080.
services:
otel-hive:
image: ghcr.io/storl0rd/otel-hive:latest
ports:
- "8080:8080" # UI + REST API
- "4320:4320" # OpAMP WebSocket
volumes:
- ./data:/app/data
environment:
JWT_SECRET: "change-me-use-openssl-rand-hex-32"
restart: unless-stopped docker compose up -d
# UI available at http://localhost:8080
# First visit → setup wizard creates your admin account
Data persists in ./data/app.db. Generate a strong JWT secret with openssl rand -hex 32.
Option B — Linux binary
Single static binary. No Docker required. Suitable for bare-metal VMs or systemd services.
# Download the latest release binary
curl -Lo otel-hive \
https://github.com/storl0rd/otel-hive/releases/latest/download/otel-hive-linux-amd64
chmod +x otel-hive
# Run with defaults (data stored in ./data/)
JWT_SECRET="$(openssl rand -hex 32)" ./otel-hive
To run as a systemd service, drop a unit file in /etc/systemd/system/otel-hive.service:
[Unit]
Description=otel-hive OpAMP manager
After=network.target
[Service]
ExecStart=/usr/local/bin/otel-hive
WorkingDirectory=/var/lib/otel-hive
Environment=JWT_SECRET=change-me
Restart=always
User=otel-hive
[Install]
WantedBy=multi-user.target sudo systemctl daemon-reload
sudo systemctl enable --now otel-hive Option C — Kubernetes
No Helm chart yet (roadmap). Deploy manually with a Deployment + PVC + two Services. Use the OTel Operator on the collector side — it manages the OpAMP connection without needing the Supervisor.
apiVersion: apps/v1
kind: Deployment
metadata:
name: otel-hive
namespace: observability
spec:
replicas: 1
selector:
matchLabels:
app: otel-hive
template:
metadata:
labels:
app: otel-hive
spec:
containers:
- name: otel-hive
image: ghcr.io/storl0rd/otel-hive:latest
ports:
- containerPort: 8080 # UI + REST
- containerPort: 4320 # OpAMP WS
env:
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: otel-hive-secret
key: jwt-secret
volumeMounts:
- name: data
mountPath: /app/data
volumes:
- name: data
persistentVolumeClaim:
claimName: otel-hive-data
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: otel-hive-data
namespace: observability
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: Service
metadata:
name: otel-hive
namespace: observability
spec:
selector:
app: otel-hive
ports:
- name: ui
port: 8080
targetPort: 8080
- name: opamp
port: 4320
targetPort: 4320 # Create the secret first
kubectl create secret generic otel-hive-secret \
--from-literal=jwt-secret="$(openssl rand -hex 32)" \
-n observability
kubectl apply -f otel-hive-k8s.yaml Expose the UI via an Ingress and the OpAMP port via a LoadBalancer or NodePort. The OpAMP connection is a persistent WebSocket — do not put it behind a stateless L7 proxy without sticky sessions.
Collector-side setup
Each collector needs to speak OpAMP. There are two options: the OpAMP Supervisor (bare-metal / VMs) or the OpAMP extension built into the Contrib distribution (simpler, but fewer capabilities).
Option 1 — OpAMP Supervisor (recommended for VMs)
The Supervisor wraps the collector as a managed subprocess, proxies OpAMP, and can restart the collector on config change. It lives alongside the collector binary.
1. Install the Supervisor
# Download the latest Supervisor binary
curl -Lo opampsupervisor \
https://github.com/open-telemetry/opentelemetry-collector-releases/releases/latest/download/otelcol-contrib_linux_amd64
chmod +x opampsupervisor
sudo mv opampsupervisor /usr/local/bin/
# Install your collector binary (if not already present)
curl -Lo otelcol-contrib.tar.gz \
https://github.com/open-telemetry/opentelemetry-collector-releases/releases/latest/download/otelcol-contrib_0.120.0_linux_amd64.tar.gz
tar -xzf otelcol-contrib.tar.gz
sudo mv otelcol-contrib /usr/local/bin/otelcol 2. Create supervisor.yaml
Adjust endpoint to point at your otel-hive server. Generate an API key from the otel-hive UI under API Keys.
server:
endpoint: ws://otel-hive.internal:4320/v1/opamp
headers:
Authorization: "Bearer YOUR_API_KEY_HERE"
agent:
executable: /usr/local/bin/otelcol
config_apply_timeout: 30s
# Fallback config used before first remote config is received
bootstrap_config_file: /etc/otelcol/bootstrap.yaml
capabilities:
accepts_remote_config: true
reports_effective_config: true
reports_health: true
# Labels used for config matching in git repo path convention
agent_description:
non_identifying_attributes:
- key: env
value: production
- key: role
value: gateway 3. Create a bootstrap config
The bootstrap config is used on first start before otel-hive pushes a remote config. Keep it minimal.
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
exporters:
debug:
verbosity: basic
service:
pipelines:
traces:
receivers: [otlp]
exporters: [debug] 4. Run the Supervisor
opampsupervisor --config /etc/otelcol/supervisor.yaml Within ~5 seconds the collector should appear in the otel-hive UI under Agents.
Option 2 — OpAMP extension (simpler, K8s-friendly)
The opampextension is built into otelcol-contrib. No separate process — the collector manages its own OpAMP connection. Config changes require a collector restart (the extension handles this automatically).
extensions:
opamp:
server:
ws:
endpoint: ws://otel-hive.internal:4320/v1/opamp
headers:
Authorization: "Bearer YOUR_API_KEY_HERE"
capabilities:
accepts_remote_config: true
reports_effective_config: true
reports_health: true
agent_description:
non_identifying_attributes:
env: production
role: node-agent
service:
extensions: [opamp]
# ... rest of your pipeline Git repo layout
otel-hive uses a path convention to map config files to collectors. The path structure encodes the collector labels that should receive each config.
configs/
├── environments/
│ ├── production/
│ │ ├── gateway.yaml # → collectors with: env=production, role=gateway
│ │ └── node-agent.yaml # → collectors with: env=production, role=node-agent
│ ├── staging/
│ │ └── gateway.yaml # → collectors with: env=staging, role=gateway
│ └── default/
│ └── base.yaml # fallback for uncategorized collectors
└── groups/
├── aws-east.yaml # → collectors with: region=aws-east
└── security.yaml
The collector's non_identifying_attributes (set in supervisor.yaml or the opamp extension config) are matched against path segments. A collector in production with role=gateway receives environments/production/gateway.yaml.
Using otel-hive
1. First-run setup wizard
On first launch, otel-hive detects no users exist and returns {"setup_required": true}. The UI redirects to the setup wizard where you create your admin account. After that, all API routes require a valid JWT or API key.
2. Connect a git source
Go to Git Sources → Add Source. Fill in your repo URL, branch, provider (GitHub / GitLab / Gitea / HTTP), and an optional token for private repos. Set a poll interval (default 5 min) and optionally configure a webhook secret for push-triggered syncs. Click Sync Now to do an immediate fetch.
3. Push a config change
Commit a collector config YAML to your repo at the appropriate path (e.g., configs/environments/production/gateway.yaml). otel-hive fetches the change on the next poll (or immediately via webhook), matches it to collectors by label, and pushes the new config via OpAMP. The collector applies it and reports back its effective config.
4. Monitor agents
The Agents page shows every connected collector: health status, last-seen timestamp, current config version, and the labels it reported. Red/yellow health badges surface problems before users notice them.
5. Audit log
Every mutating operation is recorded in the audit log: config pushes, git syncs, login events, API key creation/revocation, and agent restarts. Filter by event type or date range to answer "who changed what, and when."
Resource sizing
| Fleet size | vCPU | RAM | Notes |
|---|---|---|---|
| < 20 collectors | 0.25 | 128 MB | Lab / dev. Runs in a single Docker container fine. |
| 20–100 collectors | 0.5 | 256 MB | Comfortable baseline for small production fleets. |
| 100–300 collectors | 1 | 512 MB | SQLite WAL mode handles this range well. |
| 300–500 collectors | 2 | 1 GB | Monitor SQLite write latency; plan PostgreSQL migration. |
| > 500 collectors | PostgreSQL backend (roadmap). Open an issue if you hit this scale. | ||
Links & resources
- github.com/storl0rd/otel-hive — source code, releases, issue tracker
- Releases — pre-built binaries (linux/amd64, linux/arm64) and Docker images on GHCR
- OpAMP specification — official OTel docs on the Open Agent Management Protocol
- opampextension — built-in OpAMP client for otelcol-contrib