Configuration

CntrlNode is configured via environment variables or a YAML config file. Environment variables take precedence over the config file.

Environment variables

VariableDefaultDescription
CNTRLNODE_PORT7474HTTP/2 server port
CNTRLNODE_STORAGEbboltStorage backend: bbolt or postgres
CNTRLNODE_DB_PATH./cntrlnode.dbPath to bbolt database file
CNTRLNODE_DB_URL(required for postgres)PostgreSQL connection string
CNTRLNODE_OLLAMA_HOSTlocalhost:11434Ollama host for embeddings
CNTRLNODE_EMBED_MODELnomic-embed-textEmbedding model name
CNTRLNODE_AUTH_ENABLEDfalseEnable API key authentication
CNTRLNODE_API_KEYS(empty)Comma-separated list of valid API keys
CNTRLNODE_LOG_LEVELinfoLog level: debug, info, warn, error
CNTRLNODE_DEVfalseDev mode: verbose logging, mock embeddings

YAML config file

Create config.yaml (or pass --config <path> at startup):

port: 7474
storage: bbolt
dbPath: ./cntrlnode.db
logLevel: info
dev: false

auth:
  enabled: false
  apiKeys: []

ollama:
  host: localhost:11434
  embedModel: nomic-embed-text

Startup flags

./cntrlnode start --config ./config.yaml
./cntrlnode start --port 8080
./cntrlnode start --storage postgres --db-url postgres://localhost/cntrlnode

Storage backends

bbolt (default — dev mode)

Zero dependencies. State is persisted to a single file on disk. Suitable for development, single-node deployments, and testing.

CNTRLNODE_STORAGE=bbolt
CNTRLNODE_DB_PATH=./cntrlnode.db

PostgreSQL (production)

Requires PostgreSQL 14+ with the pgvector extension for semantic agent discovery.

CNTRLNODE_STORAGE=postgres
CNTRLNODE_DB_URL=postgres://user:pass@localhost:5432/cntrlnode?sslmode=require

Run migrations on first start (automatic) or manually:

psql $DATABASE_URL -f migrations/001_init.sql

Ollama (semantic discovery)

Semantic agent discovery (/v1/registry/discover with a query field) requires Ollama running locally with the nomic-embed-text model pulled:

ollama pull nomic-embed-text

If Ollama is unavailable, tag-based discovery still works — semantic discovery gracefully falls back.

In dev mode (CNTRLNODE_DEV=true), a mock embedder is used so Ollama is not required.

Log output

CntrlNode logs structured JSON to stdout:

{"level":"info","time":"2024-01-15T10:30:00Z","message":"server started","port":7474,"storage":"bbolt"}
{"level":"info","time":"2024-01-15T10:30:05Z","message":"agent registered","id":"researcher-1","tags":["research","pdf"]}

Pipe through jq for human-readable output in development:

./cntrlnode start | jq .

Complete example

# Production with PostgreSQL and auth
CNTRLNODE_PORT=7474 \
CNTRLNODE_STORAGE=postgres \
CNTRLNODE_DB_URL=postgres://cntrlnode:secret@db:5432/cntrlnode \
CNTRLNODE_AUTH_ENABLED=true \
CNTRLNODE_API_KEYS=key-prod-abc123,key-svc-def456 \
CNTRLNODE_LOG_LEVEL=info \
./cntrlnode start