Strapi CMS, Heroku error: no pg_hba.conf entry for host - node.js

Three months ago, I created an Strapi App that has deployed on Heroku, and everything works fine. I used macOS 10.13.6 and node 14.15.4 for the local environment
The configuration of database was created inside a file named database.js which located in rootApp/config/env/production/database.js
The following are everything config inside these file (database.js):
const parse = require('pg-connection-string').parse;
const config = parse(process.env.HEROKU_POSTGRESQL_MAROON_URL);
module.exports = ({ env }) => ({
defaultConnection: 'default',
connections: {
default: {
connector: 'bookshelf',
settings: {
client: 'postgres',
host: "ec2-35-169-184-61.compute-1.amazonaws.com",
port: 5432,
database: "d3d9tcukxxx",
username: "mwtwuvkwxxxx",
password: "42f0337xxxxx",
},
options: {
ssl:true,
},
},
},
});
But after 3 months (right now), I checked from heroku logs --tail then these app getting an error and the message was:
error error: no pg_hba.conf entry for host "3.86.36.125", user "mwtwuvkwtrqpir", database "d3d9tcukrk5fgh", SSL off
I used Strapi 3.2.5 , and I was deployed on Heroku Postgres with Plan free (Hobby).
I hope everyone helping me for this questions, and hope helping others for same case.
Thank you

We had the same issue on our Heroku instances and just recently found a fix.
Adding rejectUnauthorized to the database config appears to work.
config/database.js
module.exports = ({ env }) => ({
defaultConnection: 'default',
connections: {
default: {
connector: 'bookshelf',
settings: {
client: 'postgres',
host: env('DATABASE_HOST', 'localhost'),
port: env.int('DATABASE_PORT', 5432),
database: env('DATABASE_NAME', 'strapi'),
username: env('DATABASE_USERNAME', 'strapi'),
password: env('DATABASE_PASSWORD', 'strapi'),
schema: env('DATABASE_SCHEMA', 'public'), // Not Required
ssl: {
rejectUnauthorized: env.bool('DATABASE_SSL_SELF', false), // For self-signed certificates
},
},
options: {
ssl: env.bool('DATABASE_SSL', false),
},
},
},
});
I cannot take full credit however, it was this post on the Strapi forum that led me to the answer:
https://forum.strapi.io/t/error-no-pg-hba-conf-entry-for-host-ssl-off/3409
subsequently this link:
https://strapi.io/documentation/developer-docs/latest/setup-deployment-guides/configurations.html#database

Related

Failed to connect to *name_server* - getaddrinfo ENOTFOUND

When connecting to the database with sequelize-typescript, an error occurs
Failed to connect to SERVER\SQL2016:1433 - getaddrinfo ENOTFOUND SERVER\SQL2016
Connection settings
import { Sequelize } from 'sequelize-typescript'
import { environment } from '../config'
import { normalize, join } from 'path'
export default new Sequelize({
database: environment.database.database,
dialect: "mssql",
username: environment.database.username,
// port: environment.database.port,
password: environment.database.password,
host: environment.database.host,
logging: !environment.production ? console.log : false,
models: [normalize(join(__dirname, "..", "models"))],
dialectOptions: {
options: {
enableArithAbort: true,
cryptoCredentialsDetails: {
minVersion: "TLSv1",
},
},
},
})
interface DatabaseConnection {
database: string
username: string
port: number
password: string
host: string
hostAsodu: string
databaseAsodu: string
}
export const environment: Environment = {
port: process.env.PORT ? Number(process.env.PORT) : 3030,
production: process.env.NODE_ENV === "production",
database: {
database: process.env.DB_DATABASE ?? String(),
username: process.env.DB_USERNAME ?? String(),
port: process.env.DB_PORT ? Number(process.env.DB_PORT) : 0,
password: process.env.DB_PASSWORD ?? String(),
host: process.env.DB_HOST ?? String(),
hostAsodu: process.env.DB_HOST_ASODU ?? String(),
databaseAsodu: process.env.DB_DATABASE_ASODU ?? String()
},
}
I tried connectit with and without a port, the error is the same. It just connects to SERVER, but does not want to connect to the named SERVER \ SQL2016. How can I fix this error? Found nothing on the docks
ENOTFOUND is an operating-system-level error from your OS's networking code. It means you asked it to look up a hostname and it came up with nothing. In the lingo, your name "could not be resolved." (www.stackoverflow.com is a hostname, for example. https://www.stackoverflow.com is a URL, which happens to contain a hostname.)
getaddrinfo() is OS method that asks the domain name service (DNS) to look up a hostname.
It looks to me like you tried to look up the hostname SERVER\SQL2016. That's not a hostname. You probably want something like sql2016.example.com instead. Ask the person who operates that SQL Server instance for the correct hosthame.
The SQL Server instance I use has a hostname something like devdatabase.dev.example.com.
Edit The SQL2016 part of your connection string is known as the server instance or DataSource. You need to specify it separately from the hostname. See this. Error connecting to SQL Server database with sequelize You also need to make sure your SQL Server software is configured to allow TCP connections.
Try this as you connect.
export default new Sequelize({
database: environment.database.database,
dialect: "mssql",
username: environment.database.username,
// port: environment.database.port,
password: environment.database.password,
host: environment.database.host, /* should be the hostname without \SQL2016 */
logging: !environment.production ? console.log : false,
models: [normalize(join(__dirname, "..", "models"))],
dialectOptions: {
instanceName: 'SQL2016',
options: {
enableArithAbort: true,
cryptoCredentialsDetails: {
minVersion: "TLSv1",
},
},
},
})

How to add an SSL certificate (ca-cert) to node.js environment variables in order to connect to Digital Ocean Postgres Managed Database?

I am currently using node-postgres to create my pool. This is my current code:
const { Pool } = require('pg')
const pgPool = new Pool({
user: process.env.PGUSER,
password: process.env.PGPASSWORD,
host: process.env.PGHOST,
database: process.env.PGDATABASE,
port: process.env.PGPORT,
ssl: {
rejectUnauthorized: true,
// Would like to add line below
// ca: process.env.CACERT,
},
})
I found another post where they read in the cert using 'fs' which can be seen below.
const config = {
database: 'database-name',
host: 'host-or-ip',
user: 'username',
password: 'password',
port: 1234,
// this object will be passed to the TLSSocket constructor
ssl: {
ca: fs.readFileSync('/path/to/digitalOcean/certificate.crt').toString()
}
}
I am unable to do that as I am using git to deploy my application. Specifically Digital Oceans new App Platform. I have attempted reaching out to them with no success. I would prefer not to commit my certificate in my source control. I see a lot of posts of people suggesting to set
ssl : { rejectUnauthorized: false}
That is not the approach I want to take. My code does work with that but I want it to be secure.
Any help is appreciated thanks.
Alright I finally was able to figure it out. I think the issue was multiline and just unfamiliarity with dotenv for my local developing environment.
I was able to get it all working with my code like this. It also worked with the fs.readFileSync() but I didn't want to commit that to my source control.
const { Pool } = require('pg')
const fs = require('fs')
const pgPool = new Pool({
user: process.env.PGUSER,
password: process.env.PGPASSWORD,
host: process.env.PGHOST,
database: process.env.PGDATABASE,
port: process.env.PGPORT,
ssl: {
rejectUnauthorized: true,
// ca: fs.readFileSync(
// `${process.cwd()}/cert/ca-certificate.crt`.toString()
// ),
ca: process.env.CA_CERT,
},
})
.on('connect', () => {
console.log('connected to the database!')
})
.on('error', (err) => {
console.log('error connecting to database ', err)
})
Now in my config.env I had to make it look like this:
CA_CERT="-----BEGIN CERTIFICATE-----\nVALUES HERE WITH NO SPACES AND A \n
AFTER EACH LINE\n-----END CERTIFICATE-----"
I had to keep it as a single line string to have it work. But I was finally to connect with
{rejectUnauthorized:true}
For the digital ocean app platform environment variable, I copied everything including the double quotes and pasted it in there. Seems to work great. I do not think you will be able to have this setting set to true with their $7 development database though. I had to upgrade to the managed one in order to find any CA cert to download.

Strapi giving me DB errors in production, even though I'm using correct credentials

EDIT: I found a file at /config/database.js which is used to connect to sqlite in development. When I change the client name from sqlite to postgres, that's when the trouble starts.
Isn't strapi supposed to ignore files like this in production? How can I get strapi to ignore this file, and just use my postgres db?
module.exports = ({ env }) => ({
defaultConnection: 'default',
connections: {
default: {
connector: 'bookshelf',
settings: {
client: 'sqlite',
filename: env('DATABASE_FILENAME', '.tmp/data.db'),
},
options: {
useNullAsDefault: true,
},
},
},
});
End edit.
I'm trying to get my strapi app to start up in production, but it keeps erroring out saying
[2020-07-22T01:15:40.246Z] debug ⛔️ Server wasn't able to start properly.
[2020-07-22T01:15:40.247Z] error error: password authentication failed for user "<redacted>"
The rest of the output is related to pg, which leads me to think that this is a DB connection error.
I can log into my db from the command line using psql -U postgres -W, which confirms that I know my password.
In addition, I'm using pm2 to run things, and instead of using process.env in that file, I just added the db variables directly, but that made no difference.
The application has been built in production mode. I have 3 dbs in pg, one called postgres, one with my apps name, and another called strapi.
Thanks
my /config/enviroronments/production.database.json looks like this
{
"defaultConnection": "default",
"connections": {
"default": {
"connector": "bookshelf",
"settings": {
"client": "postgres",
"host": "${process.env.DATABASE_HOST || '127.0.0.1'}",
"port": "${process.env.DATABASE_PORT || 27017}",
"database": "${process.env.DATABASE_NAME || 'strapi'}",
"username": "${process.env.DATABASE_USERNAME || ''}",
"password": "${process.env.DATABASE_PASSWORD || ''}"
},
"options": {
"ssl": false
}
}
}
}
and I have a .env file at the root of the backend app that looks like this
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_NAME="<redacted - all letters>"
DATABASE_USERNAME="<redacted - all letters>"
DATABASE_PASSWORD="<redacted - all letters>"
Found the issue. When I created the app, I used sqlite as my db. As a result, the default database.js file wasn't set up in a way that could be overwritten with env variables.
I created a new local Strapi app with pgsql as my db, and copied the contents of the database.js file to my server. All working now.
New file for reference
module.exports = ({ env }) => ({
defaultConnection: 'default',
connections: {
default: {
connector: 'bookshelf',
settings: {
client: 'postgres',
host: env('DATABASE_HOST', '127.0.0.1'),
port: env.int('DATABASE_PORT', 5432),
database: env('DATABASE_NAME', 'my-strapi-project'),
username: env('DATABASE_USERNAME', 'testing'),
password: env('DATABASE_PASSWORD', 'testing'),
ssl: env.bool('DATABASE_SSL', false),
},
options: {}
},
},
});
I had the same situation in development. I created a strapi app with SQLite and decided to use PostgreSQL. That's where the trouble came in. So the fix was as follows:
app_name/config/database.js
module.exports = ({ env }) => ({
connection: {
client: 'postgres',
connection: {
host: env('DATABASE_HOST', '127.0.0.1'),
port: env.int('DATABASE_PORT', 5432),
database: env('DATABASE_NAME', 'db_name'),
user: env('DATABASE_USERNAME', 'postgres'),
password: env('DATABASE_PASSWORD', 'postgres'),
ssl: env.bool('DATABASE_SSL', false),
},
},
});
Your dependencies under app_name/package.json should be like
"dependencies": {
"#strapi/strapi": "4.1.8",
"#strapi/plugin-users-permissions": "4.1.8",
"#strapi/plugin-i18n": "4.1.8",
"pg": "8.6.0"
}
[2023-02-19 11:27:27.197] debug: ⛔️ Server wasn't able to start properly.
[2023-02-19 11:27:27.199] error: password authentication failed for user "root"
FIX==>
su - postgres
psql postgres
CREATE ROLE root SUPERUSER LOGIN PASSWORD 'password';
The point of interest here is the module used with strapi .
configuration file database.js
module.exports = ({ env }) => ({
defaultConnection: "default",
connection: {
client: "postgres",
connection: {
host: "127.0.0.1",
port: 5432,
database: "dbname",
username: "postgres",
password: "password",
ssl: false
},
debug: true,
useNullAsDefault: true
}
});
version package.json
"#_sh/strapi-plugin-ckeditor": "^2.0.3",
"#strapi/plugin-i18n": "4.6.1,",
"#strapi/plugin-users-permissions": "4.6.1,",
"#strapi/strapi": "4.6.1,",
"better-sqlite3": "8.0.1",
"pg": "8.6.0"
check version
/etc/postgresql/{{version-postsql}}/main/pg_hba.conf
local replication all peer
host replication all 127.0.0.1/32 md5
host replication all ::1/128 md5
host all postgres 127.0.0.1/32 trust
host all all ::1/128 trust
restart postgresql
sudo systemctl restart postgresql.service
su - postgres
psql
DROP root;
CREATE ROLE root WITH SUPERUSER CREATEDB CREATEROLE LOGIN ENCRYPTED PASSWOR 'password......';
CREATEDB dbname;
I don't know why it took the initial role of root but the above simple solution worked for me

Node Sequelize (MSSQL) - Login failed for user ''

I've come across several posts for this question however, none of them seem to have an actual answer. Several ideas, yet none of them work.
After digging around both the Sequelize and Tedious packages and watching my config get passed down correctly, I'm at a loss.
I am trying to run migrations against a new database in MSSQL. I have no problem connecting to it with the same creds I'm using here so I know that's not the issue.
I have my config.js that is pulling env vars. With the exception of my custom console statements, this file was auto generated from sequelize and is correctly referenced in my sequelizerc
require('dotenv').config()
console.log('[+] Loading database config...')
if (process.env.NODE_ENV === 'production') {
console.log(`[+] Using database: ${process.env.PROD_DB_DATABASE}`)
} else if (process.env.NODE_ENV === 'development') {
console.log(`[+] Using database: ${process.env.DEV_DB_DATABASE}`)
} else if (process.env.NODE_ENV === 'test') {
console.log(`[+] Using database: ${process.env.TEST_DB_DATABASE}`)
} else if (process.env.NODE_ENV === 'local') {
console.log(`[+] Using database: ${process.env.LOCAL_DB_DATABASE}`)
} else {
console.log(`[-] CANNOT LOAD DATABASE FROM ENV: ${process.env.NODE_ENV}`)
process.exit()
}
module.exports = {
production: {
database: process.env.PROD_DB_DATABASE,
username: process.env.PROD_DB_USERNAME,
password: process.env.PROD_DB_PASSWORD,
host: process.env.PROD_DB_HOST,
port: process.env.PROD_DB_PORT,
dialect: process.env.PROD_DB_DIALECT,
storage: process.env.PROD_DB_STORAGE,
logging: false,
dialectOptions: {
instanceName: process.env.PROD_INSTANCE_NAME
},
pool: {
min: 5,
max: 1,
acquire: 6000,
idle: 6000
}
},
development: {
database: process.env.DEV_DB_DATABASE,
username: process.env.DEV_DB_USERNAME,
password: process.env.DEV_DB_PASSWORD,
host: process.env.DEV_DB_HOST,
port: process.env.DEV_DB_PORT,
dialect: process.env.DEV_DB_DIALECT,
storage: process.env.DEV_DB_STORAGE,
logging: console.log,
dialectOptions: {
instanceName: process.env.DEV_INSTANCE_NAME,
debug: true
},
pool: {
min: 5,
max: 1,
acquire: 6000,
idle: 6000
}
},
test: {
database: process.env.TEST_DB_DATABASE,
username: process.env.TEST_DB_USERNAME,
password: process.env.TEST_DB_PASSWORD,
host: process.env.TEST_DB_HOST,
port: process.env.TEST_DB_PORT,
dialect: process.env.TEST_DB_DIALECT,
storage: process.env.TEST_DB_STORAGE,
logging: false
},
local: {
database: process.env.LOCAL_DB_DATABASE,
username: process.env.LOCAL_DB_USERNAME,
password: process.env.LOCAL_DB_PASSWORD,
host: process.env.LOCAL_DB_HOST,
port: process.env.LOCAL_DB_PORT,
dialect: process.env.LOCAL_DB_DIALECT,
storage: process.env.LOCAL_DB_STORAGE,
logging: false
}
}
When i run my migration i get the error:
> node_modules/.bin/sequelize db:migrate
// ERROR: Login failed for user ''.
As mentioned above I dug through sequelize and tedious and my config is getting passed properly through both so i know it's not an env var issue or a NODE_ENV issue.
Anyone have any ideas here? I'm about to smash my face into my keyboard.
More for older versions:
If you are using sequelize#4, then it seems there is a hidden requirement that you must use tedious#<=5.
Which version of Sequelize are you using? If it's v5,
According to Sequelize v5's document:
Sequelize now works with tedious >= 6.0.0
However, in its package.json, it does not depend on tedious at all.
Since your program still runs, I guess you manually installed an older version of tedious before, which caused this strange problem.
Manually installing tedious of version>=6 should solve this problem, just like stated in its Getting started document page:
You'll also have to manually install the driver for your database of choice:
# One of the following:
$ npm install --save pg pg-hstore # Postgres
$ npm install --save mysql2
$ npm install --save mariadb
$ npm install --save sqlite3
$ npm install --save tedious # Microsoft SQL Server
const Sequelize = require('sequelize');
const sequelize = new Sequelize(
process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASS, {
dialect: 'mssql',
host: process.env.DB_HOST, //This is an IP
dialectOptions: {
options: {
instanceName: process.env.DB_INSTANCE_NAME,
trustServerCertificate: true
},
}
}
);
module.exports = {
sequelize,
Sequelize
};
Here is another solution, it's working for me.
I was getting the same error. The reason was due to explicitly mentioning the name of the DB in the sequelize config file and it did not exist. The reason could be different in your case but a quick look at SQL Server error logs will give you the reason for the failure.
Login failed for user 'user'. Reason: Failed to open the explicitly specified database 'dbo'. [CLIENT: XX.XX.XX.XX]

Knex:Error Pool2 - Error: The server does not support SSL connections

Trying to connect with Postgres Node js and ran into the error
Resource Wall is listening on port 8080
Knex:Error Pool2 - Error: The server does not support SSL connections
Knex:Error Pool2 - Error: The server does not support SSL connections
How to turn off SSL connection? Here is my environment setup
DB_HOST=localhost
DB_USER=postgres
DB_PASS=password
DB_NAME=dbname
DB_SSL=true if heroku
DB_PORT=5432
And my knexfile.js
require('dotenv').config();
module.exports = {
development: {
client: 'postgresql',
connection: {
host : process.env.DB_HOST,
user : process.env.DB_USER,
password : process.env.DB_PASS,
database : process.env.DB_NAME,
port : process.env.DB_PORT,
ssl : process.env.DB_SSL
},
migrations: {
directory: './db/migrations',
tableName: 'migrations'
},
seeds: {
directory: './db/seeds'
}
},
production: {
client: 'postgresql',
connection: process.env.DATABASE_URL + '?ssl=true',
pool: {
min: 2,
max: 10
},
migrations: {
tableName: 'migrations'
}
}
};
Since I am running in dev, I expected that it won't go through SSL. Tried removing that SSL part from object and URL too. No luck.
There is no reason why knex would try to force using ssl connection when it is not explicitly asked to do that (well actually pg driver takes care of that part).
You may want to use this as a base to connect heroku and then work more complex configuration on top of this:
const knex = require('knex')({
client: 'pg',
connection: 'postgres://user:pass#server:port/database'
});
knex.raw('select 1')
.then(res => {
console.log('Success');
})
.catch(err => {
console.log('Something failed', err);
});

Resources