Skip to content

TLS Configuration

TLS on the vdb-mysql listener is optional. When enabled, it secures the connection between your application and VirtualDB. When disabled, connections are accepted in plaintext — suitable for local development or environments where the network is already secured.

Enabling TLS

Set both variables before starting vdb-mysql:

sh
export VDB_TLS_CERT_FILE=/etc/vdb/server.crt
export VDB_TLS_KEY_FILE=/etc/vdb/server.key
./vdb-mysql

Both must be provided together. Setting one without the other causes vdb-mysql to exit at startup with an error.

What changes when TLS is enabled

TLS enabledTLS disabled
Auth plugin advertisedcaching_sha2_passwordmysql_clear_password
Minimum TLS version1.2N/A
Client opt-in requiredNoYes — see below

Why every connection goes through full authentication

When TLS is enabled, VirtualDB advertises caching_sha2_password but always performs the full authentication exchange — the fast-auth shortcut is never used. This is intentional: VirtualDB holds no local password store. To verify a client's credentials, it opens a short-lived probe connection to your source MySQL server, which requires the plaintext password. The full-auth path is the only way to obtain that. TLS on the listener ensures the password travels encrypted between the client and VirtualDB.

Scope of TLS

VDB_TLS_CERT_FILE and VDB_TLS_KEY_FILE apply only to the listener — the connection between your application and vdb-mysql. They have no effect on the connections vdb-mysql opens to your source database. TLS on that leg is your source server's concern and is configured via the tls= parameter in VDB_SOURCE_DSN.

Certificate requirements

  • Both the certificate and key must be PEM-encoded files.
  • The certificate file may include the full chain (leaf certificate followed by intermediates).
  • The private key must match the leaf certificate's public key.
  • The minimum TLS version accepted from clients is 1.2.

Container images and CA certificates

If you're running vdb-mysql in a minimal container image (such as scratch or a distroless image) without ca-certificates installed, the system certificate pool will be empty. vdb-mysql continues to run — it does not fail. Install ca-certificates in your image if you need the system pool populated.

Note: client certificate authentication is not supported in this release.

Generating a self-signed certificate (development)

For local development, a self-signed certificate is sufficient. Use --ssl-mode=REQUIRED when connecting to require TLS without verifying the server certificate.

sh
openssl req -x509 -newkey rsa:4096 -nodes \
  -keyout server.key \
  -out server.crt \
  -days 365 \
  -subj "/CN=vdb-mysql" \
  -addext "subjectAltName=IP:127.0.0.1,DNS:localhost"

Start vdb-mysql with TLS:

sh
VDB_TLS_CERT_FILE=./server.crt \
VDB_TLS_KEY_FILE=./server.key \
./vdb-mysql

Connect with the MySQL CLI:

sh
mysql -h 127.0.0.1 -P 3306 -u myuser -p myapp --ssl-mode=REQUIRED

Using TLS with Docker

Mount your certificate and key into the container:

sh
docker run --rm \
  -e VDB_SOURCE_DSN="vdb_user:secret@tcp(db.internal:3306)/myapp" \
  -e VDB_AUTH_SOURCE_ADDR="db.internal:3306" \
  -e VDB_DB_NAME="myapp" \
  -e VDB_TLS_CERT_FILE=/run/secrets/vdb-cert \
  -e VDB_TLS_KEY_FILE=/run/secrets/vdb-key \
  -v /etc/vdb/server.crt:/run/secrets/vdb-cert:ro \
  -v /etc/vdb/server.key:/run/secrets/vdb-key:ro \
  -p 3306:3306 \
  ghcr.io/virtual-db/mysql:latest

With Docker Compose secrets:

yaml
services:
  vdb:
    image: ghcr.io/virtual-db/mysql:latest
    environment:
      VDB_SOURCE_DSN: "vdb_user:secret@tcp(db.internal:3306)/myapp"
      VDB_AUTH_SOURCE_ADDR: "db.internal:3306"
      VDB_DB_NAME: myapp
      VDB_TLS_CERT_FILE: /run/secrets/vdb_tls_cert
      VDB_TLS_KEY_FILE: /run/secrets/vdb_tls_key
    secrets:
      - vdb_tls_cert
      - vdb_tls_key
    ports:
      - "3306:3306"

secrets:
  vdb_tls_cert:
    file: ./certs/server.crt
  vdb_tls_key:
    file: ./certs/server.key

Connecting without TLS

Without TLS, vdb-mysql uses mysql_clear_password — the password is sent over the wire in plaintext. Most MySQL clients refuse this by default as a safety measure.

You must explicitly enable cleartext auth on every client that connects. Both disabling TLS and enabling the cleartext plugin are required.

MySQL CLI

sh
mysql -h 127.0.0.1 -P 3306 -u myuser -p myapp \
  --ssl-mode=DISABLED \
  --enable-cleartext-plugin

Go (go-sql-driver/mysql)

Append both parameters to your DSN:

user:password@tcp(127.0.0.1:3306)/myapp?tls=false&allowCleartextPasswords=true

Other clients

Look for a "cleartext plugin" or "allow clear text passwords" option in your client's documentation. Without it, the client will reject vdb-mysql's auth advertisement and the connection will fail at the handshake stage.

Released under the Elastic License 2.0.