Install and configure Jaeger for distributed tracing with Elasticsearch backend

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

Set up Jaeger distributed tracing system with Elasticsearch storage backend for microservices monitoring. Configure collector, query service, and UI with SSL security and performance optimization.

Prerequisites

  • Root or sudo access
  • Elasticsearch 8.x installed and running
  • At least 4GB RAM
  • Network connectivity for downloading packages

What this solves

Jaeger provides distributed tracing for microservices architectures, allowing you to track requests across multiple services and identify performance bottlenecks. This tutorial shows how to install Jaeger with Elasticsearch as the storage backend, configure SSL security, and optimize performance for production workloads.

Step-by-step installation

Update system packages

Start by updating your package manager to ensure you have the latest versions available.

sudo apt update && sudo apt upgrade -y
sudo dnf update -y

Install required dependencies

Install essential packages needed for Jaeger installation and operation.

sudo apt install -y curl wget unzip systemd
sudo dnf install -y curl wget unzip systemd

Create Jaeger user and directories

Create a dedicated user for Jaeger services and set up the required directory structure with proper permissions.

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

Download Jaeger binaries

Download the latest Jaeger release and extract the binaries to the system PATH.

cd /tmp
JAEGER_VERSION="1.51.0"
wget https://github.com/jaegertracing/jaeger/releases/download/v${JAEGER_VERSION}/jaeger-${JAEGER_VERSION}-linux-amd64.tar.gz
tar -xzf jaeger-${JAEGER_VERSION}-linux-amd64.tar.gz
sudo cp jaeger-${JAEGER_VERSION}-linux-amd64/jaeger-* /usr/local/bin/
sudo chmod 755 /usr/local/bin/jaeger-*
sudo chown root:root /usr/local/bin/jaeger-*

Configure Jaeger collector

Create the configuration file for Jaeger collector with Elasticsearch backend settings.

es:
  server-urls: http://localhost:9200
  index-prefix: jaeger
  create-index-templates: true
  version: 8
  num-shards: 5
  num-replicas: 1
  bulk:
    size: 5000000
    workers: 1
    flush-interval: 200ms
  tags-as-fields:
    all: false
    dot-replacement: "@"
    include: "http.status_code,error"
  archive:
    enabled: true
    index-prefix: jaeger-archive

collector:
  grpc-server:
    host-port: 0.0.0.0:14250
  http-server:
    host-port: 0.0.0.0:14268
  zipkin:
    host-port: 0.0.0.0:9411
  otlp:
    grpc:
      host-port: 0.0.0.0:4317
    http:
      host-port: 0.0.0.0:4318

log-level: info

Create Jaeger collector systemd service

Set up the systemd service file for the Jaeger collector component.

[Unit]
Description=Jaeger Collector
Documentation=https://www.jaegertracing.io/
After=network.target elasticsearch.service
Wants=elasticsearch.service

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

# Security settings
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/log/jaeger /var/lib/jaeger

# Resource limits
LimitNOFILE=1000000
LimitNPROC=1000000

[Install]
WantedBy=multi-user.target

Configure Jaeger query service

Create the configuration file for Jaeger query service that provides the web UI and API.

es:
  server-urls: http://localhost:9200
  index-prefix: jaeger
  version: 8
  tags-as-fields:
    all: false
    dot-replacement: "@"
    include: "http.status_code,error"
  archive:
    enabled: true
    index-prefix: jaeger-archive

query:
  base-path: /
  ui-config: /etc/jaeger/ui.json
  static-files: /usr/local/share/jaeger/ui/
  log-file: /var/log/jaeger/query.log
  host-port: 0.0.0.0:16686
  grpc-server:
    host-port: 0.0.0.0:16685
  max-clock-skew-adjustment: 0s

log-level: info

Create Jaeger UI configuration

Configure the Jaeger UI with custom settings and branding options.

{
  "monitor": {
    "menuEnabled": true
  },
  "dependencies": {
    "menuEnabled": true
  },
  "archiveEnabled": true,
  "tracking": {
    "gaID": null,
    "trackErrors": true
  },
  "search": {
    "maxLookback": {
      "label": "2 Days",
      "value": "2d"
    },
    "maxLimit": 1500
  },
  "scripts": [],
  "linkPatterns": []
}

Create Jaeger query systemd service

Set up the systemd service file for the Jaeger query component.

[Unit]
Description=Jaeger Query Service
Documentation=https://www.jaegertracing.io/
After=network.target elasticsearch.service jaeger-collector.service
Wants=elasticsearch.service

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

# Security settings
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/log/jaeger /var/lib/jaeger

# Resource limits
LimitNOFILE=65536
LimitNPROC=65536

[Install]
WantedBy=multi-user.target

Configure sampling strategies

Create sampling strategies configuration to control trace collection rates and reduce storage overhead.

{
  "service_strategies": [
    {
      "service": "frontend",
      "type": "probabilistic",
      "param": 1.0
    },
    {
      "service": "api-gateway",
      "type": "probabilistic",
      "param": 0.8
    },
    {
      "service": "user-service",
      "type": "probabilistic",
      "param": 0.5
    }
  ],
  "default_strategy": {
    "type": "probabilistic",
    "param": 0.1
  },
  "operation_strategies": [
    {
      "service": "frontend",
      "operation": "health-check",
      "type": "probabilistic",
      "param": 0.001
    }
  ]
}

Generate SSL certificates

Create SSL certificates for secure communication between Jaeger components.

sudo mkdir -p /etc/jaeger/certs
cd /etc/jaeger/certs

# Generate CA key and certificate
sudo openssl genrsa -out ca-key.pem 4096
sudo openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem -subj "/C=US/ST=CA/L=San Francisco/O=Example/CN=Jaeger CA"

# Generate server key and certificate
sudo openssl genrsa -out server-key.pem 4096
sudo openssl req -subj "/CN=jaeger.example.com" -sha256 -new -key server-key.pem -out server.csr
sudo openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -out server-cert.pem -CAcreateserial

# Set proper permissions
sudo chown jaeger:jaeger /etc/jaeger/certs/*
sudo chmod 600 /etc/jaeger/certs/*-key.pem
sudo chmod 644 /etc/jaeger/certs/*.pem
sudo rm server.csr

Configure firewall rules

Open the necessary ports for Jaeger services to communicate properly.

sudo ufw allow 14250/tcp comment 'Jaeger gRPC'
sudo ufw allow 14268/tcp comment 'Jaeger HTTP'
sudo ufw allow 16686/tcp comment 'Jaeger UI'
sudo ufw allow 9411/tcp comment 'Zipkin'
sudo ufw allow 4317/tcp comment 'OTLP gRPC'
sudo ufw allow 4318/tcp comment 'OTLP HTTP'
sudo firewall-cmd --permanent --add-port=14250/tcp --add-port=14268/tcp --add-port=16686/tcp --add-port=9411/tcp --add-port=4317/tcp --add-port=4318/tcp
sudo firewall-cmd --reload

Start and enable Jaeger services

Enable and start both Jaeger collector and query services.

sudo systemctl daemon-reload
sudo systemctl enable jaeger-collector jaeger-query
sudo systemctl start jaeger-collector
sudo systemctl start jaeger-query

Configure performance optimization

Create additional configuration for production performance tuning.

# Additional collector configuration for high throughput
collector:
  queue-size: 10000
  num-workers: 50
  es-bulk-size: 5000000
  es-bulk-workers: 5
  es-bulk-flush-interval: 200ms
  
# Memory settings
max-spans: 100000
max-connections-per-host: 30

# Archive settings
archive:
  max-span-age: 168h  # 7 days
  cleanup-interval: 1h

Configure SSL/TLS security

Update collector configuration for SSL

Enable SSL/TLS encryption for the Jaeger collector service.

es:
  server-urls: https://localhost:9200
  index-prefix: jaeger
  create-index-templates: true
  version: 8
  tls:
    enabled: true
    ca: /etc/jaeger/certs/ca.pem
    cert: /etc/jaeger/certs/server-cert.pem
    key: /etc/jaeger/certs/server-key.pem
    server-name: elasticsearch.example.com
    skip-host-verify: false

collector:
  grpc-server:
    host-port: 0.0.0.0:14250
    tls:
      enabled: true
      cert: /etc/jaeger/certs/server-cert.pem
      key: /etc/jaeger/certs/server-key.pem
      ca: /etc/jaeger/certs/ca.pem
  http-server:
    host-port: 0.0.0.0:14268
    tls:
      enabled: true
      cert: /etc/jaeger/certs/server-cert.pem
      key: /etc/jaeger/certs/server-key.pem

log-level: info

Update query service for SSL

Configure SSL/TLS for the Jaeger query service and web UI.

es:
  server-urls: https://localhost:9200
  index-prefix: jaeger
  version: 8
  tls:
    enabled: true
    ca: /etc/jaeger/certs/ca.pem
    cert: /etc/jaeger/certs/server-cert.pem
    key: /etc/jaeger/certs/server-key.pem
    server-name: elasticsearch.example.com
    skip-host-verify: false

query:
  base-path: /
  ui-config: /etc/jaeger/ui.json
  host-port: 0.0.0.0:16686
  tls:
    enabled: true
    cert: /etc/jaeger/certs/server-cert.pem
    key: /etc/jaeger/certs/server-key.pem
    ca: /etc/jaeger/certs/ca.pem
  grpc-server:
    host-port: 0.0.0.0:16685
    tls:
      enabled: true
      cert: /etc/jaeger/certs/server-cert.pem
      key: /etc/jaeger/certs/server-key.pem

log-level: info

Verify your setup

Check that all Jaeger services are running correctly and can communicate with Elasticsearch.

sudo systemctl status jaeger-collector
sudo systemctl status jaeger-query

# Check service logs
sudo journalctl -u jaeger-collector -n 20
sudo journalctl -u jaeger-query -n 20

# Verify Elasticsearch connectivity
curl -f http://localhost:9200/_cluster/health
curl -f http://localhost:9200/jaeger-*/_search?size=0

# Test Jaeger endpoints
curl -f http://localhost:14268/api/sampling
curl -f http://localhost:16686/api/services

# Check UI accessibility
curl -I http://localhost:16686
Note: The Jaeger UI should be accessible at http://localhost:16686. You can integrate this with OpenTelemetry Collector for comprehensive observability.

Common issues

SymptomCauseFix
Collector fails to startElasticsearch not accessibleCheck ES health: curl localhost:9200/_cluster/health
No traces in UIWrong collector endpointVerify apps send to correct port (14268 HTTP, 14250 gRPC)
High memory usageToo many spans in memoryReduce queue-size and increase bulk workers
SSL certificate errorsWrong certificate pathsCheck file permissions: ls -la /etc/jaeger/certs/
Permission denied errorsIncorrect file ownershipsudo chown -R jaeger:jaeger /var/lib/jaeger /var/log/jaeger
UI loads but no dataQuery service can't reach ESCheck query service logs and ES connectivity
Never use chmod 777. It gives every user on the system full access to your files. Instead, fix ownership with chown and use minimal permissions like 644 for files and 755 for directories.

Integration with monitoring stack

Jaeger integrates well with existing monitoring infrastructure. You can forward logs to Fluentd for centralized collection and use it alongside Grafana and Prometheus for comprehensive observability.

Next steps

Automated install script

Run this to automate the entire setup

Wil je dit niet zelf beheren?

Wij beheren infrastructuur voor bedrijven die afhankelijk zijn van uptime. Volledig beheerd, met één vast aanspreekpunt dat je omgeving kent.

U krijgt één vast aanspreekpunt dat uw omgeving kent

Op kantoor in Rotterdam 09:45 · bereikbaar in een bericht, geen ticketformulier