TCP routing

Sōzune can forward raw TCP traffic to your services. Two pieces:

  • Listeners are declared statically in config.yaml. Each listener binds a port at startup.
  • Backends attach dynamically through Docker labels and reference a listener by name.

A label that points at an undeclared listener is ignored with a warning. Sōzune does not open ports on the fly from labels alone — by design, to keep startup state predictable.

Declare listeners

proxy:
  http:
    listen_address: 80
  https:
    listen_address: 443
  tcp:
    - name: postgres
      listen: 5432
    - name: redis
      listen: 6379
FieldDescription
nameIdentifier referenced by service labels. Must be unique across proxy.tcp.
listenPort to bind on 0.0.0.0.

Attach a backend with Docker labels

services:
  db:
    image: postgres:16
    labels:
      - "sozune.enable=true"
      - "sozune.tcp.db.entrypoint=postgres"
      - "sozune.tcp.db.port=5432"
LabelDescription
sozune.tcp.<svc>.entrypointName of a listener declared under proxy.tcp. Required. Routes are dropped with diagnostic E005 if missing.
sozune.tcp.<svc>.portBackend port on the container. Defaults to 8080 (informational diagnostic emitted).
sozune.tcp.<svc>.priorityHigher wins when multiple services share the same listener (default 0).

The container's IP is resolved through the same network rules as HTTP — see Docker labels and sozune.network to pick a network when the container is on several.

Limitations

  • No TLS termination. Sōzu's TCP path is pure passthrough — TLS bytes flow as-is. For client-side STARTTLS protocols (PostgreSQL, MySQL) this is fine; for terminating TLS, use an HTTPS entrypoint instead.
  • No half-close. Sōzu treats a client FIN as a full disconnect, so protocols that rely on half-closing one direction to signal end-of-stream may misbehave. Most request/response and long-lived stream protocols are unaffected.
  • No IP allowlist or connection-rate limit yet. Both are not currently implemented for TCP entrypoints.

Errors and diagnostics

CodeMeaning
E005A sozune.tcp.<svc> service has no entrypoint= label. The route is dropped.
Log: references undeclared listenerThe label points at a name not present in proxy.tcp. The route is dropped. Add the listener to the config or fix the label.