Warning: setting ssl: true on your database connection offers only limited protection, as the server's certificate is not verified. Set "ssl: [cacertfile: path/to/file]" instead

My application recently upgraded to elixir 1.17 and Erlang/OTP 27.0. It connects to a DigitalOcean managed PostgreSQL cluster.

Now, each time I deploy, this warning log message shows up in my application’s logs:

setting ssl: true on your database connection offers only limited protection, as the server's certificate is not verified. Set "ssl: [cacertfile: path/to/file]" instead

There was a recent change in OTP’s ssl configuration defaults, where it now defaults with verify: :verify_peer instead of verify: :verify_none.

The solution seemed straightforward: I need to either pass the verify: :verify_none ssl option, or profile a CA cert file. I tried both of these solutions, and nothing changed. The same warning message appears.

Here’s my Repo’s configuration with the cacertfile option:

iex> MyApp.Repo.config()
[
  telemetry_prefix: [:myapp, :repo],
  otp_app: :myapp,
  timeout: 15000,
  start_apps_before_migration: [:logger_json],
  adapter: Ecto.Adapters.Postgres,
  database: "...",
  username: "...",
  password: "...",
  hostname: "...",
  port: 25060,
  ssl: true,
  ssl_opts: [
    verify: :verify_peer,
    cacertfile: "/home/app/db-ca-certificate.crt"
  ],
  pool_size: 10
]

According to the ecto_sql docs, the ssl_opts is what you use to pass options to Erlang’s ssl module.

I also tried passing the cacertfile path as a charlist instead of a string, but that made no difference.

I may be missing something, but the link to the docs you posted doesn’t mention an :ssl_opts key. I think you need to pass that list of options to :ssl.

2 Likes

The docs were just updated after a made my original post. Here are the docs that show the :ssl_opts option: Ecto.Adapters.Postgres — Ecto SQL v3.11.3. The CHANGELOG makes no mention of the documentation change, but here is the PR that changed the documentation.

I’ll try the :ssl option now…

Looks like OP in that issue linked to another issue that is similar to yours:

If switching to :ssl doesn’t work, maybe try adding server_name_indication: false?

The :ssl option works!

Here’s an edited version of what my configuration looks like:

config :myapp, MyApp.Repo,
  adapter: Ecto.Adapters.Postgres,
  database: "...",
  username: "...",
  password: "...",
  hostname: "...",
  port: 25060,
  ssl: [
    verify: :verify_peer,
    cacertfile: "/app/.postgres-cert.crt"
  ],
  pool_size: 20
5 Likes