Skip to content

gRPC and conduitctl

This page is the connection and command reference for the optional control plane: enabling gRPC, pointing conduitctl at a server, and invoking each subcommand. For when to reload, apply an overlay, or export, see Reload and export. For how config layers merge, see Configuration model.

Enabling the control plane

Conduit starts the gRPC listener only when the process starts with a control: block that sets listen_address (for example 127.0.0.1:5199). Without it, DNS still runs but conduitctl apply, export, reload, trace, health, and live acl check are unavailable — use SIGHUP or a process restart to reload from disk instead. Offline validate --file and acl check --file still work.

Adding or changing control: via reload updates the stored config but does not start or rebind the listener today. Restart conduit after enabling or moving the control address.

Config fields: Reference: control.

Connecting

Every remote conduitctl subcommand shares one connect helper. Settings resolve in this order: CLI flags → environment variables → optional YAML client config file → built-in defaults. A missing client file is not an error.

Offline commands (validate --file, acl check --file) do not need the client file or a running control plane.

Client configuration file

Default path (YAML):

Platform Path
Unix (XDG) $XDG_CONFIG_HOME/conduit/conduitctl.yaml, or ~/.config/conduit/conduitctl.yaml
Windows %APPDATA%\conduit\conduitctl.yaml

Override the path with --config or CONDUITCTL_CONFIG.

Example file:

endpoint: https://conduit.example:5199
api_key_file: ~/secrets/conduit-api-key   # prefer a path over inline api_key
tls:
  ca: ~/tls/ca.pem
  cert: ~/tls/client.pem                  # mTLS when the server requires a client cert
  key: ~/tls/client-key.pem
  # insecure_skip_verify: true            # opt-in only — see TLS below

Flags, env, and file fields

Setting Flag Env Client file
Endpoint --endpoint CONDUIT_CONTROL endpoint
API key (inline) --api-key CONDUIT_API_KEY api_key (discouraged)
API key file --api-key-file CONDUIT_API_KEY_FILE api_key_file
Trust CA / bundle --tls-ca CONDUIT_TLS_CA tls.ca
Client cert (mTLS) --tls-cert CONDUIT_TLS_CERT tls.cert
Client key (mTLS) --tls-key CONDUIT_TLS_KEY tls.key
Skip verify --tls-insecure CONDUIT_TLS_INSECURE tls.insecure_skip_verify
Client config path --config CONDUITCTL_CONFIG —

Built-in default endpoint: http://127.0.0.1:5199. Use http:// for plain TCP; use https:// when control.tls is configured on the server.

TLS verification (HTTPS)

For https:// endpoints, conduitctl by default:

  1. Validates the server certificate chain against the configured trust store (--tls-ca / tls.ca, otherwise the client’s normal trusted roots), and
  2. Verifies that the certificate identity matches the endpoint hostname (DNS SAN / usual TLS rules, or IP SAN when the host is an IP).

Present a client certificate and key when the server sets control.tls.client_ca_path (mTLS). Server-side setup: mTLS.

Skip-verify (--tls-insecure / CONDUIT_TLS_INSECURE / tls.insecure_skip_verify) disables chain and hostname verification. It is a supported opt-out for self-signed server certificates when you do not distribute a CA to every client host. Prefer pinning a CA when practical. Skip-verify is never the default and is not implied by using https:// or setting other TLS fields. Treat it as a weakened transport authentication mode.

On success, mutating commands print ok to stdout (and may print generation=… when the server returns it). Failures exit non-zero with error text on stderr.

Authentication

Server config Client requirement
control.api_keys empty No credentials (anonymous access to control RPCs)
control.api_keys non-empty Valid key via Authorization: Bearer … or header x-api-key — conduitctl uses Bearer (--api-key / CONDUIT_API_KEY)
control.tls.client_ca_path set Server requires a client certificate (mTLS) in addition to any API key rules

Details: API keys, mTLS.

Config control vs runtime control

Two families share the same gRPC listener and conduitctl connect settings:

Family What it changes Examples Shows up in export?
Config control Effective configuration (file layer and/or overlay) through the Configurator apply, reload, export, typed primitives (pool, backend, orchestrator, …) Yes — after a successful mutation
Runtime control Observed operator state outside effective config health freeze / drain / resume No — health runtime state is separate

Changing a backend’s weight is config control (conduitctl backend set-weight or an overlay apply). Drain / freeze is runtime control (conduitctl health) and is not a substitute for a weight change. Details: Backend health.

Commands

Command Needs server? Purpose
conduitctl apply Yes Patch the in-memory overlay (apply modes)
conduitctl export Yes Print effective config as YAML
conduitctl reload Yes Reload from disk; clear overlay
conduitctl validate --file No Offline YAML validation and runtime snapshot compile (Rhai, data sources, forward)
conduitctl acl check Yes (default) Dry-run client ACL for an IP against the live snapshot
conduitctl acl check --file No Same dry-run against a local config file (twin of validate)
conduitctl trace Yes Fetch pipeline trace events for a transaction id
conduitctl health Yes Per-backend health show, freeze, set up/down (drain), resume automatic
conduitctl pool / backend Yes Typed pool list/get; backend set-weight / remove
conduitctl orchestrator Yes Get / set overlay-hot orchestrator limits
conduitctl data-source / data-source-limits Yes List/get/upsert/remove data sources; get/set limits
conduitctl events Yes Get events; get/set filters and emit on existing sinks
conduitctl rhai Yes Get / set Rhai sandbox limits
conduitctl metrics Yes Get / patch metrics plan (deep merge)
conduitctl cache Yes List/get; set hot cache knobs (max_entries, LMDB policy, …)

RPC methods and messages: Reference: gRPC and CLI.

Document apply vs typed primitives

Both paths update the same effective config and runtime snapshot:

  • Document workflow — author sparse YAML and conduitctl apply (merge / replace / clear), or edit the startup file and reload. Best when configuration management owns patches or you need a multi-field change in one file.
  • Primitive workflow — typed conduitctl subcommands (and the matching config-primitive gRPC services) for overlay-hot settings. Best for surgical automation (set one weight, adjust a limit). Internally the server mutates effective config, synthesizes a full overlay replacement, then validates and swaps — so interleaved document apply and primitives keep unrelated overlay fields.

Primitives apply only where overlay is allowed and the change takes effect without process restart (including live reconcile after snapshot swap). They do not expose restart-pending-only knobs (for example listener bind, orchestrator.txn_table_capacity, event sink add/remove / queue_depth, caches[].memory.shard_count). Prefer document apply or a restart for those.

export always shows effective config (no remove-marker tombstones). Mutating apply/reload/primitive responses include generation (correlates with conduit_config_generation) and optional status notes.

apply

conduitctl apply --file patch.yaml              # default: merge into overlay
conduitctl apply --merge --file patch.yaml      # explicit merge
conduitctl apply --replace --file patch.yaml    # replace entire overlay
conduitctl apply --clear                        # clear overlay; no --file
Flag Conflicts with Behavior
(default) — Merge patch into accumulated overlay
--merge --replace, --clear Explicit merge (same as default)
--replace --merge, --clear Replace overlay; schema_version-only patch clears overlay
--clear --merge, --replace, --file Clear overlay without re-reading startup file

--file is required for merge and replace; omit it for --clear.

Patch files are sparse YAML — only keys you include are sent. Overlays must not include rules: or tracing:; apply is rejected if those sections are present. metrics: is allowed (deep merge). Semantics, examples, and overlay scope: Reload and export — apply modes. To remove a pool or backend via overlay, set remove: true on the matched entry — see Configuration model — remove marker.

export

conduitctl export                    # stdout
conduitctl export --output PATH      # write file

Returns effective config as YAML (file layer + overlay, defaults normalized). See Reload and export — export.

reload

conduitctl reload

Re-reads the config path from process startup and clears the overlay. Same semantics as SIGHUP when gRPC is enabled. See Reload from disk.

validate

conduitctl validate --file PATH

Runs locally — no control plane connection. Validates YAML structure, then builds the same runtime snapshot Conduit uses at startup and reload: Rhai scripts are read and compiled, data sources are loaded, and forward settings are compiled. Paths resolve relative to the config file directory (or as absolute paths). Failures print prefixed errors (for example script '…': …, rule '…': …, data source '…': …) to stderr and exit non-zero.

The server also exposes ValidateConfig over gRPC for automation that already talks to the control plane; the CLI does not call it today.

acl check

Dry-run client ACL evaluation for one IP. Prints pretty JSON to stdout. Exit code is 0 whenever the check itself succeeds (connect/load/evaluate); the JSON decision fields carry admit / drop / refuse / tag. The check is read-only — it does not bump ACL metrics or emit denial logs.

conduitctl acl check 203.0.113.50
conduitctl acl check 203.0.113.50 --listener public
conduitctl acl check 10.1.2.3 --file /path/to/conduit.yaml
conduitctl acl check 10.1.2.3 --file /path/to/conduit.yaml --listener public
Mode Flag What is evaluated
Live (default) (none) Running process snapshot + in-memory CIDR tables (includes overlay) via CheckAcl
File --file PATH Local compile of that YAML (same path resolution as validate) — no control plane

Omit --listener to return one result object per listener. Filter with --listener NAME (resolved listener name, including the default protocol:address form). Unknown listener or invalid IP exits non-zero.

JSON shape:

{
  "ip": "10.1.2.3",
  "source": "live",
  "results": [
    {
      "listener": "public",
      "decision": "admit",
      "matched": "corp_nets",
      "action": "accept"
    },
    {
      "listener": "internal",
      "decision": "tag",
      "tag": "corp",
      "matched": "corp_nets",
      "action": "tag"
    }
  ]
}

source is live or file. decision is admit, drop, refuse, or tag (tag name in sibling tag). matched is the CIDR view name, or default when default_action applied. action is the matched rule action, or allow / deny for the default.

trace

conduitctl trace TXN_ID

Prints pipeline trace events when tracing captured the transaction. Exits non-zero if no trace was found.

health

Per-backend health inspection and operator controls. Requires the control plane. Behavior: Backend health. RPC reference: Reference: gRPC and CLI — BackendHealth.

conduitctl health show
conduitctl health show --pool default
conduitctl health show --pool default --backend resolver-a

conduitctl health freeze --global
conduitctl health freeze --pool default
conduitctl health freeze --pool default --backend resolver-a

conduitctl health set down --pool default --backend resolver-a
conduitctl health set up --pool default --backend resolver-a

conduitctl health resume --global
conduitctl health resume --pool default --backend resolver-a
Subcommand Purpose
show Print observed/applied health, scope, eligibility, latency EWMA per backend
freeze Freeze — stop probe-driven changes to applied at the scope (--global, --pool, or --pool + --backend)
set up\|down Manually set applied health and imply freeze (drain = set down)
resume Resume automatic — unfreeze and snap applied to observed

--backend accepts the configured backend name or host:port address. Prefer health resume over ad-hoc clear sequences while frozen — see Clear-while-frozen.

Config primitives (examples)

# Pools / backends
conduitctl pool list
conduitctl pool get edge
conduitctl backend set-weight --pool edge --backend primary --weight 50
conduitctl backend remove --pool edge --backend secondary

# Orchestrator / Rhai limits (hot fields only)
conduitctl orchestrator set-limits --max-attempts 5
conduitctl rhai set-limits --max-operations 20000

# Metrics plan (deep-merge patch)
conduitctl metrics patch --enabled false

# Cache hot knobs
conduitctl cache set-max-entries --name answers --max-entries 2500

# Event filters on an existing sink (not sink add/remove)
conduitctl events set-filters --name lab-tap --sample-percent 25

gRPC services for these commands: Reference: gRPC and CLI — Config primitive services.

Access logs

Every control RPC logs at info as control rpc (the transport line): gRPC method (rpc), peer address (peer), whether the connection used TLS (tls: true/false — transport encryption, distinct from requestor mtls), requestor identity (requestor: anonymous, API key, mTLS, or rejected), gRPC status (grpc_code, e.g. Ok, InvalidArgument), and latency (latency_ms). Request and response bodies are not logged.

Connections that never become an RPC — TCP accept errors, or TLS handshake failures (wrong protocol, bad/missing client certificate, etc.) — log at warn as control plane connection failed with tls, error, and peer when known.

Config RPCs (ApplyConfig, ValidateConfig, ReloadFromFile, and mutating config primitives) additionally emit a separate control rpc outcome line (the application line) with rpc, outcome (ok or rejected), error_count, and the joined errors. Successful outcomes (outcome=ok) log at info; rejections (outcome=rejected) log at warn so failed apply/validate/reload attempts stand out while the last-good snapshot stays active.

The two lines report different layers. A config that fails validation is rejected in-band — the RPC still succeeds at the transport layer — so it logs control rpc with grpc_code=Ok and a control rpc outcome at warn with outcome=rejected and error_count>0. conduitctl surfaces the same rejection as a non-zero exit with the validation messages.

gRPC reflection

When control.reflection_enabled: true, Conduit registers the standard gRPC server reflection service for dev and test tooling (for example discovering ConduitControl without a local copy of the proto). Leave reflection off in production unless you need it.