Secure q connections with SSL/TLS¶
This page explains how to set up, configure, and verify TLS-encrypted connections between q server and client processes for local development.
TLS encrypts a q connection end to end, so neither the credentials nor the data can be read in transit. q implements it through the OpenSSL libraries, which you install and configure separately from q itself. For connections without encryption, see IPC basics.
Prerequisites¶
Before you configure TLS, install the OpenSSL libraries and make sure q can find them. For background, see the OpenSSL documentation.
Install OpenSSL¶
Install the latest OpenSSL libraries for your operating system, then add the library path to the environment variable your system uses:
- Linux:
LD_LIBRARY_PATH - macOS:
DYLD_LIBRARY_PATH - Windows:
PATH
Verify the OpenSSL version¶
q searches for compatible OpenSSL shared libraries at startup. It has supported OpenSSL 1.1 since v4.0 2020.03.17.
Since v4.1t 2022.03.25, q tries versioned shared libraries in this order:
libssl.so, libssl.so.3, libssl.so.1.1, libssl.so.1.0, libssl.so.10, libssl.so.1.0.2, libssl.so.1.0.1, libssl.so.1.0.0
libssl.3.dylib, libssl.1.1.dylib
q loads both libssl and libcrypto, in this order of preference:
| Architecture | libssl | libcrypto |
|---|---|---|
| w64 | libssl-3-x64.dlllibssl-1_1-x64.dll |
libcrypto-3-x64.dlllibcrypto-1_1-x64.dll |
| w32 | libssl-3.dlllibssl-1_1.dll |
libcrypto-3.dlllibcrypto-1_1.dll |
Windows also needs the Visual C++ redistributable
KX tested the Windows build against the precompiled libraries from Win32/Win64 OpenSSL. Install the Microsoft Visual C++ redistributable package from Microsoft's download page as well.
Before v4.1t 2022.03.25, q loaded these unversioned files:
libssl.so
libssl.dylib
q loads both libssl and libcrypto, in this order of preference:
| Architecture | libssl | libcrypto |
|---|---|---|
| w64 | libssl-1_1-x64.dll |
libcrypto-1_1-x64.dll |
| w32 | libssl-1_1.dll |
libcrypto-1_1.dll |
Basic TLS setup¶
This section walks through creating self-signed certificates and configuring a server and a client for a TLS connection. It suits a local development environment; in production, use certificates from a certificate authority your organization trusts.
Step 1: Generate certificates¶
TLS requires the server to hold a certificate and a private key. For local testing, generate your own with the openssl command-line tool.
The script below creates a local certificate authority (CA) and uses it to sign a certificate for a server and one for a client:
# Create a dedicated directory for the certificates
mkdir $HOME/certs && cd $HOME/certs
# --- 1. Create the certificate authority (CA) ---
# A private key for the CA. Keep this secret.
openssl genrsa -out ca-private-key.pem 2048
# A self-signed root certificate for the CA. This is the trust anchor.
openssl req -x509 -new -nodes -key ca-private-key.pem -sha256 -days 365 \
-out ca-cert.pem -subj "/C=US/ST=CA/L=Somewhere/O=Someone/CN=MyTestCA"
# --- 2. Create the server certificate ---
openssl genrsa -out server-private-key.pem 2048
# A certificate signing request (CSR) for the server
openssl req -new -sha256 -key server-private-key.pem \
-subj "/C=US/ST=CA/L=Somewhere/O=Someone/CN=MyTestServer" -out server.csr
# Sign the server's CSR with the CA, producing the certificate
openssl x509 -req -in server.csr -CA ca-cert.pem -CAkey ca-private-key.pem \
-CAcreateserial -out server-cert.pem -days 365 -sha256
# --- 3. Create the client certificate ---
openssl genrsa -out client-private-key.pem 2048
openssl req -new -sha256 -key client-private-key.pem \
-subj "/C=US/ST=CA/L=Somewhere/O=Someone/CN=MyTestClient" -out client.csr
openssl x509 -req -in client.csr -CA ca-cert.pem -CAkey ca-private-key.pem \
-CAcreateserial -out client-cert.pem -days 365 -sha256
To inspect what you generated:
openssl req -in server.csr -noout -text # the server's CSR
openssl x509 -in server-cert.pem -noout -text # the server's X.509 certificate
openssl req -in client.csr -noout -text # the client's CSR
openssl x509 -in client-cert.pem -noout -text # the client's X.509 certificate
To verify both certificates against the CA:
openssl verify -CAfile ca-cert.pem server-cert.pem
openssl verify -CAfile ca-cert.pem client-cert.pem
A shorter route to local certificates
For local development, mkcert produces locally trusted certificates without the openssl invocations above.
Keep private keys out of reach of q
Store certificates and private keys outside any directory reachable from within q. A remote user who can read your q home directory can read your server's private key.
Step 2: Configure and start the server¶
Point the environment variables at the server's certificate, its private key, and the CA certificate that verifies connecting clients:
export SSL_CERT_FILE=$HOME/certs/server-cert.pem # the server's certificate
export SSL_KEY_FILE=$HOME/certs/server-private-key.pem # the server's private key
export SSL_CA_CERT_FILE=$HOME/certs/ca-cert.pem # verifies client certificates
Start q with the -E command-line option to enable TLS server mode. For the port itself, see how to configure listening ports.
q -p 5001 -E 1
Step 3: Configure and connect the client¶
In a new terminal, set the client's environment variables. For mutual authentication the client needs its own certificate and key, and it needs the CA certificate to verify the server:
export SSL_CERT_FILE=$HOME/certs/client-cert.pem # the client's certificate
export SSL_KEY_FILE=$HOME/certs/client-private-key.pem # the client's private key
export SSL_CA_CERT_FILE=$HOME/certs/ca-cert.pem # verifies the server's certificate
Start a client q process and open a secure connection with hopen and the tcps:// scheme. The general form is:
h: hopen `:tcps://hostname:port[:username:password]
So, against the server from step 2:
q)h: hopen `:tcps://localhost:5001 / open a secure handle
q)h "2+2" / send a command over the encrypted connection
4
A client can also make secure HTTP (HTTPS) requests through the REST server module, and secure WebSocket (WSS) connections — see using WebSockets with q.
Verify the connection¶
Check the configuration¶
To see the TLS settings a q process loaded, use -26!. It returns a dictionary:
q)(-26!)[]
SSLEAY_VERSION | OpenSSL 3.0.13 30 Jan 2024
SSL_CERT_FILE | /home/user/certs/server-cert.pem
SSL_CA_CERT_FILE | /home/user/certs/ca-cert.pem
SSL_CA_CERT_PATH | /usr/lib/ssl
SSL_KEY_FILE | /home/user/certs/server-private-ke..
SSL_CIPHER_LIST | ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RS..
SSL_VERIFY_CLIENT| NO
SSL_VERIFY_SERVER| YES
Inspect the connection status¶
To get protocol details for an active connection handle, run .z.e on the remote process. It returns a dictionary describing the connection, including whether the peer's certificate verified:
q)h".z.e"
CIPHER | TLS_AES_256_GCM_SHA384
PROTOCOL| TLSv1.3
Troubleshoot common errors¶
When a connection fails, check the q console for messages from the OpenSSL library. Two common cases:
-
No shared cipher. The client and server cannot agree on a cipher suite. Compare the
SSL_CIPHER_LISTsettings on both processes. q reports a'connerror.140735201689680:error:1408A0C1:SSL routines:ssl3_get_client_hello:no shared cipher:s3_srvr.c:1417: 'conn -
CA certificate not found. The path in
SSL_CA_CERT_FILEorSSL_CA_CERT_PATHis wrong, or the file is unreadable. q reports a'connerror....error:02001002:system library:fopen:No such file or directory... ...error:2006D080:BIO routines:BIO_new_file:no such file... ...error:0B084002:x509 certificate routines:X509_load_cert_crl_file:system lib... 'conn. OS reports: Protocol not available
Configuration reference: environment variables¶
Set these environment variables before you start the process; q reads them at startup.
A KX_ prefix takes precedence
Since v3.6, q prefers a KX_-prefixed variable over the plain name, so KX_SSL_CERT_FILE overrides SSL_CERT_FILE. The prefix avoids collisions with other applications that read the same variable names.
Where a variable holds no absolute path, q resolves it against the default directory that openssl version -d reports:
$ openssl version -d
OPENSSLDIR: "/opt/local/etc/openssl"
SSL_CERT_FILE¶
The path to a file holding the local process's certificate in PEM format. Order the file starting with the subject's own certificate, then any intermediate CA certificates, ending with the root.
Default: <OPENSSLDIR>/server-crt.pem
SSL_KEY_FILE¶
The path to the private key that belongs to the certificate in SSL_CERT_FILE, also in PEM format.
Default: <OPENSSLDIR>/server-key.pem
SSL_CA_CERT_FILE¶
The path to a file holding one or more trusted certificate authority (CA) certificates, which q uses to verify the certificate a peer presents. The file must be PEM format, and can hold several concatenated certificates, each delimited as:
-----BEGIN CERTIFICATE-----
... (CA certificate in base64 encoding) ...
-----END CERTIFICATE-----
Text before, between, and after the certificates is permitted, which is useful for describing them.
Default: <OPENSSLDIR>/cacert.pem
Verifying public websites needs a public CA bundle
To verify certificates from public websites, such as when .Q.hg fetches over HTTPS, import a CA bundle from a reputable source such as the curl CA extract page:
curl https://curl.se/ca/cacert.pem > $HOME/certs/cabundle.pem
export SSL_CA_CERT_FILE=$HOME/certs/cabundle.pem
You can append your own self-signed CA certificates to that file.
SSL_CA_CERT_PATH¶
The path to a directory holding individual trusted CA certificate files in PEM format.
Default: <OPENSSLDIR>
SSL_CIPHER_LIST¶
The cipher suites the q process offers during the TLS handshake. Override the default to comply with a specific security policy.
Default: the intermediate compatibility list recommended by Mozilla Server Side TLS:
ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-
AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-
SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-
AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:
ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:
ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:
DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-
RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-
RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:
AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS
SSL_VERIFY_CLIENT¶
How a q server validates a client's certificate.
NO(default): the server doesn't request a certificate from the client.YES: the server requests a certificate, and disconnects if it is missing or not valid.REQUESTONLY(since v4.1t 2024.02.07): the server requests a certificate, and continues even if it is missing or not valid.IFPRESENT(since v4.1t 2024.02.07): the server requests a certificate, disconnects if the certificate presented is not valid, and continues if none is presented.
SSL_VERIFY_SERVER¶
How a q client validates the server's certificate.
YES(default): the client verifies the server's certificate against the CAs inSSL_CA_CERT_FILEorSSL_CA_CERT_PATH. An expired certificate fails.NO: no certificate verification at all. This is insecure — use it only on a trusted, private network.HOSTIP(since v4.1 2025.11.25): everythingYESdoes, and additionally checks that the certificate's subject alternative name (SAN) or common name (CN) matches the host you named inhopen. Requires OpenSSL 1.0.2 or later.
With HOSTIP, the check depends on how you addressed the server:
- For a hostname, q checks the certificate's SAN or CN against it, as
X509_check_hostdoes. -
For an IP address, q checks the certificate against the IPv4 address, as
X509_check_ipdoes. Connecting to127.0.0.1, for example, requires this in the certificate:X509v3 extensions: X509v3 Subject Alternative Name: IP Address:127.0.0.1
SSL_MINPROTOCOL¶
The minimum TLS protocol version the process accepts. Accepted values are SSLv3, TLSv1, TLSv1.1, TLSv1.2, TLSv1.3, and None for no limit. Requires OpenSSL 1.1.0 or later. Since q 5.0.20260401.
Default: TLSv1
SSL_MAXPROTOCOL¶
The maximum TLS protocol version the process accepts. Accepted values are SSLv3, TLSv1, TLSv1.1, TLSv1.2, TLSv1.3, and None for no limit. Requires OpenSSL 1.1.0 or later. Since q 5.0.20260401.
SSL_CIPHERSUITES¶
The cipher suites available for TLSv1.3, as a colon-separated list in order of preference. q combines this list with any TLSv1.2 ciphers from SSL_CIPHER_LIST. To list the cipher suites your system offers, run openssl ciphers -s -tls1_3. Requires OpenSSL 1.1.0 or later. Since q 5.0.20260401.
Performance and limitations¶
Performance¶
TLS adds overhead to both connection setup and data transfer:
- Connection setup: a TLS
hopenon localhost can be 40 to 50 times slower than a plain TCP connection, because of the certificate exchange and cryptographic handshake. - Data transfer: once connected, transfer costs roughly 1.5 times a plain connection, assuming your OpenSSL library has AES-NI hardware acceleration available.
Because of that overhead, TLS suits long-lived, latency-insensitive, low-throughput connections best.
Threading support¶
TLS support across multi-threaded q has changed over time.
Before v4.1t 2023.11.10, TLS was unavailable in secondary threads, which ruled out:
- Multi-threaded input mode, that is
-swith a negative number hopenwith a timeout, added in v3.5- Use within
peach
Since v4.1t 2023.11.10, TLS works on any thread that supports messaging at all, including:
- Incoming connections in multi-threaded input mode
- One-shot synchronous requests within
peachor on a socket thread - HTTPS client requests, such as through the Kurl module, within
peachor on a socket thread
Next steps¶
- IPC basics — the unencrypted connections that TLS wraps.
- Configure listening ports — the port options that combine with
-E. - Secure and monitor IPC connections — authentication and authorization on top of an encrypted transport.
- Use WebSockets with q — secure WebSocket (WSS) connections over the same TLS configuration.