Labelgate

Multi-Host (Agent Mode)

Deploy Labelgate across multiple Docker hosts using Agent mode.

Agent mode lets you monitor Docker containers across multiple hosts. A central Main instance handles all Cloudflare API calls, while lightweight Agent instances on remote hosts collect container labels and report back.

Architecture

┌──────────────┐     WebSocket     ┌──────────────┐
│   Agent #1   │ ──────────────>   │              │
│  Docker Host │                   │    Main      │ ───> Cloudflare API
│              │                   │   Instance   │
└──────────────┘                   │              │
                                   │              │
┌──────────────┐     WebSocket     │              │
│   Agent #2   │ ──────────────>   │              │
│  Docker Host │                   └──────────────┘
└──────────────┘

Connection Modes

Outbound (Agent connects to Main)

Best for agents behind NAT or firewalls. The agent initiates the connection.

Inbound (Main connects to Agent)

Best for agents on internal networks where the main instance can reach them directly.

Outbound Mode Example

Main Instance

# docker-compose.yaml (main host)
services:
  labelgate:
    image: labelgate:latest
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - labelgate-data:/app/config
    environment:
      - LABELGATE_CLOUDFLARE_API_TOKEN
      - LABELGATE_CLOUDFLARE_ACCOUNT_ID
      - LABELGATE_CLOUDFLARE_TUNNEL_ID
      - LABELGATE_AGENT_ENABLED=true
      - LABELGATE_AGENT_LISTEN=:8081
    ports:
      - "8081:8081"
    configs:
      - source: labelgate-config
        target: /etc/labelgate/labelgate.yaml

  cloudflared:
    image: cloudflare/cloudflared:latest
    restart: unless-stopped
    command: tunnel run --token ${TUNNEL_TOKEN}

volumes:
  labelgate-data:

configs:
  labelgate-config:
    content: |
      agent:
        enabled: true
        listen: :8081
        agents:
          docker-host-1:
            token: ${AGENT_1_TOKEN}
            default_tunnel: default
          docker-host-2:
            token: ${AGENT_2_TOKEN}
            default_tunnel: default

Agent Instance

# docker-compose.yaml (remote host)
services:
  labelgate-agent:
    image: labelgate:latest
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      - LABELGATE_MODE=agent
      - LABELGATE_CONNECT_MODE=outbound
      - LABELGATE_CONNECT_ENDPOINT=wss://main-host.example.com:8081
      - LABELGATE_CONNECT_TOKEN=${AGENT_TOKEN}
      - LABELGATE_DEFAULT_TUNNEL=default

  # Your services with labels (same as single-host)
  webapp:
    image: nginx:alpine
    labels:
      labelgate.tunnel.web.hostname: "remote-app.example.com"
      labelgate.tunnel.web.service: "http://webapp:80"

Inbound Mode Example

Main Instance

# docker-compose.yaml (main host)
services:
  labelgate:
    image: labelgate:latest
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - labelgate-data:/app/config
    environment:
      - LABELGATE_CLOUDFLARE_API_TOKEN
      - LABELGATE_CLOUDFLARE_ACCOUNT_ID
      - LABELGATE_CLOUDFLARE_TUNNEL_ID
    configs:
      - source: labelgate-config
        target: /etc/labelgate/labelgate.yaml

volumes:
  labelgate-data:

configs:
  labelgate-config:
    content: |
      agent:
        enabled: true
        agents:
          docker-host-1:
            connect_to: wss://192.168.1.11:8082
            token: ${AGENT_1_TOKEN}

Agent Instance (Inbound)

# docker-compose.yaml (remote host)
services:
  labelgate-agent:
    image: labelgate:latest
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      - LABELGATE_MODE=agent
      - LABELGATE_CONNECT_MODE=inbound
      - LABELGATE_CONNECT_LISTEN=:8082
      - LABELGATE_CONNECT_TOKEN=${AGENT_TOKEN}
    ports:
      - "8082:8082"

Key Notes

  • Agents are lightweight: They only collect container labels and report to the main instance. All Cloudflare API calls happen on the main instance.
  • Hostname conflicts: Cross-host hostname conflicts are detected. First container to register a hostname wins, regardless of which host it's on.
  • Tunnel assignment: Container label > Agent default tunnel > Global default tunnel.
  • Reconnection: Agents automatically reconnect with exponential backoff if the connection drops.
  • TLS: For production, always use TLS for agent connections. Configure certificates on the server side (main for outbound, agent for inbound).

On this page