Skip to content

Proxy Config Reference

This document describes the configuration options for QHx Proxy, including configuration file format, command-line flags, and environment variables.

QHx Proxy accepts configuration from two sources:

  1. Configuration file: A YAML file specified with the -config flag
  2. Environment variable: YAML configuration in the QHX_PROXY_CONFIG environment variable. This is direct YAML text, not a filename.

If no -config flag is provided, the proxy will read the configuration from the QHX_PROXY_CONFIG environment variable. If neither is provided, the proxy will exit with an error.

The following command line flags are supported:

  • -config <string>: Path to the YAML configuration file. If not specified, YAML configuration data is taken directly from the environment variable QHX_PROXY_CONFIG.

  • -zap-log-level <value>: Configure logging level (debug, info, error, panic or an integer). Higher integer values give higher verbosity.

  • -zap-encoder {json | console}: Configures the logging output format.

  • -zap-devel: Enables development mode logging configuration.

  • Type: String (YAML or JSON content)
  • Required: Only if -config flag is not provided
  • Description: Complete YAML/JSON configuration as a string

Example:

Terminal window
export QHX_PROXY_CONFIG='
spiffe:
workload_socket_path: "unix:///tmp/spire-agent/public/api.sock"
listeners:
- name: "example"
address: ":8080"
mode: "client"
target:
url: "https://example.com"
'

The configuration file uses YAML with the following structure:

# SPIFFE configuration (required)
spiffe:
workload_socket_path: "unix:///tmp/spire-agent/public/api.sock"
# Optional: TLS key logging for debugging
keylog: "/path/to/keylog.txt"
# Listeners configuration (required - at least one)
listeners:
- name: "example-client"
address: ":8081"
protocol: http
mode: client
target:
url: https://onward.example:8081
spiffe_id: "^spiffe://qhx.dev/ns/foo/sa/bar/.*$"
- name: "example-server"
address: ":8082"
protocol: http
mode: server
source:
spiffe_ids:
- "^spiffe://qhx.dev/ns/foo/sa/bar/.*$"
target:
url: http://localhost:8083

The spiffe section configures SPIFFE/SPIRE integration:

  • Type: String
  • Required: Yes
  • Description: Path to SPIRE Workload API socket
  • Format: Unix socket path (e.g., unix:///tmp/spire-agent/public/api.sock)
  • Type: String
  • Required: No
  • Description: Path to TLS key log file for debugging TLS connections
  • Note: Debugging use only — contains cryptographic keys which compromise confidentiality and integrity of TLS connections

The listeners section defines one or more proxy listeners. Each listener operates independently and can be configured in different modes.

  • Type: String
  • Required: Yes
  • Description: Unique name for the listener
  • Constraints: Must be unique across all listeners
  • Type: String
  • Required: Yes
  • Description: Network address to listen on
  • Format: host:port (e.g., :8080, 127.0.0.1:8081, 0.0.0.0:9000)
  • Type: String
  • Required: Yes
  • Values: "client", "server" or "central"
  • Description:
    • client: Client mode - forwards requests over secure mTLS transport
    • server: Server mode - terminates mTLS and forwards to target servers
    • central: Central mode - terminates mTLS and forwards to target servers over mTLS in turn
  • Type: String
  • Default: "http"
  • Values: "http", "tcp" or "mqtt"
  • Description: Protocol to use for proxying

For tcp protocol listeners, the target.url scheme should be set as follows:

  • client or central: tls://host:port (mTLS hop)
  • server: tcp://host:port (plaintext hop)

For mqtt protocol listeners, the target.url scheme should be set as follows:

  • client or central: mqtts://host:port (mTLS hop)
  • server: mqtt://host:port (plaintext hop)

Each listener must specify a target using the target section:

  • Type: String
  • Required: Yes
  • Description: Target URL to proxy requests to
  • Format: Full URL including scheme (e.g., https://api.example.com:8443, http://backend:8080)
  • Type: String
  • Required: No (recommended for client mode; validation omitted if not specified)
  • Description: Expected SPIFFE ID of the target service
  • Format: SPIFFE ID URI (e.g., spiffe://example.org/service-name)
  • Note: Used in client mode to validate the target’s identity

For server mode listeners, you can restrict which clients are allowed to connect:

  • Type: Array of strings
  • Required: No
  • Description: List of allowed client SPIFFE ID patterns (each pattern is a regular expression)
  • Default: If not specified, any authenticated SPIFFE client is allowed
  • Format: Regular expressions matching SPIFFE ID URIs

Example:

source:
spiffe_ids:
- "spiffe://example\\.org/web-.*" # Allow web services
- "spiffe://trusted\\.domain/.*" # Allow any service from trusted domain
- "spiffe://example\\.org/api-client" # Allow specific client

Each listener can specify custom timeouts:

  • Type: Duration string
  • Default: "15s"
  • Description: Maximum time to read request headers and body
  • Format: Go duration format (e.g., "30s", "1m", "500ms")
  • Type: Duration string
  • Default: "60s"
  • Description: Maximum time to write response
  • Format: Go duration format (e.g., "30s", "2m", "5000ms")
  • Type: Duration string
  • Default: "120s"
  • Description: Maximum time to wait for next request on keep-alive connections
  • Format: Go duration format (e.g., "60s", "5m")
  • Type: Boolean
  • Default: false
  • Description: Disables connection reuse for outgoing connections made to mTLS peers.

This middleware provides notarization support for the OpenAI HTTP API.

listeners:
- name: http
protocol: http
...
middlewares:
- name: openai
notary:
enable: true
database:
path: /var/lib/notary.db

This middleware provides notary query support for the HTTP protocol implementation. It can be used to obtain signed workload identity statements and request receipts over HTTP from the notary.

listeners:
- name: http
protocol: http
...
middlewares:
- name: notary-query

This middleware provides DDIL store-and-forward support in intermittent connectivity environments for the MQTT protocol module.

listeners:
- name: "mqtt-buffered"
address: ":1883"
mode: "client"
protocol: "mqtt"
target:
url: "mqtts://broker.example.com:8883"
middlewares:
- type: "buffer"
storage:
type: "in-memory" # Must be 'in-memory'
max-bytes: 33554432 # 32MiB
max-messages: 0 # unlimited
max-ttl: 0s # unlimited
overflow-policy: "reject" # One of 'drop-oldest', 'drop-newest' or 'reject'
reconnect-backoff:
initial: 1s
max: 30s

buffer behavior:

  • When using QoS 0, messages are persisted into the local buffer. Replay to upstream is attempted and re-attempted asynchronously in the background. Relay of messages to the upstream occur without ACK coordination. Re-delivery attempts are allowed, and duplicate message delivery is possible (at-least-once delivery).

  • When using QoS 1, an ACK is returned to the downstream client after persisting the data into the local buffer. As with QoS 0, replay to upstream is attempted and re-attempted asynchronously in the background. However, message IDs are used to avoid duplicate deliveries in the event of re-delivery attempts.

  • QoS 2 is currently unsupported when the buffer middleware is used.

Defaults:

  • storage.type: in-memory
  • storage.max-bytes: 32MiB
  • storage.max-messages: unlimited (0)
  • storage.max-ttl: unlimited (0s)
  • overflow-policy: reject
  • reconnect-backoff.initial: 1s
  • reconnect-backoff.max: 30s

storage.type defines the storage backend. Currently, only the in-memory store is supported.

storage.max-bytes defines the maximum buffer size of buffered messages.

storage.max-messages defines the maximum number of messages in the buffer (0: unlimited).

If storage.max-bytes or storage.max-messages are hit, the overflow-policy is enforced.

overflow-policy defines what happens if the buffer overflows. The supported values are drop-oldest (drop oldest message), drop-newest (drop newest messages), or reject (reject publish command).

reconnect-backoff defines the initial and maximum reconnection delays in the event that the upstream connection fails.

This example configures QHx Proxy in client mode using the HTTP protocol. The application is able to make unencrypted HTTP requests to http://localhost:8081, which are encapsulated in a post-quantum secure mTLS connection to a peer QHx Proxy instance in server mode or a QHx Proxy instance in central mode. The mTLS connection is based on mutual authentication using cryptographically secure, post-quantum safe workload identities for both client and server, which is entirely transparent to the application.

spiffe:
workload_socket_path: "unix:///tmp/spire-agent/public/api.sock"
listeners:
- name: "api-client"
## Listen on localhost:8081 in client mode using the HTTP protocol
address: "127.0.0.1:8081"
mode: "client"
protocol: "http"
target:
## Destination address
url: "https://api.example.com:8443"
## Require the destination to match this workload identity
spiffe_id: "spiffe://example.org/api-server"
timeouts:
read: "30s"
write: "60s"
idle: "300s"

This example configures QHx Proxy in server mode using the HTTP protocol. Incoming requests are required to use mTLS and are verified as using a post-quantum safe workload identity which is authorized according to the configuration below. The request is then de-encapsulated and forwarded to the local application server.

spiffe:
workload_socket_path: "unix:///tmp/spire-agent/public/api.sock"
listeners:
- ## Listen on :8443 in server mode using the HTTP protocol
name: "secure-gateway"
address: ":8443"
mode: "server"
protocol: "http"
target:
## Forward to this pod-internal service
url: "http://localhost:8080"
source:
spiffe_ids:
## Allow connections from clients with these IDs
- "spiffe://example\\.org/web-.*"
- "spiffe://example\\.org/api-gateway"
timeouts:
read: "15s"
write: "60s"
idle: "120s"
spiffe:
workload_socket_path: "unix:///tmp/spire-agent/public/api.sock"
notary:
enable: true
database:
path: /var/qhx/notary/notary.db
listeners:
# Central mode listener
- name: central-http
address: ":8081"
mode: central
protocol: http
target:
url: "https://service:8081"
spiffe_ids:
- "spiffe://qhx.dev/foo"
source:
spiffe_ids:
- "spiffe://qhx.dev/bar"
middleware:
- type: openai
- type: notary-query
spiffe:
workload_socket_path: "unix:///tmp/spire-agent/public/api.sock"
listeners:
# TCP client mode listener (plaintext in, mTLS out)
- name: tcp-client
address: ":9001"
mode: client
protocol: tcp
target:
url: "tls://central.example.com:9443"
spiffe_ids:
- "spiffe://example.org/central"
# TCP server mode listener (mTLS in, plaintext out)
- name: tcp-server
address: ":9443"
mode: server
protocol: tcp
target:
url: "tcp://localhost:5432"
source:
spiffe_ids:
- "spiffe://example.org/app-.*"
spiffe:
workload_socket_path: "unix:///tmp/spire-agent/public/api.sock"
listeners:
# Client mode listener
- name: "external-api-client"
address: ":8081"
mode: client
protocol: http
target:
url: "https://api.external.com"
spiffe_id: "spiffe://external.example.org/api"
# Server mode listener
- name: "internal-server"
address: ":8082"
mode: server
protocol: http
target:
url: "http://backend:3000"
source:
spiffe_ids:
- "spiffe://internal\\.example\\.org/.*"