feat: Add path to socket for external mariadb database (#6670)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Frank Elsinga <frank@elsinga.de>
This commit is contained in:
Diego 2026-01-18 16:44:43 +01:00 committed by GitHub
parent 999c09d818
commit a86789be6c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 36 additions and 13 deletions

View File

@ -165,7 +165,7 @@ class Database {
* Read the database config * Read the database config
* @throws {Error} If the config is invalid * @throws {Error} If the config is invalid
* @typedef {string|undefined} envString * @typedef {string|undefined} envString
* @returns {{type: "sqlite"} | {type:envString, hostname:envString, port:envString, database:envString, username:envString, password:envString}} Database config * @returns {{type: "sqlite"} | {type:envString, hostname:envString, port:envString, database:envString, username:envString, password:envString, socketPath:envString}} Database config
*/ */
static readDBConfig() { static readDBConfig() {
let dbConfig; let dbConfig;
@ -185,7 +185,7 @@ class Database {
/** /**
* @typedef {string|undefined} envString * @typedef {string|undefined} envString
* @param {{type: "sqlite"} | {type:envString, hostname:envString, port:envString, database:envString, username:envString, password:envString}} dbConfig the database configuration that should be written * @param {{type: "sqlite"} | {type:envString, hostname:envString, port:envString, database:envString, username:envString, password:envString, socketPath:envString}} dbConfig the database configuration that should be written
* @returns {void} * @returns {void}
*/ */
static writeDBConfig(dbConfig) { static writeDBConfig(dbConfig) {
@ -284,6 +284,7 @@ class Database {
port: dbConfig.port, port: dbConfig.port,
user: dbConfig.username, user: dbConfig.username,
password: dbConfig.password, password: dbConfig.password,
socketPath: dbConfig.socketPath,
...(dbConfig.ssl ...(dbConfig.ssl
? { ? {
ssl: { ssl: {
@ -309,6 +310,7 @@ class Database {
user: dbConfig.username, user: dbConfig.username,
password: dbConfig.password, password: dbConfig.password,
database: dbConfig.dbName, database: dbConfig.dbName,
socketPath: dbConfig.socketPath,
timezone: "Z", timezone: "Z",
typeCast: function (field, next) { typeCast: function (field, next) {
if (field.type === "DATETIME") { if (field.type === "DATETIME") {

View File

@ -102,6 +102,7 @@ class SetupDatabase {
dbConfig.dbName = process.env.UPTIME_KUMA_DB_NAME; dbConfig.dbName = process.env.UPTIME_KUMA_DB_NAME;
dbConfig.username = getEnvOrFile("UPTIME_KUMA_DB_USERNAME"); dbConfig.username = getEnvOrFile("UPTIME_KUMA_DB_USERNAME");
dbConfig.password = getEnvOrFile("UPTIME_KUMA_DB_PASSWORD"); dbConfig.password = getEnvOrFile("UPTIME_KUMA_DB_PASSWORD");
dbConfig.socketPath = process.env.UPTIME_KUMA_DB_SOCKET?.trim();
dbConfig.ssl = getEnvOrFile("UPTIME_KUMA_DB_SSL")?.toLowerCase() === "true"; dbConfig.ssl = getEnvOrFile("UPTIME_KUMA_DB_SSL")?.toLowerCase() === "true";
dbConfig.ca = getEnvOrFile("UPTIME_KUMA_DB_CA"); dbConfig.ca = getEnvOrFile("UPTIME_KUMA_DB_CA");
Database.writeDBConfig(dbConfig); Database.writeDBConfig(dbConfig);
@ -160,6 +161,7 @@ class SetupDatabase {
runningSetup: this.runningSetup, runningSetup: this.runningSetup,
needSetup: this.needSetup, needSetup: this.needSetup,
isEnabledEmbeddedMariaDB: this.isEnabledEmbeddedMariaDB(), isEnabledEmbeddedMariaDB: this.isEnabledEmbeddedMariaDB(),
isEnabledMariaDBSocket: process.env.UPTIME_KUMA_DB_SOCKET?.trim().length > 0,
}); });
}); });
@ -202,16 +204,22 @@ class SetupDatabase {
// External MariaDB // External MariaDB
if (dbConfig.type === "mariadb") { if (dbConfig.type === "mariadb") {
if (!dbConfig.hostname) { // If socketPath is provided and not empty, validate it
response.status(400).json("Hostname is required"); if (process.env.UPTIME_KUMA_DB_SOCKET?.trim().length > 0) {
this.runningSetup = false; dbConfig.socketPath = process.env.UPTIME_KUMA_DB_SOCKET.trim();
return; } else {
} // socketPath not provided, hostname and port are required
if (!dbConfig.hostname) {
response.status(400).json("Hostname is required");
this.runningSetup = false;
return;
}
if (!dbConfig.port) { if (!dbConfig.port) {
response.status(400).json("Port is required"); response.status(400).json("Port is required");
this.runningSetup = false; this.runningSetup = false;
return; return;
}
} }
if (!dbConfig.dbName) { if (!dbConfig.dbName) {
@ -241,6 +249,7 @@ class SetupDatabase {
user: dbConfig.username, user: dbConfig.username,
password: dbConfig.password, password: dbConfig.password,
database: dbConfig.dbName, database: dbConfig.dbName,
socketPath: dbConfig.socketPath,
...(dbConfig.ssl ...(dbConfig.ssl
? { ? {
ssl: { ssl: {

View File

@ -1369,6 +1369,7 @@
"None (Successful Connection)": "None (Successful Connection)", "None (Successful Connection)": "None (Successful Connection)",
"expectedTlsAlertDescription": "Select the TLS alert you expect the server to return. Use {code} to verify mTLS endpoints reject connections without client certificates. See {link} for details.", "expectedTlsAlertDescription": "Select the TLS alert you expect the server to return. Use {code} to verify mTLS endpoints reject connections without client certificates. See {link} for details.",
"TLS Alert Spec": "RFC 8446", "TLS Alert Spec": "RFC 8446",
"mariadbSocketPathDetectedHelptext": "Connecting to the database as specified via the {0} environment variable.",
"Expand All Groups": "Expand All Groups", "Expand All Groups": "Expand All Groups",
"Collapse All Groups": "Collapse All Groups" "Collapse All Groups": "Collapse All Groups"
} }

View File

@ -79,7 +79,7 @@
</div> </div>
<template v-if="dbConfig.type === 'mariadb'"> <template v-if="dbConfig.type === 'mariadb'">
<div class="form-floating mt-3 short"> <div v-if="!isProvidedMariaDBSocket" class="form-floating mt-3 short">
<input <input
id="floatingInput" id="floatingInput"
v-model="dbConfig.hostname" v-model="dbConfig.hostname"
@ -90,11 +90,19 @@
<label for="floatingInput">{{ $t("Hostname") }}</label> <label for="floatingInput">{{ $t("Hostname") }}</label>
</div> </div>
<div class="form-floating mt-3 short"> <div v-if="!isProvidedMariaDBSocket" class="form-floating mt-3 short">
<input id="floatingInput" v-model="dbConfig.port" type="text" class="form-control" required /> <input id="floatingInput" v-model="dbConfig.port" type="text" class="form-control" required />
<label for="floatingInput">{{ $t("Port") }}</label> <label for="floatingInput">{{ $t("Port") }}</label>
</div> </div>
<div v-if="isProvidedMariaDBSocket" class="mt-1 short text-start">
<i18n-t keypath="mariadbSocketPathDetectedHelptext" tag="div" class="form-text">
<code>UPTIME_KUMA_DB_SOCKET</code>
</i18n-t>
</div>
<hr v-if="isProvidedMariaDBSocket" class="mt-3 mb-2 short" />
<div class="form-floating mt-3 short"> <div class="form-floating mt-3 short">
<input <input
id="floatingInput" id="floatingInput"
@ -198,6 +206,9 @@ export default {
disabledButton() { disabledButton() {
return this.dbConfig.type === undefined || this.info.runningSetup; return this.dbConfig.type === undefined || this.info.runningSetup;
}, },
isProvidedMariaDBSocket() {
return this.info.isEnabledMariaDBSocket;
},
}, },
async mounted() { async mounted() {
let res = await axios.get("/setup-database-info"); let res = await axios.get("/setup-database-info");