KDB knowledge

TLS (https and sslmode=require)

Encrypt both ports with one certificate - https:// for the HTTP API and the console, sslmode=require for PostgreSQL clients.

With TLS on, everything between a client and KDB is encrypted: passwords, tokens and data. One certificate serves both ports.

PortClients connect with
HTTP (9900)https://host:9900 (browsers, curl, HTTP libraries)
PostgreSQL (8832)sslmode=require (or verify-full), also sslnegotiation=direct of PostgreSQL 17

Turn it on

Syntax:

kdb serve --tls-cert cert.pem --tls-key key.pem [--tls-required on|off]
kdb serve --tls-cert auto
kdb.conf:  "tls_cert": "/data/cert.pem", "tls_key": "/data/key.pem"
env:       KDB_TLS_CERT=/data/cert.pem  KDB_TLS_KEY=/data/key.pem  KDB_TLS_REQUIRED=on
SettingMeaningDefault
--tls-cert FILEthe certificate in PEM: the server's first, then the chainoff
--tls-key FILEits private key in PEM (without a passphrase)-
--tls-cert autoKDB makes a self-signed certificate once, in <data folder>/_tls/, and keeps using it-
--tls-required on|offon: plain connections are refused, except from this computer (127.x)on
kdb serve --data-dir kdb-data --bind 0.0.0.0 --token "long-random-secret-1" --tls-cert auto

A self-signed certificate (auto)

--tls-cert auto makes kdb-cert.pem and kdb-key.pem in <data folder>/_tls/ the first time (EC P-256, valid 10 years, for localhost, 127.0.0.1 and the --bind address), and uses the same pair after every restart.

What changes for clients

ClientBeforeWith TLS
browser, consolehttp://host:9900https://host:9900
curlcurl http://...curl https://... (-k or --cacert for self-signed)
psql, DBeaver, driverssslmode=disablesslmode=require, or verify-full with the certificate
plain http:// from another computeranswered400: This KDB server speaks HTTPS only: use https:// ...
plain PostgreSQL from another computeransweredSQLSTATE 28000: this server requires TLS: connect with sslmode=require

Docker

Inside a container KDB must listen on all addresses (--bind 0.0.0.0), so the published ports decide who can reach it:

docker runReachable from
-p 9900:9900 -p 8832:8832every computer that can reach this one
-p 127.0.0.1:9900:9900 -p 127.0.0.1:8832:8832this computer only

Through Docker's port mapping, clients reach KDB from Docker's own address, not from 127.x: with TLS on, they must use TLS. The image's health check runs inside the container on 127.0.0.1, so it keeps working.