Knex Heroku Error: self signed certificate

Viewed 6473

I keep getting this error:

Error: self signed certificate

When running this command in the terminal:

knex migrate:latest --env production

My knexfile.js

       require('dotenv').config(); 
module.exports = {
      development: {
        client: "pg",
        connection: {
          host: "localhost",
          database: "my-movies"
        }
      },

      production: {
        client: "pg",
        connection: process.env.DATABASE_URL
      }
    };

My .env file:

DATABASE_URL=<my_database_url>?ssl=true

Heroku app info:

Addons:         heroku-postgresql:hobby-dev
Auto Cert Mgmt: false
Dynos:
Git URL:        https://git.heroku.com/path-name.git
Owner:          xxxxxxxxx@xxxx.com
Region:         us
Repo Size:      0 B
Slug Size:      0 B
Stack:          heroku-18
Web URL:        https://my-appname.herokuapp.com/

I've tried putting a key value pair in the production in the knexfile of ssl: true and I get the same error. I've done it this way in the past many, many times and have never had this issue. Wondering if Heroku has changed anything but while searching their docs I couldn't find anything.

5 Answers

The following config at knexfile.js worked for me.

...
production: {
    client: 'postgresql',
    connection: { 
        connectionString: process.env.DATABASE_URL,
        ssl: { rejectUnauthorized: false }
    }
}
...

where the DATABASE_URL is what you get by running heroku config --yourAppName

This is due to a breaking change in pg@^8 (2020/02/25) cf. this heroku help forum.

You can get the full pg@^8 announcement but here is the relevant passage:

Now we will use the default ssl options to tls.connect which includes rejectUnauthorized being enabled. This means your connection attempt may fail if you are using a self-signed cert.

And it seems heroku is using self-signed certificates somewhere.

possible solutions:

  • downgrade to pg@^7
  • instruct pg@^8 to ignore problematic certificates ssl: { rejectUnauthorized: false } (see announcement linked above)
  • find a way to download and trust the certificate instructions

The ssl: { rejectUnauthorized: false } pg config isn't working for me at the moment either.. but I found a temporary (maybe permanent) solution via the heroku docs

Set the following config var:

heroku config:set PGSSLMODE=no-verify

If you are using a config like:

...
production: {
    client: 'postgresql',
    connection: { 
        connectionString: process.env.DATABASE_URL,
        ssl: { rejectUnauthorized: false }
    }
}
...

...and it still isn't working for you, make sure you don't have a ?ssl=true or sslmode set in DB your connection string.

If ssl is set in your connection string it will override the ssl part of your config, meaning behavior is equivalent to:

...
production: {
    client: 'postgresql',
    connection: { 
        connectionString: process.env.DATABASE_URL,
        ssl: true
    }
}
...

Removing the ssl entry from your connection string will fix the problem.

What worked for me was not using just a connection string but also adding the CA from my database as an option to the connection object in knex.

production: {
    client: 'postgresql',
    connection: { 
        connectionString: process.env.DATABASE_URL,
        ssl: { 
          rejectUnauthorized: false,
          ca: process.env.POSTGRES_CA,
        }
    }
}
Related