Skip to main content
Mole configuring listeners

Listener Configuration

Let other agents connect to you. Choose QUIC for best performance, HTTP/2 or WebSocket to bypass firewalls that block UDP.

Quick setup:

listeners:
- transport: quic # Best performance (UDP)
address: "0.0.0.0:4433"

- transport: h2 # Firewall-friendly (TCP/HTTPS)
address: "0.0.0.0:443"
path: "/mesh"

Configuration

Listeners use the global TLS configuration by default:

tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: true

listeners:
- transport: quic # quic, h2, ws
address: "0.0.0.0:4433" # Bind address

Transport Types

QUIC Listener

Best performance, UDP-based:

tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: true

listeners:
- transport: quic
address: "0.0.0.0:4433"

HTTP/2 Listener

TCP-based, firewall-friendly:

listeners:
- transport: h2
address: "0.0.0.0:8443"
path: "/mesh" # Optional URL path

WebSocket Listener

Maximum compatibility:

listeners:
- transport: ws
address: "0.0.0.0:443"
path: "/mesh" # Required for WebSocket

Plain WebSocket (Reverse Proxy)

For deployments behind a reverse proxy that handles TLS termination:

listeners:
- transport: ws
address: "127.0.0.1:8080" # Bind to localhost only
path: "/mesh"
plaintext: true # No TLS - proxy handles it

The plaintext option:

  • Accepts unencrypted WebSocket connections (ws://)
  • Only available for ws transport
  • Does not require TLS certificates
  • Should only be used behind trusted reverse proxies

Security considerations:

  • Always bind to 127.0.0.1 to prevent direct external access
  • Block the plaintext port from external access via firewall
  • mTLS client authentication is not available in this mode
  • Peer authentication and end-to-end encryption still work

See Reverse Proxy Deployment for Nginx, Caddy, and Apache configuration examples.

Multiple Listeners

An agent can listen on multiple transports simultaneously:

tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: true

listeners:
# Primary: QUIC for direct connections
- transport: quic
address: "0.0.0.0:4433"

# Fallback: HTTP/2 for firewall traversal
- transport: h2
address: "0.0.0.0:8443"
path: "/mesh"

# Alternative: WebSocket for maximum compatibility
- transport: ws
address: "0.0.0.0:443"
path: "/mesh"

TLS Configuration

Using Global Settings

By default, listeners use the global TLS configuration:

tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: true

listeners:
- transport: quic
address: "0.0.0.0:4433"
# Uses global cert, key, and mtls setting

Per-Listener Overrides

Override specific settings per listener:

tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: true

listeners:
# Uses global settings
- transport: quic
address: "0.0.0.0:4433"

# Override: different certificate
- transport: h2
address: "0.0.0.0:8443"
tls:
cert: "./certs/public.crt"
key: "./certs/public.key"

# Override: disable mTLS
- transport: ws
address: "0.0.0.0:443"
tls:
mtls: false

Mutual TLS (mTLS)

mTLS is controlled by the global mtls setting or per-listener override:

tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: true # Global: require client certs

listeners:
- transport: quic
address: "0.0.0.0:4433"
# mTLS enabled (from global)

- transport: h2
address: "0.0.0.0:8443"
tls:
mtls: false # Override: no client certs required

With mTLS:

  • Only peers with valid certificates can connect
  • Provides mutual authentication
  • Recommended for production

See TLS Configuration for details.

Bind Address

All Interfaces

Accept connections from anywhere:

listeners:
- transport: quic
address: "0.0.0.0:4433" # All IPv4 interfaces

Specific Interface

Bind to specific IP:

listeners:
- transport: quic
address: "192.168.1.10:4433" # Specific interface

IPv6

listeners:
- transport: quic
address: "[::]:4433" # All IPv6 interfaces

Localhost Only

For testing or local-only access:

listeners:
- transport: quic
address: "127.0.0.1:4433" # Localhost only

Port Selection

TransportDefault PortAlternative Ports
QUIC4433Any UDP port
HTTP/28443, 443Any TCP port
WebSocket443, 80Any TCP port

Firewall Considerations

# For restrictive firewalls, use HTTPS port
listeners:
- transport: h2
address: "0.0.0.0:443"

# Or WebSocket on standard HTTPS
listeners:
- transport: ws
address: "0.0.0.0:443"
path: "/mesh"

URL Path

HTTP/2 and WebSocket support URL paths:

listeners:
- transport: h2
address: "0.0.0.0:443"
path: "/mesh/v1"

Peers must use matching path:

peers:
- transport: h2
address: "server.example.com:443"
path: "/mesh/v1"

Examples

Development

tls:
ca: "./certs/ca.crt"
cert: "./certs/agent.crt"
key: "./certs/agent.key"
mtls: false # Relax for development

listeners:
- transport: quic
address: "127.0.0.1:4433"

Production (Multi-Transport)

tls:
ca: "/etc/muti-metroo/certs/ca.crt"
cert: "/etc/muti-metroo/certs/agent.crt"
key: "/etc/muti-metroo/certs/agent.key"
mtls: true

listeners:
# QUIC for performance
- transport: quic
address: "0.0.0.0:4433"

# HTTP/2 for TCP fallback
- transport: h2
address: "0.0.0.0:443"
path: "/mesh"

Containers

tls:
ca_pem: "${TLS_CA}"
cert_pem: "${TLS_CERT}"
key_pem: "${TLS_KEY}"
mtls: true

listeners:
- transport: quic
address: "0.0.0.0:4433"

Troubleshooting

Port Already in Use

# Find what's using the port
lsof -i :4433
netstat -tlnp | grep 4433

# Kill the process or choose different port

Permission Denied

Ports below 1024 require root on Linux:

# Option 1: Use port > 1024
address: "0.0.0.0:4433"

# Option 2: Run as root (not recommended)
sudo muti-metroo run -c config.yaml

# Option 3: Use capabilities
sudo setcap 'cap_net_bind_service=+ep' muti-metroo

Certificate Errors

# Verify certificate
muti-metroo cert info ./certs/agent.crt

# Check key matches certificate
openssl x509 -noout -pubkey -in agent.crt | openssl md5
openssl ec -in agent.key -pubout 2>/dev/null | openssl md5
# (should match)