PostgreSQL SSL/TLS Configuration Guide
This guide covers SSL/TLS encryption for PostgreSQL wire protocol connections in HeliosDB-Lite.
Table of Contents
- Overview
- Certificate Management
- Server Configuration
- Client SSL Modes
- Client Connection
- Testing
- Troubleshooting
- Security Best Practices
Overview
HeliosDB-Lite supports SSL/TLS encryption for PostgreSQL protocol connections, providing secure communication between clients and the database server. The implementation follows the PostgreSQL wire protocol SSL/TLS negotiation standard.
Features
- Standard Protocol: Compatible with PostgreSQL SSL negotiation and every
sslmode - Flexible Certificates: Self-signed and CA-signed certificates (PEM)
- Client-Enforced TLS: The server offers TLS; clients that require it use
sslmode=requireor stricter
Protocol Flow
- Client sends SSLRequest message (code: 80877103)
- Server responds with ‘S’ (SSL supported) or ‘N’ (not supported)
- If ‘S’, the TLS handshake begins
- After TLS handshake, normal startup message follows over encrypted connection
Certificate Management
Generating Self-Signed Certificates
For testing and development, use self-signed certificates:
# Create certs directorymkdir -p certs
# Generate self-signed certificate and private keyopenssl req -x509 -newkey rsa:2048 -nodes \ -keyout certs/server.key \ -out certs/server.crt \ -days 365 \ -subj "/CN=localhost"
# Set appropriate permissionschmod 600 certs/server.keychmod 644 certs/server.crtProduction Certificates
For production environments, use CA-signed certificates:
- Generate Certificate Signing Request (CSR):
openssl req -new -newkey rsa:2048 -nodes \ -keyout certs/server.key \ -out certs/server.csr \ -subj "/CN=your-domain.com"-
Submit CSR to Certificate Authority (e.g., Let’s Encrypt, DigiCert)
-
Install Certificate:
# Place certificate and key in certs directorycp server.crt certs/cp server.key certs/chmod 600 certs/server.keychmod 644 certs/server.crtCertificate Verification
Verify certificate files before using:
openssl x509 -in certs/server.crt -noout -subject -datesopenssl rsa -in certs/server.key -check -nooutServer Configuration
Start the server with a certificate and its private key (PEM). Both flags are required together:
export HELIOSDB_JWT_SECRET="$(openssl rand -hex 32)"heliosdb-lite start --data-dir /var/lib/heliosdb \ --tls-cert certs/server.crt --tls-key certs/server.keyProduction example with password authentication on all interfaces:
export HELIOSDB_JWT_SECRET="$(openssl rand -hex 32)"heliosdb-lite start --data-dir /var/lib/heliosdb --listen 0.0.0.0 \ --auth scram-sha-256 --password "$HELIOSDB_ADMIN_PASSWORD" \ --tls-cert /etc/heliosdb/certs/server.crt --tls-key /etc/heliosdb/certs/server.keyWith TLS configured, the server accepts TLS from every client that requests it and also
accepts clients that do not. Enforce TLS in the clients with sslmode=require or
stricter. WAL replication traffic between nodes is encrypted automatically when
--tls-cert is set.
Client SSL Modes
sslmode | Behaviour | Use Case |
|---|---|---|
disable | Never use TLS | Local development only |
allow | Plaintext first, TLS if the server insists | Transitional |
prefer | TLS when available (libpq default) | Migration |
require | Fail if TLS is not available | Production |
verify-ca | require + verify the server certificate chain | High security |
verify-full | verify-ca + verify the host name | Maximum security |
Client-certificate authentication (the server verifying client certificates) is planned.
Client Connection
Using psql
# Require SSLpsql "sslmode=require host=127.0.0.1 port=5432 user=postgres dbname=heliosdb"
# Verify the server certificate against your CApsql "sslmode=verify-ca sslrootcert=/path/to/ca.crt host=127.0.0.1 port=5432 user=postgres"
# Full connection stringpsql "postgresql://postgres@127.0.0.1:5432/heliosdb?sslmode=require"Using PostgreSQL Drivers
Rust (tokio-postgres with postgres-native-tls)
use native_tls::TlsConnector;use postgres_native_tls::MakeTlsConnector;use tokio_postgres::config::{Config, SslMode};
let connector = MakeTlsConnector::new(TlsConnector::builder().build()?);
let mut config = Config::new();config.host("127.0.0.1");config.port(5432);config.user("postgres");config.dbname("heliosdb");config.ssl_mode(SslMode::Require);
let (client, connection) = config.connect(connector).await?;Python (psycopg2)
import psycopg2
conn = psycopg2.connect( host="127.0.0.1", port=5432, user="postgres", dbname="heliosdb", sslmode="require")Node.js (pg)
const { Client } = require('pg');
const client = new Client({ host: '127.0.0.1', port: 5432, user: 'postgres', database: 'heliosdb', ssl: { rejectUnauthorized: false // For self-signed certs only }});
await client.connect();Testing
-
Start an SSL-enabled server (see Server Configuration).
-
Test the SSL connection:
psql "sslmode=require host=127.0.0.1 port=5432 user=postgres"
# Inside psql\conninfo# SSL connection (protocol: TLSv1.3, cipher: ...)- Inspect the certificate the server presents:
openssl s_client -starttls postgres -connect 127.0.0.1:5432 -showcerts </dev/nullTroubleshooting
Common Issues
”Both —tls-cert and —tls-key must be specified together for TLS.”
Pass both flags, or neither.
Certificate Not Found
Check the paths passed to --tls-cert and --tls-key, or regenerate the files:
mkdir -p certsopenssl req -x509 -newkey rsa:2048 -nodes \ -keyout certs/server.key \ -out certs/server.crt \ -days 365 \ -subj "/CN=localhost"Permission Denied
The server user cannot read the key. Set correct file permissions and ownership:
chmod 600 certs/server.keychmod 644 certs/server.crtTLS Handshake Failed
- Verify certificate validity:
openssl x509 -in certs/server.crt -text -noout- Check certificate dates:
openssl x509 -in certs/server.crt -noout -dates- Check the client trusts the issuing CA (
sslrootcertforverify-ca/verify-full).
Debugging
export HELIOSDB_JWT_SECRET="$(openssl rand -hex 32)"RUST_LOG=debug heliosdb-lite start --data-dir ./mydb \ --tls-cert certs/server.crt --tls-key certs/server.keySecurity Best Practices
Production Deployment
- Use CA-signed certificates (not self-signed)
- Require TLS in every client (
sslmode=requireor stricter) - Restrict file permissions:
Terminal window chmod 600 certs/server.keychmod 644 certs/server.crt - Rotate certificates regularly (before expiration); restart the server to load new files
- Use strong authentication (
--auth scram-sha-256, nottrust)
Certificate Management
- Store keys securely (encrypted storage, key management systems)
- Limit key access (Unix permissions, access control lists)
- Monitor certificate expiration
- Use separate certificates for each environment
Network Security
- Use firewall rules to restrict access
- Use VPN or private networks for additional security
- Monitor connection attempts in the server log
Compliance
For regulated environments (HIPAA, PCI-DSS, etc.):
- Require TLS in every client and verify the server certificate (
verify-full) - Use SCRAM-SHA-256 with per-application roles
- Encrypt data at rest with TDE (see the Encryption Quick Start)
- Maintain security documentation