Skip to main content

Listener Commands

Commands for managing dynamic transport listeners.

Transport listeners are the QUIC/HTTP2/WebSocket sockets that accept inbound peer connections (the top-level listeners: config block). Dynamic listeners let you open or close one on an already-running agent without editing config.yaml and restarting. A common use case: bring up a second ingress on a different port or transport to migrate peers, or expose a plaintext WebSocket endpoint behind a reverse proxy on demand.

Listeners are uniquely keyed by listen address. Dynamic listeners persist across agent restarts when agent.data_dir is set (see Dynamic Config Persistence) and are restored across sleep/wake. They reuse the agent's global TLS certificate (or an auto-generated self-signed one) and the global mTLS setting.

listener add​

Add a dynamic transport listener.

muti-metroo listener add <transport> <address> [flags]

Description​

Opens a new listener on the target agent. <transport> is one of quic, h2, or ws; <address> is the bind address (:4433, 0.0.0.0:4433, 127.0.0.1:3002). HTTP/2 and WebSocket listeners require --path.

The listener reuses the agent's global TLS configuration. --plaintext starts a WebSocket listener without TLS, for use behind a trusted reverse proxy. Supply --advertise-address to publish a public dial target via NodeInfo so other agents can discover and dial the listener.

When agent.data_dir is configured the listener survives agent restarts via the dynamic config journal; if no data_dir is set (or the journal is not writable) it remains ephemeral and is lost on restart.

Flags​

FlagShortDefaultDescription
--agent-alocalhost:8080Agent API address (host:port or http(s):// URL)
--target-tTarget agent ID (omit for local agent)
--pathHTTP path for h2/ws listeners (e.g. /ws/)
--plaintextfalseStart a WebSocket listener without TLS (ws only)
--advertise-addressPublic host:port to advertise to the mesh
--advertise-pathPath to advertise for h2/ws (defaults to --path)
--advertise-transportTransport to advertise (defaults to the listener transport)

Examples​

# Open a new QUIC listener on the local agent
muti-metroo listener add quic :4434

# Open a plaintext WebSocket listener behind a reverse proxy
muti-metroo listener add ws 127.0.0.1:3002 --path /ws/ --plaintext

# Open a listener and advertise its public dial target to the mesh
muti-metroo listener add quic :4433 --advertise-address vps.example.com:4433

# Tell remote agent D (reachable via mesh) to open a listener
muti-metroo listener add quic :4433 --target <agent-d-id>

Output​

Listener added: listener :4434 added (transport=quic)

listener remove​

Remove a dynamic transport listener.

muti-metroo listener remove <address> [flags]

Description​

Stops accepting new inbound connections on the listener at the given address and tears the socket down. Existing peer connections established through it are not affected.

Only dynamic listeners can be removed this way. Listeners declared in the listeners: config are protected and cannot be removed without restarting the agent.

This command prompts for confirmation; pass --yes / -y to skip in scripts.

Flags​

FlagShortDefaultDescription
--agent-alocalhost:8080Agent API address (host:port or http(s):// URL)
--target-tTarget agent ID (omit for local agent)

Examples​

# Remove a dynamic listener from the local agent
muti-metroo listener remove :4434

# Remove from a remote agent
muti-metroo listener remove :4434 -t abc123def456

Output​

Listener removed: listener :4434 removed

listener list​

List all transport listeners.

muti-metroo listener list [flags]

Description​

Displays every transport listener known to the agent: static (config-file) and dynamic (runtime). Reports transport, address, path, TLS mode, and whether a dial target is advertised.

Flags​

FlagShortDefaultDescription
--agent-alocalhost:8080Agent API address (host:port or http(s):// URL)
--target-tTarget agent ID (omit for local agent)
--jsonfalseOutput in JSON format

Examples​

# List listeners on local agent
muti-metroo listener list

# List listeners on remote agent
muti-metroo listener list -t abc123def456

# JSON output
muti-metroo listener list --json

Output​

Standard output:

Listeners (2)
ADDRESS TRANS PATH TLS TYPE ADVERTISE
:4433 quic - tls static vps.example.com:4433
127.0.0.1:3002 ws /ws/ plaintext dynamic -

JSON output:

{
"status": "ok",
"listeners": [
{
"transport": "quic",
"address": ":4433",
"plaintext": false,
"advertise_address": "vps.example.com:4433",
"dynamic": false
},
{
"transport": "ws",
"address": "127.0.0.1:3002",
"path": "/ws/",
"plaintext": true,
"dynamic": true
}
]
}

Authorization​

Dynamic listener modifications follow the same rules as dynamic route, forward, and peer management. If an agent has management.public_key configured but does NOT have the corresponding management.private_key, listener add/remove/list commands are rejected with HTTP 403 Forbidden. Add/remove on a remote agent (via --target) additionally require a valid management signature; list is read-only.


Important Notes​

Persistence​

Dynamic listeners survive agent restarts when agent.data_dir is configured: every add/remove is appended to a dynamic config journal under data_dir/dynamic-config.log and replayed on the next start. They are also restored when the agent wakes from sleep mode.

If no data_dir is configured, or the journal file cannot be written, the runtime mutation still succeeds but remains ephemeral: the listener is lost on the next restart.

Listeners declared in config.yaml take precedence and cannot be replaced or removed at runtime.

TLS Settings​

Dynamic listeners inherit the agent's global TLS certificate, key, and mTLS setting. Per-listener certificate overrides are not supported at runtime; use config.yaml if you need different TLS material for a specific listener. --plaintext (ws only) starts the listener without TLS for reverse-proxy deployments.

Replacing Dynamic Listeners​

Re-running listener add with the same address stops the old listener and starts a fresh one with the new settings. Config-file listeners cannot be replaced at runtime.