CallMeter Docs

Worker Configuration

Complete reference for all environment variables, SIP/media network settings, logging, health checks, token management, and performance tuning for CallMeter workers.

This page documents every configuration option available for user-owned CallMeter workers. All configuration is done through environment variables passed to the Docker container.

Required Environment Variables

These variables must be set for the worker to start and connect to CallMeter.

VariableDescriptionExample
WORKER_TOKENAuthentication token generated when creating the worker in CallMeter. Format: cmw_ prefix + 64 hex characters (68 characters total).cmw_a1b2c3d4...
CLOUD_URLAddress of the CallMeter Worker Gateway. Always set to wg.callmeter.io:443.wg.callmeter.io:443

WORKER_TOKEN Is Sensitive

The worker token is a secret credential. Never hardcode it in Dockerfiles, commit it to version control, or expose it in logs. Use Docker secrets, environment files with restricted permissions, or a secrets management system.

# Minimal configuration
environment:
  WORKER_TOKEN: "${WORKER_TOKEN}"
  CLOUD_URL: "wg.callmeter.io:443"

Optional Environment Variables

General Settings

VariableDescriptionDefaultExample
WORKER_NAMEHuman-readable name displayed in the CallMeter dashboard. If not set, the worker uses the name configured in the UI when the worker was created.Name from UIdc-frankfurt-01
LOG_LEVELLogging verbosity.infodebug
LOG_FORMATLog output format.jsonpretty
HEALTH_PORTPort for the local health check HTTP endpoint.30308080
environment:
  WORKER_TOKEN: "${WORKER_TOKEN}"
  CLOUD_URL: "wg.callmeter.io:443"
  WORKER_NAME: "lab-worker-nyc"
  LOG_LEVEL: "info"
  LOG_FORMAT: "json"
  HEALTH_PORT: "3030"

SIP Network Configuration

These settings control how the worker handles SIP signaling within your network. In most deployments, the defaults work correctly. You only need to set these if the worker is behind NAT, has multiple network interfaces, or needs to bind to specific addresses.

VariableDescriptionDefaultExample
SIP_IPIP address used for SIP signaling (binds and advertises this address in SIP headers).Auto-detected10.0.1.50
MEDIA_IPIP address used for RTP media. Set this if your media traffic should use a different interface than SIP signaling.Same as SIP_IP10.0.1.51
SDP_IPIP address advertised in SDP bodies (the c= line). Use this when the worker is behind NAT and needs to advertise a different IP than it binds to.Same as MEDIA_IP192.168.1.100
SIP_PORT_STARTStarting port for SIP listeners.50605060
SIP_PORT_ENDEnding port for SIP listeners. When running multiple workers on the same host, offset these ranges.50805080

When to Set SIP_IP and MEDIA_IP

In most Docker deployments with default networking, the worker auto-detects the correct IP. Set these explicitly when:

  • The host has multiple network interfaces and you need to control which one is used
  • The worker is in a Docker network with custom subnets
  • You are running in host network mode and need to bind to a specific interface

RTP Media Port Configuration

VariableDescriptionDefaultExample
RTP_PORT_MINLowest UDP port for RTP media streams.1000010000
RTP_PORT_MAXHighest UDP port for RTP media streams.6553520000

Each active SIP endpoint uses one or more RTP ports (one for audio, one for video if enabled, plus RTCP ports). Ensure the port range is large enough for your capacity:

  • Audio-only calls: ~2 ports per endpoint (RTP + RTCP)
  • Audio + video calls: ~4 ports per endpoint (audio RTP/RTCP + video RTP/RTCP)

For a worker with 100 endpoint capacity running audio-only tests, you need at least 200 ports in the range. The default range (10000-65535) provides over 55,000 ports, which is sufficient for any capacity configuration.

Port Range and Docker Networking

If you are using Docker's default bridge network, the RTP port range is internal to the container and does not need to be exposed. RTP traffic flows between the worker container and your SIP infrastructure on the Docker host's network. If you use host network mode (--network host), ensure these ports are not in use by other services.

NAT Traversal Configuration

When the worker operates behind NAT (common in corporate networks), you may need to configure how it advertises its network address.

VariableDescriptionDefaultExample
SDP_IPThe IP address inserted into SDP c= lines. Set to the NAT public IP or the IP your SIP infrastructure can reach.Auto203.0.113.10
EXTERNAL_IPExternal IP for SIP Via/Contact headers when behind NAT.Auto203.0.113.10

Common NAT scenario: The worker has a private IP (10.0.1.50) but your SIP server needs to send RTP to the worker's NAT-mapped address (203.0.113.10):

environment:
  SIP_IP: "10.0.1.50"         # Local bind address
  SDP_IP: "203.0.113.10"      # Advertised in SDP to SIP server
  EXTERNAL_IP: "203.0.113.10" # Advertised in SIP headers

If your SIP infrastructure and the worker are on the same network (the most common deployment), you do not need NAT configuration at all.

Logging Configuration

Workers produce structured logs that can be consumed by log aggregation systems.

Log Levels

LevelDescriptionUse When
errorCritical failures onlyProduction, minimal output
warnErrors and warningsProduction, standard
infoNormal operation eventsDefault, recommended for most deployments
debugDetailed diagnostic outputTroubleshooting specific issues
traceExtremely verbose, includes SIP messages and RTP detailsDeep debugging only --- generates significant log volume

Avoid trace in Production

The trace log level outputs raw SIP messages and per-packet RTP information. This generates very high log volume (potentially gigabytes per hour under load) and can impact performance. Use it only for short debugging sessions.

Log Formats

FormatDescriptionUse When
jsonStructured JSON, one object per lineMachine consumption, log aggregation (ELK, Splunk, Datadog)
prettyHuman-readable with colorsManual debugging, development
# Production logging
environment:
  LOG_LEVEL: "info"
  LOG_FORMAT: "json"
# Debugging
environment:
  LOG_LEVEL: "debug"
  LOG_FORMAT: "pretty"

Log Output

All logs are written to stdout and stderr, following Docker logging conventions. Use Docker's logging drivers to route logs to your preferred destination:

# Docker Compose with logging driver
services:
  callmeter-worker:
    image: registry.callmeter.io/worker:latest
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "5"

Health Check Configuration

The worker runs an HTTP health endpoint for monitoring and orchestration integration.

VariableDefaultDescription
HEALTH_PORT3030Port for the health HTTP server

Health Endpoint

GET http://localhost:{HEALTH_PORT}/health

Response:

{
  "status": "healthy",
  "connected": true,
  "uptime": 3600
}
FieldTypeDescription
statusstringhealthy or unhealthy
connectedbooleanWhether the worker has an active gateway connection
uptimenumberSeconds since the worker process started

Docker Health Check Integration

Add a health check to your Docker Compose configuration:

services:
  callmeter-worker:
    image: registry.callmeter.io/worker:latest
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3030/health"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 15s

This allows Docker to automatically detect and optionally restart unhealthy workers.

Token Management

Token Format

Worker tokens follow a fixed format:

  • Prefix: cmw_ (4 characters)
  • Random hex string: 64 characters
  • Total length: 68 characters

Example: cmw_a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890

Token Security

The token authenticates the worker to the CallMeter platform. It is hashed server-side and never stored in plaintext. Security best practices:

  • Store in a secrets manager --- HashiCorp Vault, AWS Secrets Manager, GCP Secret Manager, Azure Key Vault
  • Use environment files with restricted permissions --- chmod 600 .env
  • Never commit to version control --- Add .env to .gitignore
  • Rotate periodically --- Regenerate tokens as part of your security rotation schedule
  • One token per worker --- Never share tokens between workers; a token can only authenticate one simultaneous connection

Regenerating a Token

If a token is compromised or lost:

  1. Open your project in CallMeter
  2. Navigate to Workers
  3. Click on the worker
  4. Click Regenerate Token
  5. Copy the new token immediately (it will not be shown again)
  6. Update the WORKER_TOKEN environment variable on the Docker host
  7. Restart the worker container

Regeneration Invalidates the Previous Token

When you regenerate a token, the previous token is immediately invalidated. The worker using the old token will disconnect and cannot reconnect until updated with the new token.

ErrorCauseResolution
authentication failed: invalid tokenToken is wrong, expired, or regeneratedVerify the token matches what is shown in the UI, or regenerate
authentication failed: worker disabledThe worker has been disabled by an adminRe-enable the worker in the UI
authentication failed: duplicate connectionAnother worker or container is already connected with this tokenStop the other instance, or wait for its connection to time out

Performance Tuning

Resource Allocation

The worker's capacity should match the resources allocated to the Docker container. General guidelines:

Concurrent EndpointsCPU CoresMemoryNetwork
10-251 core512 MB10 Mbps
25-502 cores1 GB25 Mbps
50-1002-4 cores2 GB50 Mbps
100-2004 cores4 GB100 Mbps
200-5008 cores8 GB250 Mbps

These are approximate values for audio-only calls. Video calls require approximately 3-5x the CPU and 5-10x the bandwidth per endpoint.

Docker Resource Limits

Set explicit resource limits to prevent the worker from consuming all host resources:

deploy:
  resources:
    limits:
      cpus: "4.0"
      memory: 4G
    reservations:
      cpus: "2.0"
      memory: 2G

Network Mode

For optimal network performance, especially at high endpoint counts, consider using Docker host networking:

services:
  callmeter-worker:
    image: registry.callmeter.io/worker:latest
    network_mode: host
    environment:
      WORKER_TOKEN: "${WORKER_TOKEN}"
      CLOUD_URL: "wg.callmeter.io:443"
      SIP_IP: "10.0.1.50"

Host networking eliminates Docker's NAT overhead and provides direct access to the host's network stack. This is recommended for workers handling more than 100 concurrent endpoints.

Host Network Mode Trade-offs

Host networking removes port isolation between the container and host. The health endpoint will bind directly to the host's port 3030 (or whatever HEALTH_PORT is set to), and SIP/RTP ports are used directly on the host. Ensure no port conflicts with other services.

Complete Configuration Example

A production-ready docker-compose.yml with all common options:

version: "3.8"

services:
  callmeter-worker:
    image: registry.callmeter.io/worker:latest
    container_name: callmeter-worker
    restart: unless-stopped
    environment:
      # Required
      WORKER_TOKEN: "${WORKER_TOKEN}"
      CLOUD_URL: "wg.callmeter.io:443"
      # Identity
      WORKER_NAME: "production-dc-fra-01"
      # Logging
      LOG_LEVEL: "info"
      LOG_FORMAT: "json"
      # Health
      HEALTH_PORT: "3030"
      # SIP/Media (only if needed for your network)
      # SIP_IP: "10.0.1.50"
      # MEDIA_IP: "10.0.1.50"
      # SDP_IP: "10.0.1.50"
      # RTP_PORT_MIN: "10000"
      # RTP_PORT_MAX: "20000"
    ports:
      - "3030:3030"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3030/health"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 15s
    deploy:
      resources:
        limits:
          cpus: "4.0"
          memory: 4G
        reservations:
          cpus: "2.0"
          memory: 2G
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "5"

Next Steps

On this page