diff --git a/plugins/storage/server/utils.ts b/plugins/storage/server/utils.ts index c3c88fba5..13520b9d1 100644 --- a/plugins/storage/server/utils.ts +++ b/plugins/storage/server/utils.ts @@ -12,7 +12,7 @@ export const createRootDirForLocalStorage = () => { } } catch (err) { Logger.fatal( - "Couldn't create root dir for local storage of attachments", + `Failed to create directory for local file storage at ${env.FILE_STORAGE_LOCAL_ROOT_DIR}`, err ); } diff --git a/server/index.ts b/server/index.ts index 781410bb5..c4d34acfe 100644 --- a/server/index.ts +++ b/server/index.ts @@ -23,7 +23,7 @@ import { checkEnv, checkPendingMigrations } from "./utils/startup"; import { checkUpdates } from "./utils/updates"; import onerror from "./onerror"; import ShutdownHelper, { ShutdownOrder } from "./utils/ShutdownHelper"; -import { sequelize } from "./storage/database"; +import { checkConnection, sequelize } from "./storage/database"; import RedisAdapter from "./storage/redis"; import Metrics from "./logging/Metrics"; @@ -50,6 +50,7 @@ if (serviceNames.includes("collaboration")) { // This function will only be called once in the original process async function master() { + await checkConnection(); await checkEnv(); await checkPendingMigrations(); diff --git a/server/storage/database.ts b/server/storage/database.ts index b0e99eed0..3e1e98f88 100644 --- a/server/storage/database.ts +++ b/server/storage/database.ts @@ -5,6 +5,7 @@ import env from "@server/env"; import Logger from "../logging/Logger"; import * as models from "../models"; +const isDevelopment = env.ENVIRONMENT === "development"; const isProduction = env.ENVIRONMENT === "production"; const isSSLDisabled = env.PGSSLMODE === "disable"; const poolMax = env.DATABASE_CONNECTION_POOL_MAX ?? 5; @@ -18,6 +19,7 @@ export const sequelize = new Sequelize(url, { logging: (msg) => process.env.DEBUG?.includes("database") && Logger.debug("database", msg), typeValidation: true, + logQueryParameters: isDevelopment, dialectOptions: { ssl: isProduction && !isSSLDisabled @@ -36,6 +38,25 @@ export const sequelize = new Sequelize(url, { }, }); +/** + * This function is used to test the database connection on startup. It will + * throw a descriptive error if the connection fails. + */ +export const checkConnection = async () => { + try { + await sequelize.authenticate(); + } catch (error) { + if (error.message.includes("does not support SSL")) { + Logger.fatal( + "The database does not support SSL connections. Set the `PGSSLMODE` environment variable to `disable` or enable SSL on your database server.", + error + ); + } else { + Logger.fatal("Failed to connect to database", error); + } + } +}; + export const migrations = new Umzug({ migrations: { glob: ["migrations/*.js", { cwd: path.resolve("server") }],