Files
nginx-proxy-manager/backend/lib/config.js
Jamie Curnow a12553fec7 Convert backend to ESM
- About 5 years overdue
- Remove eslint, use bomejs instead
2025-09-03 13:59:40 +10:00

238 lines
5.5 KiB
JavaScript

import fs from "node:fs";
import NodeRSA from "node-rsa";
import { global as logger } from "../logger.js";
const keysFile = '/data/keys.json';
const mysqlEngine = 'mysql2';
const postgresEngine = 'pg';
const sqliteClientName = 'sqlite3';
let instance = null;
// 1. Load from config file first (not recommended anymore)
// 2. Use config env variables next
const configure = () => {
const filename = `${process.env.NODE_CONFIG_DIR || "./config"}/${process.env.NODE_ENV || "default"}.json`;
if (fs.existsSync(filename)) {
let configData;
try {
// Load this json synchronously
const rawData = fs.readFileSync(filename);
configData = JSON.parse(rawData);
} catch (_) {
// do nothing
}
if (configData?.database) {
logger.info(`Using configuration from file: ${filename}`);
instance = configData;
instance.keys = getKeys();
return;
}
}
const envMysqlHost = process.env.DB_MYSQL_HOST || null;
const envMysqlUser = process.env.DB_MYSQL_USER || null;
const envMysqlName = process.env.DB_MYSQL_NAME || null;
if (envMysqlHost && envMysqlUser && envMysqlName) {
// we have enough mysql creds to go with mysql
logger.info("Using MySQL configuration");
instance = {
database: {
engine: mysqlEngine,
host: envMysqlHost,
port: process.env.DB_MYSQL_PORT || 3306,
user: envMysqlUser,
password: process.env.DB_MYSQL_PASSWORD,
name: envMysqlName,
},
keys: getKeys(),
};
return;
}
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) {
// 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,
user: envPostgresUser,
password: process.env.DB_POSTGRES_PASSWORD,
name: envPostgresName,
},
keys: getKeys(),
};
return;
}
const envSqliteFile = process.env.DB_SQLITE_FILE || "/data/database.sqlite";
logger.info(`Using Sqlite: ${envSqliteFile}`);
instance = {
database: {
engine: "knex-native",
knex: {
client: sqliteClientName,
connection: {
filename: envSqliteFile,
},
useNullAsDefault: true,
},
},
keys: getKeys(),
};
};
const getKeys = () => {
// Get keys from file
logger.debug("Cheecking for keys file:", keysFile);
if (!fs.existsSync(keysFile)) {
generateKeys();
} else if (process.env.DEBUG) {
logger.info("Keys file exists OK");
}
try {
// Load this json keysFile synchronously and return the json object
const rawData = fs.readFileSync(keysFile);
return JSON.parse(rawData);
} catch (err) {
logger.error(`Could not read JWT key pair from config file: ${keysFile}`, err);
process.exit(1);
}
};
const generateKeys = () => {
logger.info("Creating a new JWT key pair...");
// Now create the keys and save them in the config.
const key = new NodeRSA({ b: 2048 });
key.generateKeyPair();
const keys = {
key: key.exportKey("private").toString(),
pub: key.exportKey("public").toString(),
};
// Write keys config
try {
fs.writeFileSync(keysFile, JSON.stringify(keys, null, 2));
} catch (err) {
logger.error(`Could not write JWT key pair to config file: ${keysFile}: ${err.message}`);
process.exit(1);
}
logger.info(`Wrote JWT key pair to config file: ${keysFile}`);
};
/**
*
* @param {string} key ie: 'database' or 'database.engine'
* @returns {boolean}
*/
const configHas = (key) => {
instance === null && configure();
const keys = key.split(".");
let level = instance;
let has = true;
keys.forEach((keyItem) => {
if (typeof level[keyItem] === "undefined") {
has = false;
} else {
level = level[keyItem];
}
});
return has;
};
/**
* Gets a specific key from the top level
*
* @param {string} key
* @returns {*}
*/
const configGet = (key) => {
instance === null && configure();
if (key && typeof instance[key] !== "undefined") {
return instance[key];
}
return instance;
};
/**
* Is this a sqlite configuration?
*
* @returns {boolean}
*/
const isSqlite = () => {
instance === null && configure();
return instance.database.knex && instance.database.knex.client === sqliteClientName;
};
/**
* Is this a mysql configuration?
*
* @returns {boolean}
*/
const isMysql = () => {
instance === null && configure();
return instance.database.engine === mysqlEngine;
};
/**
* Is this a postgres configuration?
*
* @returns {boolean}
*/
const isPostgres = () => {
instance === null && configure();
return instance.database.engine === postgresEngine;
};
/**
* Are we running in debug mdoe?
*
* @returns {boolean}
*/
const isDebugMode = () => !!process.env.DEBUG;
/**
* Returns a public key
*
* @returns {string}
*/
const getPublicKey = () => {
instance === null && configure();
return instance.keys.pub;
};
/**
* Returns a private key
*
* @returns {string}
*/
const getPrivateKey = () => {
instance === null && configure();
return instance.keys.key;
};
/**
* @returns {boolean}
*/
const useLetsencryptStaging = () => !!process.env.LE_STAGING;
/**
* @returns {string|null}
*/
const useLetsencryptServer = () => {
if (process.env.LE_SERVER) {
return process.env.LE_SERVER;
}
return null;
};
export { configHas, configGet, isSqlite, isMysql, isPostgres, isDebugMode, getPrivateKey, getPublicKey, useLetsencryptStaging, useLetsencryptServer };