Documentation · Configuration
Configuration examples
Four configurations covering common deployments — single broker, three-broker cluster, upstream TLS, and SNI-routed downstream TLS.
Klamm reads a single YAML file passed via --config. Relative paths inside
it — password_file, cert_file, key_file, ca_file — resolve against
the config file’s directory.
Single broker
# proxy.yaml
proxy:
listener_sets:
- name: plaintext
port_range:
bind_host: "127.0.0.1"
advertised_host: "127.0.0.1"
bootstrap_port: 29092
broker_port_range:
start: 29093
end: 29093
broker_id_base: 1
admin:
bind: "127.0.0.1:28080"
upstream:
bootstrap:
- "127.0.0.1:9092"
tenants:
- name: tenant-a
auth:
credentials:
- username: tenant-a
password_file: "secrets/tenant-a.password"
Run it with the published image, mounting the config directory:
docker run --rm --network host \
-v "$PWD:/etc/klamm:ro" -w /etc/klamm \
jerrinot/klamm:snapshot --config /etc/klamm/proxy.yaml
--network host keeps 127.0.0.1:9092 reachable on Linux. On Docker Desktop
replace it with published ports (-p 29092:29092 -p 28080:28080) and point
upstream.bootstrap at host.docker.internal:9092.
Clients connect to 127.0.0.1:29092 using SASL/PLAIN with username=tenant-a.
SCRAM-SHA-256 and SCRAM-SHA-512 use the same tenant credential material when
clients prefer SCRAM. This example omits allowed_topics, so it uses dynamic
namespace mode: producing to a new logical topic creates or uses the
tenant-prefixed physical topic upstream when the broker allows topic
auto-creation.
Listener-set-bound tenant (no downstream SASL)
For compatibility testing or trusted local fixtures, a listener set can skip downstream SASL and bind every connection on that listener set to one tenant:
proxy:
listener_sets:
- name: local-no-auth
auth:
mode: none
tenant: tenant-a
port_range:
bind_host: "127.0.0.1"
advertised_host: "127.0.0.1"
bootstrap_port: 29092
broker_port_range:
start: 29093
end: 29093
broker_id_base: 1
This does not disable tenant isolation or topic/group/transactional-id
rewriting. It only replaces per-connection SASL identity with
listener-set-scoped tenant identity; sessions are recorded as user anonymous.
Three-broker cluster
Expose one bootstrap route and a deterministic broker port range. Broker IDs are discovered from upstream Metadata. The example maps broker 1 to port 29093, broker 2 to 29094, and broker 3 to 29095.
proxy:
listener_sets:
- name: plaintext
port_range:
bind_host: "0.0.0.0"
advertised_host: "proxy.example.com"
bootstrap_port: 29092
broker_port_range:
start: 29093
end: 29095
broker_id_base: 1
admin:
bind: "0.0.0.0:28080"
upstream:
bootstrap:
- "kafka1:9092"
- "kafka2:9092"
- "kafka3:9092"
tenants:
- name: team-payments
auth:
credentials:
- username: payments-prod
password_file: "secrets/payments.password"
allowed_topics:
- transactions
- settlements
- name: team-analytics
auth:
credentials:
- username: analytics-prod
password_file: "secrets/analytics.password"
allowed_topics:
- transactions
- page-views
Both tenants can access transactions, but each sees only their own consumer
groups. team-payments cannot see page-views; team-analytics cannot see
settlements.
Upstream TLS
Set upstream.tls.ca_file when brokers require TLS:
upstream:
tls:
ca_file: "certs/upstream-ca.pem"
bootstrap:
- "broker-1.kafka.example.com:9093"
- "broker-2.kafka.example.com:9093"
The proxy verifies broker certificates against the configured CA bundle. TLS SNI and certificate server-name verification use the host part of each upstream address discovered from the bootstrap Metadata path.
TLS with SNI routing
proxy:
listener_sets:
- name: tls-sni
auth:
mode: required
tls:
cert_file: "certs/server.pem"
key_file: "certs/server-key.pem"
sni:
bind: "0.0.0.0:9092"
bootstrap_host: "bootstrap.kafka.example.com"
broker_host_template: "broker-{broker_id}.kafka.example.com"
SNI routing lets the bootstrap host and broker hosts share a single TLS port. The proxy routes based on the TLS Server Name Indication field; clients that do not send SNI are rejected for an SNI-routing listener.
DNS must point both the bootstrap host and every generated broker host to the
proxy. With the example above, bootstrap.kafka.example.com and names such as
broker-1.kafka.example.com must resolve to the proxy address. The downstream
TLS certificate must also be valid for those names, either through explicit
SANs or a wildcard such as *.kafka.example.com.
Reference Every YAML option accepted by the config loader, with defaults and constraints, is listed in the configuration reference.