This SSL error occurs when the hostname in your connection string doesn't match the hostname in the PostgreSQL server's SSL certificate. The mismatch happens when using verify-full SSL mode, which validates both the certificate chain and the hostname.
When PostgreSQL's SSL mode is set to `verify-full`, the client not only verifies that the certificate is signed by a trusted Certificate Authority, but also validates that the certificate's Common Name (CN) or Subject Alternative Name (SAN) matches the hostname you're connecting to. If there's a mismatch—for example, connecting to an IP address when the certificate only has a hostname, or using an alias when the certificate specifies the FQDN—this error is raised as a security measure to prevent man-in-the-middle attacks.
First, find out what hostname is actually in the PostgreSQL server's SSL certificate. If you have access to the server, check the certificate file:
# Usually located at $PGDATA/server.crt
openssl x509 -in /var/lib/postgresql/15/main/server.crt -text -noout | grep -A 1 "Subject Alternative Name"Or extract the Common Name:
openssl x509 -in /var/lib/postgresql/15/main/server.crt -noout -subjectOutput will show something like:
- CN=my-database.example.com
- DNS:my-database.example.com, DNS:*.example.com
Note the exact hostname(s) listed—this is what you must connect with.
Change your connection string to use the exact hostname from the certificate.
Incorrect (using IP or different hostname):
psql -h 192.168.1.50 -U postgres -d mydb -W
# or
psql -h localhost -U postgres -d mydb -WCorrect (using the certificate's hostname):
psql -h my-database.example.com -U postgres -d mydb -WFor applications, update your connection string:
# Before
postgresql://user:[email protected]:5432/mydb?sslmode=verify-full
# After
postgresql://user:[email protected]:5432/mydb?sslmode=verify-fullEnsure that the hostname you're using resolves to the correct IP address:
nslookup my-database.example.com
# or
dig my-database.example.comCompare the resolved IP address with your server's actual IP. If they don't match, update your DNS records or use a hostname that does resolve correctly.
If you're in a private network or using /etc/hosts, verify the entry:
grep my-database /etc/hostsUpdate if needed:
echo "192.168.1.50 my-database.example.com" | sudo tee -a /etc/hostsTest the connection using psql with verbose output to see exactly what's happening:
psql -h my-database.example.com -U postgres -d mydb -W \
sslmode=verify-full \
sslrootcert=/path/to/ca-cert.pemFor Node.js applications using node-postgres or similar libraries:
const client = new Client({
host: 'my-database.example.com',
port: 5432,
user: 'postgres',
password: 'password',
database: 'mydb',
ssl: {
rejectUnauthorized: true,
ca: fs.readFileSync('/path/to/ca-cert.pem', 'utf8'),
},
});If you get the error again, the hostname in the connection is still wrong.
Cloud-hosted PostgreSQL services provide a specific endpoint hostname that you must use:
AWS RDS:
- Endpoint: mydb.abc123xyz.us-east-1.rds.amazonaws.com
- Use this hostname exactly as provided
- Download the RDS CA certificate
psql -h mydb.abc123xyz.us-east-1.rds.amazonaws.com -U postgres -d mydb \
sslmode=verify-full \
sslrootcert=rds-ca-2023-root.pemAzure Database for PostgreSQL:
- Endpoint: mydb.postgres.database.azure.com
- SSL is mandatory; obtain the DigiCert certificate from Azure portal
Google Cloud SQL:
- Endpoint: 1.2.3.4:5432 (public IP) or private IP in same VPC
- For SSL, use sslmode=require if IP-based, or sslmode=verify-full if using Cloud Proxy
- Download the server certificate from Cloud Console
Never use IP addresses with sslmode=verify-full on managed services—use their provided hostname.
If you're in development and must connect via IP or alias, you can reduce SSL verification, but this is not recommended for production:
# Verify certificate chain but skip hostname check
psql -h 192.168.1.50 -U postgres -d mydb -W sslmode=verify-ca
# Or, encrypt without verification (least secure)
psql -h 192.168.1.50 -U postgres -d mydb -W sslmode=requireFor Node.js:
const client = new Client({
host: '192.168.1.50',
ssl: {
rejectUnauthorized: false, // Skip hostname/chain verification
},
});This leaves you vulnerable to man-in-the-middle attacks. Fix the hostname/certificate mismatch instead.
Certificate Subject Alternative Names (SAN): Modern certificates use the SAN extension instead of Common Name. A certificate might list multiple hostnames like:
DNS:my-database.example.com
DNS:db.example.com
DNS:*.example.com
IP:192.168.1.50Your connection hostname must match one of these exactly (wildcards are honored for partial matches, but IP addresses must match exactly).
Wildcards: A certificate with DNS:*.example.com will match my-database.example.com but NOT sub.my-database.example.com (multi-level wildcards are invalid) or example.com itself.
Self-Signed Certificates: If your PostgreSQL server uses a self-signed certificate and you regenerate it with a different hostname, existing clients will fail. Either regenerate the certificate with all required hostnames, or regenerate with the new hostname and update all clients.
SSL Version Issues: Ensure your PostgreSQL server's SSL certificate and client libraries support the same TLS versions (TLS 1.2+). Older distributions may have compatibility issues.
pg_dump/pg_restore: These tools also respect SSL mode and certificate validation. If you get the error in backups/restores:
pg_dump -h my-database.example.com -U postgres --require-password \
-v | gzip > backup.sql.gzKubernetes/Docker: In containerized environments, use the service DNS name from your orchestrator (e.g., postgres.default.svc.cluster.local in Kubernetes, or the container name in Docker networks), not the container IP.
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
No SSL connection
No SSL connection to PostgreSQL
pg_dump: could not obtain lock on table
pg_dump could not obtain lock on table