> ## Documentation Index
> Fetch the complete documentation index at: https://docs.codezero.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Listeners

> Configure PostgreSQL listener ports and database credential injection.

For database connections, cordon can inject credentials at the wire protocol level. PostgreSQL listeners are configured as `[[listeners]]` entries, separate from HTTP [routes](/configuration/routes), with `port` for the local listener and `upstream` for the real database host and port.

Prefer [`cordon listener add`](/cli/listener#cordon-listener-add) and [`cordon listener edit`](/cli/listener#cordon-listener-edit) over hand-editing listener entries in `cordon.toml`. The CLI validates listener names, ports, upstream addresses, TLS mode, and secret-source fields, and is meant as the safer way to produce this configuration. The TOML below is the reference format when you need to inspect, review, or automate outside the CLI.

## Listener structure

```toml theme={null}
[[listeners]]
name = "prod-db"
port = 15432
upstream = "db.prod.example.com:5432"
client_tls = "accept"

[listeners.auth]
type = "password"
username = "app_user"

[listeners.auth.secret]
source = "1password"
vault = "Engineering"
item = "Postgres Prod"
field = "password"
```

| Field           | Type    | Required | Description                                                                                   |
| --------------- | ------- | -------- | --------------------------------------------------------------------------------------------- |
| `name`          | string  | Yes      | Identifier for the listener. Route and listener names share one namespace and must be unique. |
| `port`          | integer | Yes      | Local port to listen on.                                                                      |
| `upstream`      | string  | Yes      | Upstream database host and port, such as `db.example.com:5432`.                               |
| `client_tls`    | string  | No       | Client-to-Cordon TLS mode: `accept` (default), `require`, or `disable`.                       |
| `auth.type`     | string  | Yes      | Auth type. Currently `password`.                                                              |
| `auth.username` | string  | Yes      | Username to authenticate as.                                                                  |
| `auth.secret`   | object  | Yes      | Secret source reference. See [Secret Sources](/configuration/secret-sources).                 |

Connect your application to `localhost:15432` instead of the upstream database. Cordon injects the password during the PostgreSQL authentication handshake.

Listener ports must be unique and cannot equal the HTTP proxy `listen` port.

## TLS behavior

`client_tls = "accept"` accepts PostgreSQL SSL requests when valid `tls.ca_cert_path` and `tls.ca_key_path` are configured, while still allowing plaintext clients. `client_tls = "require"` rejects plaintext startup packets and requires those CA paths. `client_tls = "disable"` declines SSL requests and keeps plaintext-only behavior. Omitted `client_tls` behaves as `accept`.

PostgreSQL client TLS uses the configured Cordon CA. Clients using `sslmode=verify-ca` or `sslmode=verify-full` must trust that CA. Cordon presents a loopback certificate for `localhost`, `127.0.0.1`, and `::1`; for `sslmode=verify-full`, connect to the local listener with one of those host identities.

Cordon always requires TLS on the Cordon-to-upstream PostgreSQL leg. It sends a PostgreSQL `SSLRequest` to the upstream server and completes TLS before sending startup or authentication data. If the upstream declines TLS or certificate verification fails, Cordon fails closed and does not send credentials.

## Upstream policy

PostgreSQL listener upstreams are configured trust decisions in v1, matching configured HTTP credential routes. Cordon resolves the upstream through the central resolver and connects to the selected `SocketAddr`, so DNS is pinned before the listener starts forwarding connections. Private, loopback, and link-local upstream policy will be revisited post-v1 in [#531](https://github.com/codezero-io/cordon/issues/531).
