The 'No SSL connection' error occurs when a PostgreSQL client expects an SSL/TLS encrypted connection but the server either doesn't support SSL, hasn't enabled it, or the connection parameters don't match. This commonly appears when sslmode is set to require or verify-ca but SSL isn't properly configured.
This error indicates a mismatch between what the client expects and what the PostgreSQL server provides regarding SSL/TLS encryption. The client may have been configured to require SSL connections (via the sslmode parameter), but the server is either not listening with SSL enabled, doesn't have SSL certificates configured, or the client and server have incompatible SSL settings. The server might also be configured to allow only non-SSL connections to the client's IP address in pg_hba.conf.
Connect to the PostgreSQL server (locally if possible) and check SSL status:
psql -U postgresInside psql, run:
SHOW ssl;If the output is off, SSL is disabled. Check the server's configuration:
sudo grep -n "^ssl = " /etc/postgresql/15/main/postgresql.confIf SSL is disabled, enable it by editing the config:
sudo nano /etc/postgresql/15/main/postgresql.confFind or add the line:
ssl = onAlso verify certificate files exist:
ls -la /etc/postgresql/15/main/server.crt
ls -la /etc/postgresql/15/main/server.keyIf certificates don't exist, you need to generate them (see Advanced Notes).
PostgreSQL uses the sslmode parameter to control SSL behavior. Adjust based on your needs:
# Development (no SSL verification - less secure)
postgresql://user:password@localhost:5432/dbname?sslmode=disable
# Production (SSL required, certificate verified against root CA)
postgresql://user:password@hostname:5432/dbname?sslmode=require
# SSL required with full verification (recommended for production)
postgresql://user:password@hostname:5432/dbname?sslmode=verify-full&sslrootcert=/path/to/root.crt
# SSL preferred but not required (fallback to non-SSL if SSL fails)
postgresql://user:password@hostname:5432/dbname?sslmode=preferFor Node.js/pg driver:
const client = new Client({
user: 'postgres',
password: 'password',
host: 'hostname',
port: 5432,
database: 'dbname',
ssl: {
rejectUnauthorized: false // For self-signed certs (dev only)
}
});For Java/JDBC:
jdbc:postgresql://hostname:5432/dbname?sslmode=require&ssl=trueThe pg_hba.conf file controls which connections require SSL. Edit it:
sudo nano /etc/postgresql/15/main/pg_hba.confReplace or add host lines with hostssl to require SSL:
# Before (allows non-SSL):
host all all 192.168.1.0/24 md5
# After (requires SSL):
hostssl all all 192.168.1.0/24 md5For AWS RDS PostgreSQL (uses IAM auth or username/password):
- RDS enforces SSL by default for most instance types
- Add sslmode=require to your connection string
After updating pg_hba.conf, reload the server:
sudo systemctl reload postgresqlVerify the changes:
sudo -u postgres psql -c "SHOW ssl;"When using sslmode=verify-full, the certificate's Common Name (CN) or Subject Alternative Name (SAN) must match the hostname in your connection string.
Check the server certificate:
sudo openssl x509 -in /etc/postgresql/15/main/server.crt -text -nooutLook for:
Subject: CN = hostname.example.comOr for SAN (Subject Alternative Name):
X509v3 Subject Alternative Name:
DNS:hostname.example.com, DNS:*.example.comIf the hostname doesn't match:
Option 1: Use hostname from certificate
Update your connection string to use the hostname from the certificate:
postgresql://user:[email protected]:5432/dbname?sslmode=verify-fullOption 2: Generate new certificate with correct hostname
Remove old certificate and regenerate:
sudo rm /etc/postgresql/15/main/server.crt /etc/postgresql/15/main/server.key
sudo -u postgres openssl req -new -x509 -days 365 -nodes \
-out /etc/postgresql/15/main/server.crt \
-keyout /etc/postgresql/15/main/server.key \
-subj "/CN=hostname.example.com"
sudo chmod 600 /etc/postgresql/15/main/server.key
sudo chown postgres:postgres /etc/postgresql/15/main/server.crt
sudo chown postgres:postgres /etc/postgresql/15/main/server.key
sudo systemctl restart postgresqlWhen using sslmode=verify-ca or verify-full, you need the root CA certificate that signed the server certificate.
For cloud providers:
AWS RDS:
# Download RDS CA certificate
wget https://truststore.amazonaws.com/global/certificates/rds-ca-2019-root.pem
# Use in connection string
postgresql://user:password@hostname:5432/dbname?sslmode=require&sslrootcert=/path/to/rds-ca-2019-root.pemAzure Database for PostgreSQL:
# Download Azure CA certificate
wget https://cacerts.digicert.com/DigiCertGlobalRootCA.crt
# Use in connection
postgresql://user:[email protected]:5432/dbname?sslmode=require&sslrootcert=/path/to/DigiCertGlobalRootCA.crtFor self-signed certificates:
# Extract the CA certificate from the server certificate
sudo openssl x509 -in /etc/postgresql/15/main/server.crt -out ca.crt
# Copy to client machine at ~/.postgresql/root.crt
mkdir -p ~/.postgresql
cp ca.crt ~/.postgresql/root.crt
chmod 600 ~/.postgresql/root.crtThen use in connection:
postgresql://user:password@hostname:5432/dbname?sslmode=verify-ca&sslrootcert=/home/user/.postgresql/root.crtVerify SSL works with the psql command-line client:
# Test with SSL required (will fail if server doesn't support SSL)
psql -h hostname -U postgres -d postgres --set=sslmode=require
# Test with full verification (requires matching hostname)
psql -h hostname -U postgres -d postgres \
--set=sslmode=verify-full \
--set=sslrootcert=/path/to/root.crt
# See verbose SSL negotiation details
psql -h hostname -U postgres -d postgres \
--set=sslmode=require \
-v sslmode=require -dIf this succeeds, your server SSL is properly configured. If it fails, check PostgreSQL server logs:
sudo journalctl -u postgresql -n 50 --no-pager
# or
sudo tail -50 /var/log/postgresql/postgresql-15-main.logSSL Modes Explained: PostgreSQL's sslmode parameter has six values:
- disable: No SSL (plaintext)
- allow: Non-SSL first, fallback to SSL if required
- prefer: SSL first, fallback to non-SSL (default in some versions)
- require: SSL mandatory, no hostname verification
- verify-ca: SSL + verify server certificate chain to root CA
- verify-full: SSL + verify certificate and hostname match
For production, use verify-full if possible.
PostgreSQL 16+ Default Behavior: Starting with PostgreSQL 16, the server defaults to preferring SSL connections. If you're upgrading from an older version and clients fail, they likely need SSL certificates or sslmode configuration.
Certificate Generation: If your server doesn't have certificates, generate them:
sudo -u postgres openssl req -new -x509 -days 3650 -nodes \
-out /etc/postgresql/15/main/server.crt \
-keyout /etc/postgresql/15/main/server.key \
-subj "/CN=localhost"
sudo chmod 600 /etc/postgresql/15/main/server.key
sudo systemctl restart postgresqlDebugging SSL Issues: Enable verbose logging in postgresql.conf:
log_connections = on
log_disconnections = on
log_statement = 'all'Then monitor logs for SSL-related errors.
Connection Poolers: If using PgBouncer or pgpool-II, ensure they also have SSL configured on both the client-facing side and backend connection to PostgreSQL.
Kubernetes/Docker: In containerized environments, ensure:
1. PostgreSQL pod/service has SSL certificates mounted
2. Client pods can access the CA certificate
3. DNS hostname resolves correctly for certificate verification
insufficient columns in unique constraint for partition key
How to fix "insufficient columns in unique constraint for partition key" in PostgreSQL
ERROR 42501: must be owner of table
How to fix "must be owner of table" in PostgreSQL
trigger cannot change partition destination
How to fix "Trigger cannot change partition destination" in PostgreSQL
SSL error: certificate does not match host name
SSL error: certificate does not match host name in PostgreSQL
pg_dump: could not obtain lock on table
pg_dump could not obtain lock on table