diff --git a/backend/db.js b/backend/db.js index 1a8b1634e..840b3dbce 100644 --- a/backend/db.js +++ b/backend/db.js @@ -9,18 +9,30 @@ function generateDbConfig() { if (cfg.engine === 'knex-native') { return cfg.knex; } + const connection = { + host: cfg.host, + user: cfg.user, + password: cfg.password, + database: cfg.name, + port: cfg.port, + }; + + // Add PostgreSQL-specific options + if (cfg.engine === 'pg') { + if (cfg.schema) { + connection.schema = cfg.schema; + } + if (cfg.sslMode) { + connection.ssl = cfg.sslMode === 'require' ? true : cfg.sslMode === 'prefer' ? { rejectUnauthorized: false } : cfg.sslMode === 'disable' ? false : cfg.sslMode === 'allow' ? { rejectUnauthorized: false } : false; + } + } + return { client: cfg.engine, - connection: { - host: cfg.host, - user: cfg.user, - password: cfg.password, - database: cfg.name, - port: cfg.port - }, + connection: connection, migrations: { - tableName: 'migrations' - } + tableName: 'migrations', + }, }; } diff --git a/backend/knexfile.js b/backend/knexfile.js index 607552f6f..ddf454de1 100644 --- a/backend/knexfile.js +++ b/backend/knexfile.js @@ -15,5 +15,14 @@ module.exports = { stub: 'lib/migrate_template.js', directory: 'migrations' } + }, + + postgres: { + client: 'pg', + migrations: { + tableName: 'migrations', + stub: 'lib/migrate_template.js', + directory: 'migrations' + } } }; diff --git a/backend/lib/config.js b/backend/lib/config.js index 23184f3e8..eb079d09b 100644 --- a/backend/lib/config.js +++ b/backend/lib/config.js @@ -50,19 +50,29 @@ const configure = () => { } const envPostgresHost = process.env.DB_POSTGRES_HOST || null; - const envPostgresUser = process.env.DB_POSTGRES_USER || null; - const envPostgresName = process.env.DB_POSTGRES_NAME || null; - if (envPostgresHost && envPostgresUser && envPostgresName) { + const envPostgresPort = process.env.DB_POSTGRES_PORT || process.env.DB_POSTGRES_PORT || 5432; + + const envPostgresUser = process.env.DB_POSTGRES_USER || null; + const envPostgresPassword = process.env.DB_POSTGRES_PASSWORD; + + const envPostgresName = process.env.DB_POSTGRES_NAME || null; + const envPostgresSchema = process.env.DB_POSTGRES_SCHEMA || 'public'; + + const envPostgresSSLMode = process.env.DB_POSTGRES_SSL_MODE || 'prefer'; + + if (envPostgresHost && envPostgresUser && envPostgresName && envPostgresPassword) { // we have enough postgres creds to go with postgres logger.info('Using Postgres configuration'); instance = { database: { engine: postgresEngine, host: envPostgresHost, - port: process.env.DB_POSTGRES_PORT || 5432, + port: envPostgresPort, user: envPostgresUser, - password: process.env.DB_POSTGRES_PASSWORD, + password: envPostgresPassword, name: envPostgresName, + schema: envPostgresSchema, + sslMode: envPostgresSSLMode, }, keys: getKeys(), }; @@ -77,10 +87,10 @@ const configure = () => { knex: { client: sqliteClientName, connection: { - filename: envSqliteFile + filename: envSqliteFile, }, - useNullAsDefault: true - } + useNullAsDefault: true, + }, }, keys: getKeys(), }; @@ -123,18 +133,17 @@ const generateKeys = () => { }; module.exports = { - /** * * @param {string} key ie: 'database' or 'database.engine' * @returns {boolean} */ - has: function(key) { + has: function (key) { instance === null && configure(); const keys = key.split('.'); let level = instance; let has = true; - keys.forEach((keyItem) =>{ + keys.forEach((keyItem) => { if (typeof level[keyItem] === 'undefined') { has = false; } else { @@ -178,12 +187,12 @@ module.exports = { instance === null && configure(); return instance.database.engine === mysqlEngine; }, - + /** - * Is this a postgres configuration? - * - * @returns {boolean} - */ + * Is this a postgres configuration? + * + * @returns {boolean} + */ isPostgres: function () { instance === null && configure(); return instance.database.engine === postgresEngine; @@ -233,5 +242,5 @@ module.exports = { return process.env.LE_SERVER; } return null; - } + }, }; diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml index 5abe057b0..6a5814537 100644 --- a/docker/docker-compose.dev.yml +++ b/docker/docker-compose.dev.yml @@ -37,6 +37,8 @@ services: DB_POSTGRES_USER: 'npm' DB_POSTGRES_PASSWORD: 'npmpass' DB_POSTGRES_NAME: 'npm' + DB_POSTGRES_SCHEMA: 'public' + DB_POSTGRES_SSL_MODE: 'prefer' # DB_SQLITE_FILE: "/data/database.sqlite" # DISABLE_IPV6: "true" # Required for DNS Certificate provisioning testing: diff --git a/docs/src/setup/index.md b/docs/src/setup/index.md index c2296da7f..af350e83f 100644 --- a/docs/src/setup/index.md +++ b/docs/src/setup/index.md @@ -121,6 +121,8 @@ services: DB_POSTGRES_USER: 'npm' DB_POSTGRES_PASSWORD: 'npmpass' DB_POSTGRES_NAME: 'npm' + DB_POSTGRES_SCHEMA: 'public' # Optional: PostgreSQL schema (default: 'public') + DB_POSTGRES_SSL_MODE: 'prefer' # Optional: SSL mode (disable, allow, prefer, require) # Uncomment this if IPv6 is not enabled on your host # DISABLE_IPV6: 'true' volumes: @@ -139,9 +141,15 @@ services: - ./postgres:/var/lib/postgresql/data ``` -::: warning +::: info -Custom Postgres schema is not supported, as such `public` will be used. +PostgreSQL Configuration Options: +- `DB_POSTGRES_SCHEMA`: PostgreSQL schema to use (default: 'public') +- `DB_POSTGRES_SSL_MODE`: SSL connection mode + - `disable`: No SSL + - `allow`: Try non-SSL first, then SSL + - `prefer`: Try SSL first, then non-SSL (default) + - `require`: SSL required :::