PgDeck

Connect PostgreSQL with SSL

Connecting to PostgreSQL over SSL.

PostgreSQL has six sslmode values and only two of them actually protect you. The difference between them is not encryption — it is whether anyone checked who they were encrypting to.

Short answer: sslmode=require encrypts the connection but performs no certificate verification, so it does not protect against an attacker who can intercept your traffic. Use verify-full for anything crossing a network you do not control: it validates the certificate chain against a CA you supply and checks that the hostname matches. That is the mode that actually prevents interception.

PgDeck PostgreSQL desktop client with schema navigation, table filtering, row editing, and SQL tools

Why developers use PgDeck

PgDeck is shaped around PostgreSQL tasks that happen every day: connect, inspect, filter, edit, query, manage structure, copy, and export.

prefer is the default and silently falls back to plaintext
require encrypts but verifies nothing — interception still possible
verify-full validates the chain and the hostname
pg_stat_ssl proves whether your session is actually encrypted
hostssl in pg_hba.conf enforces TLS server-side for everyone

Secure connections

Save PostgreSQL connection details with encrypted passwords, SSL settings, URL import, testing, search, edit, and delete actions.

Schema and data grid

Browse schemas and tables, search the table list, pin favorites, filter rows, sort columns, resize columns, and paginate results.

SQL workspace

Run SELECT and non-SELECT statements from multi-tab SQL editors with syntax highlighting and interactive query results.

Staged editing

Edit cells, add rows, duplicate rows, set NULL, stage deletes, review pending changes, and commit everything in one transaction.

How to connect to PostgreSQL over SSL

  1. Understand what each mode does

    disable never encrypts. allow and prefer will use TLS if offered and silently fall back to plaintext if not — prefer is the default, which means an unconfigured client may not be encrypted at all. require always encrypts but verifies nothing. verify-ca checks the certificate chain. verify-full also checks that the hostname you connected to matches the certificate.

  2. Use verify-full across untrusted networks

    Download the CA certificate from your provider, then reference it with sslrootcert. Without a root certificate, verify modes cannot work — and with only require, an attacker positioned between you and the server can present their own certificate, decrypt everything, and forward it on. Your connection is encrypted to the wrong party.

    postgres://user:password@db.example.com:5432/mydb?sslmode=verify-full&sslrootcert=/path/to/ca.crt
  3. Confirm the connection is actually encrypted

    Do not assume. pg_stat_ssl reports whether your own backend is using TLS, which version, and which cipher. If ssl comes back false while you believed you were using SSL, your sslmode was probably prefer and the server declined.

    SELECT ssl, version, cipher, bits
    FROM pg_stat_ssl
    WHERE pid = pg_backend_pid();
  4. Enable SSL on a self-hosted server

    Managed providers do this for you. On your own server, set ssl = on in postgresql.conf with a certificate and key, then restart. The key must be readable only by the postgres user or the server refuses to start — that permission check is deliberate.

    # postgresql.conf
    ssl = on
    ssl_cert_file = 'server.crt'
    ssl_key_file = 'server.key'
    
    # The key must not be group- or world-readable
    chmod 600 server.key
    chown postgres:postgres server.key
  5. Require SSL at the server, not just the client

    A client-side sslmode is a request, not a guarantee — it protects that client only. To make encryption mandatory for everyone, use hostssl rather than host in pg_hba.conf, which refuses any non-TLS connection matching that rule. Reload afterwards; pg_hba.conf does not need a restart.

    # pg_hba.conf — hostssl refuses unencrypted connections
    hostssl  all  all  0.0.0.0/0  scram-sha-256
    
    SELECT pg_reload_conf();

Why require is not enough

Encryption without authentication protects against passive eavesdropping and nothing else. With sslmode=require the client accepts any certificate, including a self-signed one generated by whoever is sitting between you and the server. They terminate your TLS session, read your credentials and your data in clear, and open their own connection onward. Everything looks normal at both ends. verify-full is what closes this, by checking the certificate chains to a CA you trust and that the hostname matches.

verify-ca versus verify-full

verify-ca confirms the certificate was issued by a CA you trust but not that it was issued for the host you are connecting to. If the CA signs certificates for many hosts — which is exactly the case with a cloud provider's shared CA — another customer's valid certificate would pass. verify-full adds the hostname check and is the mode to use unless you have a specific reason not to.

Getting the root certificate

Every managed provider publishes a CA bundle: Amazon RDS has regional bundles, and Supabase, Neon, Azure, and Google Cloud SQL each provide theirs from the console. Download it over HTTPS from the provider's own documentation, store it somewhere stable, and point sslrootcert at it. Do not copy a certificate from a forum post.

Client certificates for mutual TLS

sslcert and sslkey let the client present its own certificate, so the server can authenticate you by certificate rather than password. Combined with the cert authentication method in pg_hba.conf, this removes passwords from the connection entirely. It is more setup and more key rotation, and it is the strongest option available where that trade is worth making.

SSL is not a substitute for network controls

Encrypting the connection does not make a database safe to expose to the internet. Automated scanners find open port 5432 quickly and will attempt credential stuffing against it regardless of TLS. Keep the database on a private network and reach it through a bastion host or SSH tunnel, and use TLS as well rather than instead.

Related PostgreSQL guides

More on choosing, comparing, and running a PostgreSQL desktop client.

What sslmode should I use for PostgreSQL?

verify-full for anything crossing a network you do not control. It encrypts the connection, validates the server certificate against a CA you supply, and checks that the hostname matches. require encrypts but verifies nothing, which leaves you open to interception.

Is sslmode=require secure?

Only against passive eavesdropping. require accepts any certificate, so an attacker able to intercept your traffic can present their own, decrypt everything, and forward it on undetected. Use verify-full, which checks the certificate chain and the hostname.

What is the difference between verify-ca and verify-full?

verify-ca checks the certificate was issued by a CA you trust. verify-full also checks the certificate was issued for the host you are connecting to. Since cloud providers sign many customers' certificates with a shared CA, verify-ca alone would accept another customer's certificate.

How do I check if my PostgreSQL connection is encrypted?

Query pg_stat_ssl for your own backend: SELECT ssl, version, cipher FROM pg_stat_ssl WHERE pid = pg_backend_pid(). If ssl is false, your sslmode was probably prefer, which silently falls back to an unencrypted connection.

How do I force all clients to use SSL?

Use hostssl instead of host in pg_hba.conf, which refuses any connection not using TLS for matching rules, then reload with SELECT pg_reload_conf(). A client-side sslmode only protects that one client; the server-side rule applies to everyone.