CallMeter Docs

Deploying Your Own Workers

Step-by-step guide to deploying a CallMeter worker as a Docker container in your infrastructure, including configuration, verification, and multi-worker setups.

This guide walks you through deploying a CallMeter worker in your own infrastructure. By the end, you will have a Docker container running in your network, connected to CallMeter, and ready to execute SIP tests against your private infrastructure.

The entire process takes about 10 minutes.

Prerequisites

Before you begin, ensure you have:

  • Docker installed on the host machine (Docker Engine 20.10+ or Docker Desktop)
  • Outbound network access to wg.callmeter.io on port 443 (TCP) --- this is the Worker Gateway
  • Network access to your SIP infrastructure --- the worker must be able to reach your PBX, SBC, or SIP proxy on the SIP signaling port (typically 5060/UDP or 5061/TLS)
  • A CallMeter account with an active worker license (Standard, Professional, or Enterprise)
  • A project created in CallMeter where the worker will be assigned

Quick Prerequisite Check

Run these commands on the host machine to verify readiness before proceeding:

# 1. Verify Docker is installed and running
docker --version
# Expected: Docker version 20.10+ or higher

# 2. Verify outbound connectivity to the Worker Gateway
nc -zv wg.callmeter.io 443
# Expected: Connection to wg.callmeter.io port 443 [tcp/https] succeeded!

# 3. Verify connectivity to your SIP server (replace with your SIP server IP)
nc -zuv <your-sip-server-ip> 5060
# Expected: Connection succeeded (UDP) or similar positive response

If step 2 fails, your firewall is blocking outbound TCP on port 443. This is the only outbound port the worker needs to reach CallMeter --- ask your network team to allow outbound TCP to wg.callmeter.io:443.

No Inbound Firewall Rules Required

The worker initiates all connections outbound to CallMeter's Worker Gateway at wg.callmeter.io:443. You do not need to open any inbound ports, configure port forwarding, or assign a public IP address to the host machine. The worker operates identically behind NAT, corporate firewalls, and restrictive network policies.

Step 1: Create a Worker in CallMeter

  1. Log in to callmeter.io and open your project
  2. Click Workers in the project sidebar
  3. Click Add Worker
  4. Fill in the worker details:
    • Name --- A descriptive label for this worker (e.g., "DC-Frankfurt-01", "Lab-Worker", "Staging-NYC")
    • Capacity --- The maximum number of concurrent SIP endpoints this worker should handle. Set this based on the host machine's resources (see Capacity and Scaling)
  5. Click Create

After creation, CallMeter generates a worker token and displays it on screen.

Step 2: Copy the Worker Token

Copy the Token Now --- It Will Not Be Shown Again

The worker token is displayed exactly once at creation time. Copy it immediately and store it securely. If you lose the token, you will need to regenerate it, which invalidates the previous token.

The token has this format:

cmw_a1b2c3d4e5f6...  (68 characters total)

The cmw_ prefix identifies it as a CallMeter worker token. The remaining 64 characters are a cryptographically random hex string.

Store this token securely:

  • Use a secrets manager (HashiCorp Vault, AWS Secrets Manager, etc.)
  • Or store it in an environment file with restricted permissions (chmod 600)
  • Never commit tokens to version control
  • Never share tokens in chat, email, or tickets

Step 3: Verify Network Access

Before deploying the container, confirm that the host machine can reach both CallMeter and your SIP infrastructure. This prevents confusing "container won't connect" issues later.

# Test outbound connectivity to the Worker Gateway
nc -zv wg.callmeter.io 443

If this fails, check with your network team. The worker only needs outbound TCP to wg.callmeter.io on port 443. No inbound rules are required.

# Test connectivity to your SIP server (adjust IP and port)
nc -zuv 10.0.1.100 5060

If this fails, the worker will connect to CallMeter but SIP tests will fail at the registration step. Ensure the host can reach your SIP infrastructure before proceeding.

Step 4: Deploy with Docker

Option A: Docker Run (Quick Start)

Run a single command to start the worker:

docker run -d \
  --name callmeter-worker \
  --restart unless-stopped \
  -e WORKER_TOKEN=cmw_your_token_here \
  -e CLOUD_URL=wg.callmeter.io:443 \
  -p 3030:3030 \
  registry.callmeter.io/worker:latest

This command:

  • Runs the container in detached mode (-d)
  • Names it callmeter-worker for easy management
  • Restarts automatically unless explicitly stopped
  • Passes your worker token as an environment variable
  • Connects to the CallMeter Worker Gateway at wg.callmeter.io:443
  • Exposes the health check endpoint on port 3030

Replace the Token

Replace cmw_your_token_here with the actual token you copied in Step 2. The token must start with cmw_ and be exactly 68 characters long.

Create a docker-compose.yml file for more manageable configuration:

version: "3.8"

services:
  callmeter-worker:
    image: registry.callmeter.io/worker:latest
    container_name: callmeter-worker
    restart: unless-stopped
    environment:
      WORKER_TOKEN: "${WORKER_TOKEN}"
      CLOUD_URL: "wg.callmeter.io:443"
      WORKER_NAME: "dc-frankfurt-01"
      LOG_LEVEL: "info"
    ports:
      - "3030:3030"
    deploy:
      resources:
        limits:
          cpus: "4.0"
          memory: 4G
        reservations:
          cpus: "2.0"
          memory: 2G

Create a .env file alongside the compose file:

WORKER_TOKEN=cmw_your_token_here

Secure the .env file:

chmod 600 .env

Start the worker:

docker compose up -d

Protect Your .env File

The .env file contains your worker token. Ensure it is not readable by unauthorized users and is excluded from version control. Add .env to your .gitignore if this directory is tracked by git.

Step 5: Verify the Connection

After starting the container, verify the worker is connected and healthy.

Check Status in CallMeter UI

  1. Open your project in CallMeter
  2. Navigate to Workers
  3. Your worker should show status ONLINE with a green indicator
  4. The Last Heartbeat column should show a recent timestamp

The worker sends its first heartbeat within seconds of connecting. If the status does not change to ONLINE within 30 seconds, see the quick fixes below or the full Troubleshooting guide.

Quick fix if still OFFLINE after 30 seconds:

  1. Check if the container is running: docker ps | grep callmeter-worker
  2. Check logs for errors: docker logs callmeter-worker 2>&1 | grep -i "error\|fail"
  3. Verify the token: docker exec callmeter-worker env | grep WORKER_TOKEN --- should be 68 characters starting with cmw_
  4. Test connectivity from inside the container: docker exec callmeter-worker nc -zv wg.callmeter.io 443

Check the Health Endpoint

The worker exposes a local health endpoint:

curl http://localhost:3030/health

A healthy, connected worker returns:

{
  "status": "healthy",
  "connected": true,
  "uptime": 45
}
FieldDescription
statushealthy if the worker is operating normally; unhealthy if there is an issue
connectedtrue if the worker has an active connection to the Worker Gateway
uptimeSeconds since the worker process started

Check Container Logs

View real-time logs to confirm successful connection:

docker logs callmeter-worker

A successful startup sequence looks like:

[INFO] CallMeter Worker starting...
[INFO] Connecting to Worker Gateway at wg.callmeter.io:443
[INFO] Authentication successful
[INFO] Worker registered: dc-frankfurt-01
[INFO] Status: ONLINE
[INFO] Health endpoint listening on :3030
[INFO] Ready to accept test assignments

Running Your First Test with a User-Owned Worker

Once your worker shows ONLINE, you can run a test that executes entirely within your network.

  1. Create a new test in the same project where the worker is registered
  2. Configure a registrar --- add your SIP server's address, credentials, and transport protocol if you have not already
  3. Set up groups --- configure caller and callee groups with the SIP accounts, codecs, and media settings you want to test
  4. Select your worker --- in the test configuration, under Assignment, select Workers instead of Region, then pick your worker from the dropdown
  5. Set test parameters --- configure duration, endpoint count, and ramp-up period
  6. Click Run Test

The test executes entirely on your worker. SIP registration, call establishment, and RTP media all happen within your network. Only aggregated quality metrics are sent to CallMeter through the gateway connection.

Worker Must Be in the Same Project

Workers are scoped to the project where they are created. You can only select workers that belong to the same project as the test. If you do not see your worker in the dropdown, verify it was created in the correct project.

Quick fix if the test fails to start:

  • "No available capacity" --- check the worker's capacity on the Workers page. The test requires more endpoints than the worker has available.
  • SIP registration failures --- verify the worker can reach your SIP server: docker exec callmeter-worker nc -zuv <sip-server-ip> 5060
  • Worker shows OFFLINE --- the worker disconnected. Check logs and reconnect before retrying.

What Happens Behind the Scenes

When the container starts, the worker goes through this sequence:

  1. Initialization --- The worker process starts and reads its configuration from environment variables
  2. DNS resolution --- Resolves wg.callmeter.io to get the gateway's IP address
  3. TLS connection --- Establishes an encrypted TCP connection to wg.callmeter.io:443
  4. Authentication --- Presents the worker token. The gateway validates the token, verifies the associated license, and confirms no other worker is already connected with this token.
  5. Registration --- The gateway registers the worker and associates it with your organization and project. The worker appears in your dashboard.
  6. Heartbeats --- The worker sends a heartbeat every 30 seconds. If the gateway does not receive a heartbeat for 60 seconds, the worker is marked as stale.
  7. Ready --- The worker transitions to ONLINE and begins accepting test assignments.

If the connection drops at any point, the worker automatically reconnects with exponential backoff (5 seconds, then doubling up to 60 seconds). No manual intervention is required.

Common Deployment Patterns

Lab or Staging Environment

Deploy a single worker on a VM or spare machine in your lab network to validate SIP configurations before production:

docker run -d \
  --name callmeter-lab \
  --restart unless-stopped \
  -e WORKER_TOKEN=cmw_your_lab_token \
  -e CLOUD_URL=wg.callmeter.io:443 \
  -e WORKER_NAME=lab-staging \
  -p 3030:3030 \
  registry.callmeter.io/worker:latest

Datacenter Deployment

For production stress testing, deploy on a dedicated server with resource limits and structured logging:

version: "3.8"
services:
  callmeter-worker:
    image: registry.callmeter.io/worker:latest
    container_name: callmeter-dc-worker
    restart: unless-stopped
    network_mode: host
    environment:
      WORKER_TOKEN: "${WORKER_TOKEN}"
      CLOUD_URL: "wg.callmeter.io:443"
      WORKER_NAME: "dc-fra-production"
      LOG_LEVEL: "info"
      LOG_FORMAT: "json"
      SIP_IP: "10.0.1.50"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3030/health"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 15s
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "5"

Use network_mode: host for high-endpoint-count deployments to eliminate Docker's NAT overhead. Set SIP_IP to the host's IP address to ensure correct SIP header generation.

Customer Premises (MSP Pattern)

Managed service providers can deploy lightweight workers at customer sites. The worker only needs outbound internet access --- no inbound ports, no VPN tunnels:

docker run -d \
  --name callmeter-customer-site \
  --restart unless-stopped \
  -e WORKER_TOKEN=cmw_customer_site_token \
  -e CLOUD_URL=wg.callmeter.io:443 \
  -e WORKER_NAME=customer-acme-hq \
  registry.callmeter.io/worker:latest

This pattern lets you test SIP quality from the customer's actual network perspective without any complex networking setup.

Multi-Worker Deployment

For higher capacity or geographic distribution, deploy multiple workers on the same or different machines.

Multiple Workers on One Machine

Each worker needs its own token and container name:

version: "3.8"

services:
  worker-1:
    image: registry.callmeter.io/worker:latest
    container_name: callmeter-worker-1
    restart: unless-stopped
    environment:
      WORKER_TOKEN: "${WORKER_TOKEN_1}"
      CLOUD_URL: "wg.callmeter.io:443"
      WORKER_NAME: "dc-fra-worker-1"
      LOG_LEVEL: "info"
    ports:
      - "3031:3030"
    deploy:
      resources:
        limits:
          cpus: "2.0"
          memory: 2G

  worker-2:
    image: registry.callmeter.io/worker:latest
    container_name: callmeter-worker-2
    restart: unless-stopped
    environment:
      WORKER_TOKEN: "${WORKER_TOKEN_2}"
      CLOUD_URL: "wg.callmeter.io:443"
      WORKER_NAME: "dc-fra-worker-2"
      LOG_LEVEL: "info"
    ports:
      - "3032:3030"
    deploy:
      resources:
        limits:
          cpus: "2.0"
          memory: 2G

One Token Per Worker

Each worker must have its own unique token. A single token cannot be used by multiple workers simultaneously --- the second connection attempt will be rejected.

Workers Across Multiple Machines

Deploy the same Docker image on different hosts, each with its own token. Workers can be in different datacenters, cloud providers, or geographic locations. They all appear in your project's worker list and can be selected individually when creating tests.

Updating Workers

To update to the latest worker version:

# Pull the latest image
docker pull registry.callmeter.io/worker:latest

# Restart the container
docker compose down
docker compose up -d

The worker will reconnect to the gateway automatically after restart. Active test runs on the worker should complete before updating --- check the worker status in the UI and wait for any in-progress tests to finish.

Graceful Shutdown

When you stop a worker that has active endpoints, it enters the DRAINING state. Active calls complete normally before the container fully stops. The default Docker stop timeout (10 seconds) may not be sufficient for long-running tests --- consider using docker compose stop -t 300 to allow up to 5 minutes for draining.

Monitoring Workers

From the CallMeter Dashboard

The Workers page in your project shows all workers with their:

  • Name and status (ONLINE, OFFLINE, DRAINING, ERROR)
  • Current capacity usage (e.g., "35 / 100 endpoints")
  • Last heartbeat timestamp
  • Connection duration (uptime since last connection)

From the Host Machine

Monitor the Docker container directly:

# Container resource usage
docker stats callmeter-worker

# Container health
curl -s http://localhost:3030/health | jq .

# Recent logs
docker logs --tail 50 callmeter-worker

# Follow logs in real time
docker logs -f callmeter-worker

Integration with Monitoring Systems

The health endpoint at http://localhost:3030/health returns JSON and can be polled by any monitoring system (Prometheus blackbox exporter, Nagios, Zabbix, Datadog, etc.):

# Example: Prometheus blackbox probe
- targets:
  - http://worker-host:3030/health

Monitor for:

  • status changing from healthy to unhealthy
  • connected changing from true to false
  • Container restart count increasing
  • CPU and memory usage exceeding expected thresholds

Uninstalling a Worker

To remove a worker:

  1. Stop the container:
    docker compose down
  2. In CallMeter, navigate to Workers and delete the worker entry
  3. The token is now permanently invalidated

Deleting a worker in the UI does not stop the container --- always stop the container first to avoid orphaned connections.

Next Steps

  • Configuration --- Full reference for all environment variables and tuning options
  • Networking --- Firewall rules, port requirements, and NAT considerations
  • Capacity and Scaling --- Size your workers correctly and scale horizontally
  • Troubleshooting --- Diagnose connection issues, status problems, and test failures

On this page