Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.teesql.com/llms.txt

Use this file to discover all available pages before exploring further.

TeeSQL accepts TLS connections on port 5433 only. The sidecar terminates a mutual Remote Attestation TLS (RA-TLS) handshake — the server presents a self-signed X.509 certificate with a TDX attestation quote in a custom extension, and (in production) requires the client to present an equivalent attested certificate. Plaintext Postgres on port 5432 is bound to localhost inside the CVM and is unreachable from outside.

Prerequisites

  • A TeeSQL cluster host and database
  • For mutual RA-TLS (production): your application running inside an Intel TDX CVM with a dstack guest agent at /var/run/dstack.sock
  • For local development: the dstack simulator

Required SSL mode

The mode you set depends on which connection path you use. There is no single “TeeSQL sslmode” — the answer is determined by where the TLS handshake terminates.
PathsslmodeWhy
RA-TLS client library (psycopg-ra-tls, prisma-ra-tls, sqlx-ra-tls)disableThe library runs a localhost forwarder that owns TLS. The driver speaks plain Postgres to 127.0.0.1:<port>.
Raw psql/libpq direct to a CVMverify-fullThe driver itself terminates TLS with the sidecar and must verify the server’s RA-TLS chain.
Behind a dstack gateway with a public ACME certrequireThe gateway presents a normal CA-signed cert; the gateway re-establishes RA-TLS internally.
Local dev against the dstack simulatorrequireThe simulator’s RA-TLS cert is self-signed and not chainable to a public CA, so verify-full fails.
Setting sslmode=require or sslmode=verify-full on the forwarder DSN handed to a TeeSQL RA-TLS client library wires TLS twice and breaks the connection. The driver-side DSN must be sslmode=disable; the forwarder is the TLS endpoint.

Configure SSL in your client

Direct mutual RA-TLS to a CVM:
psql "host=your-cluster.teesql.com port=5433 user=postgres sslmode=verify-full \
  sslrootcert=ra-tls-ca.pem \
  sslcert=client-cert.pem \
  sslkey=client-key.pem \
  dbname=postgres"
Local dev (simulator, server-only TLS):
psql "host=localhost port=5433 user=postgres sslmode=require dbname=postgres"
Behind a dstack gateway (sslmode=require is enough — public ACME cert):
psql "postgres://postgres:your-32-byte-hex-secret@db.your-domain.com:5433/yourdb?sslmode=require"

Where the CA certificate comes from

The trust anchor for a TeeSQL connection is not a public certificate authority. The server’s RA-TLS certificate is issued by the dstack Key Management Service (KMS) bound to the cluster’s attested identity. ra-tls-parse::build_root_store treats the last certificate in the presented chain as the trust anchor — that is the dstack KMS root. Two ways to obtain the root for raw libpq/psql use:
  1. From the cluster operator. During cluster provisioning, request the KMS root cert PEM and use it as sslrootcert.
  2. From the server’s own chain. The chain is presented during the TLS handshake; tooling that uses the RA-TLS client libraries does not need the root on disk because verification happens against the embedded TDX quote, not a CA chain.
For client certificates:
let client = DstackClient::new()?;
let tls = client.get_tls_key(TlsKeyRequest {
    subject: "my-app".into(),
    alt_names: vec![],
    usage_ra_tls: true,
    usage_server_auth: false,
    usage_client_auth: true,
}).await?;
// tls.key and tls.certificate_chain are PEM
from dstack_sdk import DstackClient
client = DstackClient()
tls = client.get_tls_key(subject="my-app", usage_ra_tls=True, usage_client_auth=True)
The cert is short-lived and tied to your CVM’s TDX quote.

How RA-TLS differs from standard TLS

In standard TLS the server’s certificate is signed by a CA you already trust — the chain is the proof. In RA-TLS the server’s certificate is self-signed, but a TDX attestation is embedded in a custom X.509 extension (Phala RA-TLS OID 1.3.6.1.4.1.62397.1.8 for the current SCALE-encoded form, with .1.1 retained as a legacy raw-quote fallback). The attestation proves:
  • The server is running inside a genuine Intel TDX Trusted Domain
  • The TD’s measurements (MRTD, RTMR0–3) match the expected software stack
  • The platform’s Trusted Computing Base (firmware + microcode) is up to date
The TLS public key is bound to the quote via the REPORTDATA field, which prevents a man-in-the-middle from substituting a different certificate without invalidating the quote. A standard TLS client that does not understand the OID will reject the cert as untrusted, which is why direct libpq use needs sslrootcert set to the dstack KMS root and why the RA-TLS client libraries verify the quote out-of-band against Intel Trust Authority or a local DCAP verifier.
RA-TLS replaces “trust this CA” with “verify this hardware attestation”. The deeper protocol — quote layout, RTMR semantics, MRTD pinning — lives in Remote attestation.

Verify

Confirm the cert presented on :5433 is an RA-TLS cert with a TDX attestation extension:
openssl s_client -connect your-cluster.teesql.com:5433 -starttls postgres -showcerts </dev/null 2>/dev/null \
  | openssl x509 -text -noout \
  | grep -A1 "1.3.6.1.4.1.62397"
You should see at least one Phala RA-TLS OID (1.3.6.1.4.1.62397.1.8 for the current attestation, or .1.1 for a legacy raw quote) listed under X.509v3 extensions. If neither is present, you are not talking to a TeeSQL sidecar.
Last modified on May 1, 2026