Install and configure Jaeger for distributed tracing with Elasticsearch backend

Intermediate 45 min Apr 01, 2026 43 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

#jaeger #distributed-tracing #elasticsearch-jaeger #jaeger-ui #microservices-monitoring

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