Examples
Complete working configurations for self-managed Director deployments. Each example pairs the vmetric.yml service configuration with the environment file it requires. For the individual fields, see Service Configuration and Environment Files.
Minimal Standalone Director
vmetric.yml:
director:
id: 1
listen:
address: "0.0.0.0"
port: 8080
debug:
level: 1
console:
status: true
config/environments/env.yml:
environments:
- name: "1"
status: true
nodes:
- name: "1"
status: true
Production Standalone with ACL
vmetric.yml:
director:
id: 1
listen:
address: "0.0.0.0"
external_address: "10.0.1.100"
port: 8890
queue:
limit: 900000000
debug:
level: 1
console:
status: false
log:
status: true
config/environments/env.yml:
environments:
- name: "1"
status: true
nodes:
- name: "1"
status: true
properties:
acl:
allowed_ips:
- "10.0.0.0/24"
- "192.168.1.50"
- "172.16.0.1 - 172.16.0.254"
access_tokens:
- "prod-token-abc123"
rate_limit_max_requests: 200
rate_limit_window: 60
Three-Node HA Cluster with VIP
vmetric.yml (same on all nodes, only director.id differs):
director:
id: 1 # Change to 2, 3 on other nodes
listen:
address: "0.0.0.0"
external_address: "10.0.1.101"
port: 8890
queue:
limit: 900000000
debug:
level: 2
console:
status: true
log:
status: true
loadbalancer:
mode: dynamic
config/environments/cluster.yml:
cluster: "prod-cluster"
environments:
- name: "prod-cluster"
description: "Production HA Cluster"
status: true
clusters:
- name: "prod-cluster"
description: "3-node director cluster"
status: true
type: director
properties:
address: "10.0.1.101"
port: 6222
authentication:
token: "cluster-secret-token"
tls:
status: true
cert_name: "cluster-cert.pem"
key_name: "cluster-key.pem"
ca_name: "ca.pem"
verify: true
acl:
allowed_ips:
- "10.0.0.0/16"
allowed_tokens:
- "api-token-xyz"
rate_limit_max_requests: 500
rate_limit_window: 60
vip:
use_vip: true
bind_vip: true
vip_address: "10.0.1.100"
vip_netmask: "255.255.255.0"
vip_gateway: "10.0.1.1"
vip_interface: "eth0"
vip_monitor_interval: 5
is_nats_cluster: true
update:
mode: auto
method: cron
cron: "0 3 * * 0"
version: "latest"
nodes:
- name: "1"
description: "Node 1 - 10.0.1.101"
status: true
properties:
address: "10.0.1.101"
port: 4222
cluster:
address: "10.0.1.101"
port: 6222
authentication:
token: "cluster-secret-token"
tls:
status: true
cert_name: "cluster-cert.pem"
key_name: "cluster-key.pem"
ca_name: "ca.pem"
verify: true
- name: "2"
description: "Node 2 - 10.0.1.102"
status: true
properties:
address: "10.0.1.102"
port: 4222
cluster:
address: "10.0.1.102"
port: 6222
authentication:
token: "cluster-secret-token"
tls:
status: true
cert_name: "cluster-cert.pem"
key_name: "cluster-key.pem"
ca_name: "ca.pem"
verify: true
- name: "3"
description: "Node 3 - 10.0.1.103"
status: true
properties:
address: "10.0.1.103"
port: 4222
cluster:
address: "10.0.1.103"
port: 6222
authentication:
token: "cluster-secret-token"
tls:
status: true
cert_name: "cluster-cert.pem"
key_name: "cluster-key.pem"
ca_name: "ca.pem"
verify: true
Fleet-Managed Director
vmetric.yml:
self_managed: false
fleet:
type: httpclient
instance: production
address: wss://fleet.virtualmetric.io/ws
token: "fleet-auth-token-abc123"
director:
id: 2028574672450228224
listen:
address: "0.0.0.0"
port: 8890
debug:
level: 1
console:
status: true
Persistent Storage (Embedded NATS)
Durable pipeline on the embedded NATS backend -- the default when no payload or pipeline_bus is set. JetStream switches to FileStorage and payloads move to the NATS Object Store; VMFL/VMF writers stay in-memory. In a cluster, put these settings on the cluster's properties (they must be uniform across all nodes), not per-node.
config/environments/env.yml:
environments:
- name: "1"
status: true
nodes:
- name: "1"
status: true
properties:
persistent_storage:
status: true
For the Enterprise crash-resistant mode, add crash_resistance: true -- the local VMFL/VMF queue writers also go to disk, flushed per record:
persistent_storage:
status: true
crash_resistance: true
External Kafka / Redpanda
Routes the router-to-sender hop over an external Kafka-compatible broker. Requires payload.type: inline -- with any other payload type the bus silently falls back to nats. The topic (vm-pipeline.sender) and consumer group (<director-name>-sender) auto-create where the broker allows it.
config/environments/env.yml:
environments:
- name: "1"
status: true
nodes:
- name: "1"
status: true
properties:
persistent_storage:
status: true
payload:
type: inline
max_size: 512kb
pipeline_bus:
type: kafka
address: "{broker-1}:9092,{broker-2}:9092"
topic_prefix: vm-pipeline
# Optional SASL auth -- omit the block below for a plaintext broker.
# algorithm: plain # plain | scram-sha-256 | scram-sha-512 | gssapi
# username: "{username}"
# password: "{password}"
# tls:
# status: true
The inline payload rides base64-encoded inside the bus message, so max_size caps the raw payload before encoding (~4/3 on the wire). 512kb (~683 KB encoded) stays under a default broker's ~1 MB message.max.bytes; raise it only in step with the broker limit. For crash resistance, add crash_resistance: true under persistent_storage (the shipped example also raises max_size to 1mb).
Azure Event Hubs (Kafka endpoint)
Uses the Event Hubs Kafka endpoint as the pipeline bus -- the durable-broker option for ephemeral deployments (e.g. Azure Container Apps) with no durable local disk, where in-flight data survives a container restart inside the managed broker. SASL PLAIN over TLS on port 9093.
config/environments/env.yml:
environments:
- name: "{director-id}"
status: true
nodes:
- name: "{director-id}"
status: true
properties:
persistent_storage:
status: true
payload:
type: inline
max_size: 512kb
pipeline_bus:
type: kafka
address: "{namespace}.servicebus.windows.net:9093"
topic_prefix: vm-pipeline
algorithm: plain
username: "$ConnectionString"
password: "Endpoint=sb://{namespace}.servicebus.windows.net/;SharedAccessKeyName={policy};SharedAccessKey={key}"
tls:
status: true
Event Hubs does not auto-create topics: pre-create the event hub vm-pipeline.sender and the consumer group <director-name>-sender before starting the Director -- a missing topic drops 100% of pipeline traffic. Keep payload.max_size at or below the namespace tier's message cap (Basic 256 KB, Standard/Premium 1 MB, Dedicated 20 MB), measured on the raw payload before base64. Add crash_resistance: true under persistent_storage for the Enterprise crash-resistant mode.