Skip to main content

Command Palette

Search for a command to run...

When SSL Lies: Debugging PostgreSQL “server does not support SSL” in Kubernetes

Published
5 min read
When SSL Lies: Debugging PostgreSQL “server does not support SSL” in Kubernetes
S

DevOps & Cloud Engineer — building scalable, automated, and intelligent systems. Developer of sorts | Automator | Innovator

You spin up a Kubernetes workload. You connect to PostgreSQL.

You add sslmode=require because security matters.

And then PostgreSQL replies with:

server does not support SSL, but SSL was required

Wait. What?

This is one of those errors that sounds like a configuration typo but usually reveals something deeper about your infrastructure. Let’s break it down properly and fix it the right way.

The Setup

This was a fairly common environment:

  • Application running inside Kubernetes

  • PostgreSQL running on a private IP inside the VPC

  • Direct psql access used for testing connectivity

  • Connection string explicitly enforcing SSL

The test command looked like this:

psql "host=10.1.1.17 port=5432 dbname=mydb user=myuser sslmode=require"

And PostgreSQL responded:

psql: error: connection to server at "10.1.1.17", port 5432 failed:
server does not support SSL, but SSL was required

At first glance, it feels contradictory. PostgreSQL supports SSL. So why is it saying it does not?


What sslmode=require Actually Does

When you set:

sslmode=require

you are telling the PostgreSQL client:

If SSL cannot be negotiated, fail immediately.

No fallback. No downgrade. No retry without encryption.

The connection flow looks like this:

If the server is not configured with SSL enabled, the handshake never happens and the client exits.

That is exactly what happened here.


Why This Happens in Kubernetes Environments

In many Kubernetes setups, PostgreSQL is:

  • A container inside the cluster

  • A VM inside a private subnet

  • An internal managed database

  • Or a local development database

In these cases, SSL is often disabled by default.

This creates a mismatch:

  • The client demands encryption

  • The server is configured for plain TCP

  • PostgreSQL refuses to downgrade

  • The connection fails

From PostgreSQL’s perspective, nothing is wrong. It simply does not have SSL enabled.

Step 1: Confirm Whether the Server Supports SSL

Before changing anything, verify the server configuration.

If you can connect without SSL, try:

psql "host=10.1.1.17 port=5432 dbname=mydb user=myuser sslmode=disable"

If that works, then the database is reachable and the issue is purely SSL related.

Now check whether SSL is enabled on the server:

SHOW ssl;

If it returns:

ssl | off

then the error makes complete sense.


Step 2: Understand Your Architecture

Here is the real question:

Should SSL even be required here?

Look at the traffic path.

If all communication is happening:

  • Inside the same Kubernetes cluster

  • Or inside a private VPC

  • Without exposure to the public internet

then the network layer is already isolated.

In such cases, enforcing SSL is sometimes unnecessary and only adds complexity.

However, if the database is:

  • Publicly accessible

  • Cross region

  • Or accessed over the internet

then SSL should absolutely be enabled.


Step 3: The Two Real Fixes

There are only two correct solutions.

Option One: Disable SSL on the Client

If this is an internal trusted network, change:

sslmode=require

to:

sslmode=disable

or simply remove the parameter.

Test:

psql "host=10.1.1.17 port=5432 dbname=mydb user=myuser"

If it connects successfully, you are done.

This is common in:

  • Local development

  • Internal Kubernetes clusters

  • Private staging environments

Option Two: Enable SSL on PostgreSQL Properly

If encryption is required, then the server must be configured correctly.

In postgresql.conf:

ssl = on
ssl_cert_file = 'server.crt'
ssl_key_file = 'server.key'

Then update pg_hba.conf:

/code

Restart PostgreSQL.

Now test:

psql "host=10.1.1.17 port=5432 dbname=mydb user=myuser sslmode=require"

And confirm:

SELECT ssl_is_used();

If it returns true, the handshake succeeded.

The flow now looks like this:

That is the correct configuration if encryption is part of your compliance or security requirement.


A Common Hidden Cause in Cloud Environments

There is one more subtle scenario.

Sometimes you are used to managed services like Amazon RDS where SSL is enabled automatically.

Then you switch to:

  • Self managed PostgreSQL

  • A container image

  • A VM based deployment

And assume SSL is still enabled.

It is not.

Managed database services often handle:

  • Certificate provisioning

  • Key rotation

  • TLS negotiation

  • Client CA bundles

Self managed PostgreSQL does none of that unless you configure it explicitly.

That assumption gap is where this error usually comes from.

Practical Debug Checklist

Whenever you see this error, follow this mental model:

Keep it simple.

Test the network first. Then test without SSL.

Then make an intentional security decision.


Lessons Learned

The key takeaway is this:

Just because PostgreSQL supports SSL does not mean your server instance is configured for it. Blindly adding sslmode=require because it feels secure can actually break perfectly valid internal architectures.

Security is about understanding your network boundaries, not just toggling flags in connection strings. If traffic never leaves a private subnet, SSL might be optional.

If traffic crosses public infrastructure, SSL should be enforced and configured correctly.

The important part is intention.


Final Thought

This error is not PostgreSQL lying. It is PostgreSQL being honest.

It is simply telling you:

“I do not have SSL enabled, and you told me not to connect without it.”

Once you understand that, the fix becomes straightforward.

And like most infrastructure issues, the real problem was not PostgreSQL.

It was an assumption.