Install and configure OpenTelemetry Collector for distributed tracing and observability

Intermediate 45 min Apr 01, 2026 31 views
Ubuntu 24.04 Ubuntu 22.04 Debian 12 AlmaLinux 9 Rocky Linux 9 Fedora 41

Set up OpenTelemetry Collector to gather distributed traces and metrics from your applications. Configure receivers, processors, and exporters for comprehensive observability with Jaeger and Prometheus integration.

Prerequisites

  • Root or sudo access
  • 4GB RAM minimum
  • Docker for Jaeger backend
  • Network access to download packages

What this solves

OpenTelemetry Collector centralizes telemetry data collection from distributed applications, providing standardized observability across microservices. It receives traces, metrics, and logs from instrumented applications and exports them to monitoring backends like Jaeger, Prometheus, and Grafana for analysis and visualization.

Step-by-step installation

Update system packages

Start by updating your package manager to ensure you have the latest security patches and dependencies.

sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget gnupg2 software-properties-common
sudo dnf update -y
sudo dnf install -y curl wget gnupg2

Download OpenTelemetry Collector

Download the latest stable release of the OpenTelemetry Collector binary from the official GitHub releases.

OTEL_VERSION="0.91.0"
wget https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v${OTEL_VERSION}/otelcol_${OTEL_VERSION}_linux_amd64.tar.gz
tar -xzf otelcol_${OTEL_VERSION}_linux_amd64.tar.gz
sudo mv otelcol /usr/local/bin/
sudo chmod +x /usr/local/bin/otelcol

Create OpenTelemetry user and directories

Create a dedicated system user for running the collector and set up the required directory structure with proper permissions.

sudo useradd --system --shell /bin/false --home /var/lib/otelcol otelcol
sudo mkdir -p /etc/otelcol /var/lib/otelcol /var/log/otelcol
sudo chown otelcol:otelcol /var/lib/otelcol /var/log/otelcol
sudo chmod 755 /etc/otelcol
sudo chmod 750 /var/lib/otelcol /var/log/otelcol

Install Jaeger for trace storage

Install Jaeger as the backend for storing and visualizing distributed traces collected by OpenTelemetry.

sudo apt install -y docker.io
sudo systemctl enable --now docker
sudo usermod -aG docker $USER
sudo dnf install -y docker
sudo systemctl enable --now docker
sudo usermod -aG docker $USER
sudo docker run -d --name jaeger \
  -p 16686:16686 \
  -p 14250:14250 \
  jaegertracing/all-in-one:latest

Create OpenTelemetry Collector configuration

Configure receivers to accept telemetry data, processors for data transformation, and exporters to send data to Jaeger and Prometheus.

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318
  jaeger:
    protocols:
      grpc:
        endpoint: 0.0.0.0:14250
      thrift_http:
        endpoint: 0.0.0.0:14268
  zipkin:
    endpoint: 0.0.0.0:9411
  prometheus:
    config:
      scrape_configs:
        - job_name: 'otelcol'
          scrape_interval: 10s
          static_configs:
            - targets: ['0.0.0.0:8888']

processors:
  batch:
    timeout: 1s
    send_batch_size: 1024
  memory_limiter:
    limit_mib: 512
  resource:
    attributes:
      - key: service.instance.id
        from_attribute: host.name
        action: insert

exporters:
  jaeger:
    endpoint: localhost:14250
    tls:
      insecure: true
  prometheus:
    endpoint: "0.0.0.0:8889"
  logging:
    loglevel: info

service:
  pipelines:
    traces:
      receivers: [otlp, jaeger, zipkin]
      processors: [memory_limiter, resource, batch]
      exporters: [jaeger, logging]
    metrics:
      receivers: [otlp, prometheus]
      processors: [memory_limiter, resource, batch]
      exporters: [prometheus, logging]
  extensions: [health_check, pprof]
  telemetry:
    logs:
      level: "info"
    metrics:
      address: 0.0.0.0:8888

extensions:
  health_check:
    endpoint: 0.0.0.0:13133
  pprof:
    endpoint: 0.0.0.0:1777

Set configuration file permissions

Ensure the configuration file has proper ownership and permissions for security.

sudo chown root:otelcol /etc/otelcol/config.yaml
sudo chmod 640 /etc/otelcol/config.yaml

Create systemd service file

Create a systemd service to manage the OpenTelemetry Collector as a system service with automatic startup and restart capabilities.

[Unit]
Description=OpenTelemetry Collector
After=network.target

[Service]
Type=simple
User=otelcol
Group=otelcol
ExecStart=/usr/local/bin/otelcol --config=/etc/otelcol/config.yaml
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=otelcol
KillMode=mixed
KillSignal=SIGTERM

Security settings

NoNewPrivileges=yes ReadOnlyPaths=/ ReadWritePaths=/var/lib/otelcol /var/log/otelcol /tmp PrivateTmp=yes PrivateDevices=yes ProtectSystem=strict ProtectHome=yes ProtectControlGroups=yes ProtectKernelModules=yes ProtectKernelTunables=yes RestrictRealtime=yes RestrictSUIDSGID=yes [Install] WantedBy=multi-user.target

Configure firewall rules

Open the necessary ports for OpenTelemetry Collector receivers and health checks.

sudo ufw allow 4317/tcp comment "OTLP gRPC"
sudo ufw allow 4318/tcp comment "OTLP HTTP"
sudo ufw allow 14250/tcp comment "Jaeger gRPC"
sudo ufw allow 14268/tcp comment "Jaeger HTTP"
sudo ufw allow 9411/tcp comment "Zipkin"
sudo ufw allow 8889/tcp comment "Prometheus metrics"
sudo ufw allow 13133/tcp comment "Health check"
sudo firewall-cmd --permanent --add-port=4317/tcp --add-port=4318/tcp
sudo firewall-cmd --permanent --add-port=14250/tcp --add-port=14268/tcp
sudo firewall-cmd --permanent --add-port=9411/tcp --add-port=8889/tcp
sudo firewall-cmd --permanent --add-port=13133/tcp
sudo firewall-cmd --reload

Enable and start OpenTelemetry Collector

Start the collector service and enable it to automatically start on system boot.

sudo systemctl daemon-reload
sudo systemctl enable --now otelcol
sudo systemctl status otelcol

Create sample instrumented application

Create a simple Python application with OpenTelemetry instrumentation to test the collector setup.

sudo apt install -y python3 python3-pip python3-venv
sudo dnf install -y python3 python3-pip
mkdir -p /home/$USER/otel-demo
cd /home/$USER/otel-demo
python3 -m venv venv
source venv/bin/activate
pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp

Create sample application

Build a simple Flask application that generates traces to test the OpenTelemetry Collector configuration.

pip install flask opentelemetry-instrumentation-flask
from flask import Flask
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.instrumentation.flask import FlaskInstrumentor
import time
import random

Configure OpenTelemetry

trace.set_tracer_provider(TracerProvider()) tracer = trace.get_tracer(__name__)

Configure OTLP exporter

otlp_exporter = OTLPSpanExporter( endpoint="http://localhost:4317", insecure=True ) span_processor = BatchSpanProcessor(otlp_exporter) trace.get_tracer_provider().add_span_processor(span_processor)

Create Flask app

app = Flask(__name__) FlaskInstrumentor().instrument_app(app) @app.route('/') def hello(): with tracer.start_as_current_span("hello_operation") as span: span.set_attribute("user.id", "demo-user") # Simulate some work time.sleep(random.uniform(0.1, 0.5)) return "Hello from OpenTelemetry Demo!" @app.route('/api/data') def get_data(): with tracer.start_as_current_span("fetch_data") as span: span.set_attribute("data.source", "database") # Simulate database query time.sleep(random.uniform(0.2, 0.8)) return {"data": [1, 2, 3, 4, 5], "timestamp": int(time.time())} if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, debug=True)

Configure log rotation

Set up log rotation

Configure logrotate to manage OpenTelemetry Collector log files and prevent disk space issues.

/var/log/otelcol/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    create 640 otelcol otelcol
    postrotate
        systemctl reload otelcol > /dev/null 2>&1 || true
    endscript
}

Production security hardening

Configure TLS for secure communication

Enable TLS encryption for production deployments to secure telemetry data in transit.

sudo mkdir -p /etc/otelcol/certs
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/otelcol/certs/otelcol.key \
  -out /etc/otelcol/certs/otelcol.crt \
  -subj "/C=US/ST=State/L=City/O=Organization/CN=example.com"
sudo chown otelcol:otelcol /etc/otelcol/certs/*
sudo chmod 600 /etc/otelcol/certs/otelcol.key
sudo chmod 644 /etc/otelcol/certs/otelcol.crt
Warning: Never use chmod 777 or run the collector as root. The service account and proper file permissions provide adequate security while maintaining the principle of least privilege.

Verify your setup

# Check collector status
sudo systemctl status otelcol

Verify collector is listening on ports

sudo netstat -tlnp | grep otelcol

Check collector health endpoint

curl http://localhost:13133/

View collector logs

sudo journalctl -u otelcol -f

Test the sample application

cd /home/$USER/otel-demo source venv/bin/activate python app.py & curl http://localhost:5000/ curl http://localhost:5000/api/data

Check Jaeger UI (if accessible)

Open http://localhost:16686 in your browser

View Prometheus metrics

curl http://localhost:8889/metrics

Integration with monitoring stack

OpenTelemetry Collector integrates seamlessly with existing monitoring infrastructure. You can configure it to work with Grafana and Prometheus for metrics visualization, and complement your log aggregation setup with Loki for centralized logging.

Common issues

SymptomCauseFix
Service fails to startConfiguration syntax errorsudo /usr/local/bin/otelcol --config=/etc/otelcol/config.yaml --dry-run
No traces in JaegerApplication not sending to collectorCheck OTLP endpoint configuration in app and verify collector logs
Permission denied errorsIncorrect file ownershipsudo chown otelcol:otelcol /var/lib/otelcol /var/log/otelcol
High memory usageMemory limiter not configuredAdjust memory_limiter processor settings in config.yaml
Port binding failuresPorts already in usesudo netstat -tlnp | grep :4317 and adjust port configuration
TLS certificate errorsInvalid or expired certificatesRegenerate certificates or configure insecure: true for testing

Next steps

Automated install script

Run this to automate the entire setup

#opentelemetry #distributed-tracing #observability #jaeger #prometheus

Need help?

Don't want to manage this yourself?

We handle infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.

Talk to an engineer