diff --git a/apps/dokploy/components/shared/update-database-password.tsx b/apps/dokploy/components/shared/update-database-password.tsx
index 978375fd0..b22dbae7c 100644
--- a/apps/dokploy/components/shared/update-database-password.tsx
+++ b/apps/dokploy/components/shared/update-database-password.tsx
@@ -24,9 +24,17 @@ import {
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
+const DATABASE_PASSWORD_REGEX = /^[a-zA-Z0-9@#%^&*()_+\-=[\]{}|;:,.<>?~`]*$/;
+
const updatePasswordSchema = z
.object({
- password: z.string().min(1, "Password is required"),
+ password: z
+ .string()
+ .min(1, "Password is required")
+ .regex(DATABASE_PASSWORD_REGEX, {
+ message:
+ "Password contains invalid characters. Please avoid: $ ! ' \" \\ / and space characters",
+ }),
confirmPassword: z.string().min(1, "Please confirm the password"),
})
.refine((data) => data.password === data.confirmPassword, {
@@ -63,15 +71,12 @@ export const UpdateDatabasePassword = ({
setIsOpen(false);
} catch (e) {
const raw = e instanceof Error ? e.message : "Error updating password";
- const noContainer = raw.match(/No running container found for \S+/);
- if (noContainer) {
+ if (/No running container found/i.test(raw)) {
setError(
"The database container is not running. Please start the service before changing the password.",
);
} else {
- setError(
- "Error updating password. Please check that the container is running and try again.",
- );
+ setError(raw);
}
} finally {
setIsPending(false);
@@ -101,7 +106,7 @@ export const UpdateDatabasePassword = ({
{error && {error}}
-
+
This will change the {label.toLowerCase()} both in the running
database container and in Dokploy. The container must be running for
this operation to succeed.
diff --git a/apps/dokploy/server/api/routers/mariadb.ts b/apps/dokploy/server/api/routers/mariadb.ts
index 8a9f726e5..c049cffcb 100644
--- a/apps/dokploy/server/api/routers/mariadb.ts
+++ b/apps/dokploy/server/api/routers/mariadb.ts
@@ -43,6 +43,8 @@ import {
apiSaveEnvironmentVariablesMariaDB,
apiSaveExternalPortMariaDB,
apiUpdateMariaDB,
+ DATABASE_PASSWORD_MESSAGE,
+ DATABASE_PASSWORD_REGEX,
environments,
mariadb as mariadbTable,
projects,
@@ -375,7 +377,12 @@ export const mariadbRouter = createTRPCRouter({
.input(
z.object({
mariadbId: z.string().min(1),
- password: z.string().min(1),
+ password: z
+ .string()
+ .min(1)
+ .regex(DATABASE_PASSWORD_REGEX, {
+ message: DATABASE_PASSWORD_MESSAGE,
+ }),
type: z.enum(["user", "root"]).default("user"),
}),
)
diff --git a/apps/dokploy/server/api/routers/mongo.ts b/apps/dokploy/server/api/routers/mongo.ts
index df91ec769..fd2165445 100644
--- a/apps/dokploy/server/api/routers/mongo.ts
+++ b/apps/dokploy/server/api/routers/mongo.ts
@@ -42,6 +42,8 @@ import {
apiSaveEnvironmentVariablesMongo,
apiSaveExternalPortMongo,
apiUpdateMongo,
+ DATABASE_PASSWORD_MESSAGE,
+ DATABASE_PASSWORD_REGEX,
environments,
mongo as mongoTable,
projects,
@@ -397,7 +399,12 @@ export const mongoRouter = createTRPCRouter({
.input(
z.object({
mongoId: z.string().min(1),
- password: z.string().min(1),
+ password: z
+ .string()
+ .min(1)
+ .regex(DATABASE_PASSWORD_REGEX, {
+ message: DATABASE_PASSWORD_MESSAGE,
+ }),
}),
)
.mutation(async ({ input, ctx }) => {
diff --git a/apps/dokploy/server/api/routers/mysql.ts b/apps/dokploy/server/api/routers/mysql.ts
index b53af7521..286705612 100644
--- a/apps/dokploy/server/api/routers/mysql.ts
+++ b/apps/dokploy/server/api/routers/mysql.ts
@@ -42,6 +42,8 @@ import {
apiSaveEnvironmentVariablesMySql,
apiSaveExternalPortMySql,
apiUpdateMySql,
+ DATABASE_PASSWORD_MESSAGE,
+ DATABASE_PASSWORD_REGEX,
environments,
mysql as mysqlTable,
projects,
@@ -394,7 +396,12 @@ export const mysqlRouter = createTRPCRouter({
.input(
z.object({
mysqlId: z.string().min(1),
- password: z.string().min(1),
+ password: z
+ .string()
+ .min(1)
+ .regex(DATABASE_PASSWORD_REGEX, {
+ message: DATABASE_PASSWORD_MESSAGE,
+ }),
type: z.enum(["user", "root"]).default("user"),
}),
)
diff --git a/apps/dokploy/server/api/routers/postgres.ts b/apps/dokploy/server/api/routers/postgres.ts
index 438363915..0cb7a3812 100644
--- a/apps/dokploy/server/api/routers/postgres.ts
+++ b/apps/dokploy/server/api/routers/postgres.ts
@@ -43,6 +43,8 @@ import {
apiSaveEnvironmentVariablesPostgres,
apiSaveExternalPortPostgres,
apiUpdatePostgres,
+ DATABASE_PASSWORD_MESSAGE,
+ DATABASE_PASSWORD_REGEX,
environments,
postgres as postgresTable,
projects,
@@ -403,7 +405,12 @@ export const postgresRouter = createTRPCRouter({
.input(
z.object({
postgresId: z.string().min(1),
- password: z.string().min(1),
+ password: z
+ .string()
+ .min(1)
+ .regex(DATABASE_PASSWORD_REGEX, {
+ message: DATABASE_PASSWORD_MESSAGE,
+ }),
}),
)
.mutation(async ({ input, ctx }) => {
diff --git a/apps/dokploy/server/api/routers/redis.ts b/apps/dokploy/server/api/routers/redis.ts
index 19c1ab277..3d8ecf674 100644
--- a/apps/dokploy/server/api/routers/redis.ts
+++ b/apps/dokploy/server/api/routers/redis.ts
@@ -41,6 +41,8 @@ import {
apiSaveEnvironmentVariablesRedis,
apiSaveExternalPortRedis,
apiUpdateRedis,
+ DATABASE_PASSWORD_MESSAGE,
+ DATABASE_PASSWORD_REGEX,
environments,
projects,
redis as redisTable,
@@ -384,7 +386,12 @@ export const redisRouter = createTRPCRouter({
.input(
z.object({
redisId: z.string().min(1),
- password: z.string().min(1),
+ password: z
+ .string()
+ .min(1)
+ .regex(DATABASE_PASSWORD_REGEX, {
+ message: DATABASE_PASSWORD_MESSAGE,
+ }),
}),
)
.mutation(async ({ input, ctx }) => {
diff --git a/packages/server/src/db/schema/libsql.ts b/packages/server/src/db/schema/libsql.ts
index 770ed2355..8245b95f4 100644
--- a/packages/server/src/db/schema/libsql.ts
+++ b/packages/server/src/db/schema/libsql.ts
@@ -34,7 +34,11 @@ import {
type UpdateConfigSwarm,
UpdateConfigSwarmSchema,
} from "./shared";
-import { generateAppName } from "./utils";
+import {
+ DATABASE_PASSWORD_MESSAGE,
+ DATABASE_PASSWORD_REGEX,
+ generateAppName,
+} from "./utils";
export const libsql = pgTable("libsql", {
libsqlId: text("libsqlId")
@@ -111,9 +115,8 @@ const createSchema = createInsertSchema(libsql, {
databaseUser: z.string().min(1),
databasePassword: z
.string()
- .regex(/^[a-zA-Z0-9@#%^&*()_+\-=[\]{}|;:,.<>?~`]*$/, {
- message:
- "Password contains invalid characters. Please avoid: $ ! ' \" \\ / and space characters for database compatibility",
+ .regex(DATABASE_PASSWORD_REGEX, {
+ message: DATABASE_PASSWORD_MESSAGE,
}),
sqldNode: z.enum(sqldNode.enumValues),
sqldPrimaryUrl: z.string().nullable(),
diff --git a/packages/server/src/db/schema/mariadb.ts b/packages/server/src/db/schema/mariadb.ts
index 2659c2978..b3ff29ada 100644
--- a/packages/server/src/db/schema/mariadb.ts
+++ b/packages/server/src/db/schema/mariadb.ts
@@ -28,7 +28,13 @@ import {
type UpdateConfigSwarm,
UpdateConfigSwarmSchema,
} from "./shared";
-import { APP_NAME_MESSAGE, APP_NAME_REGEX, generateAppName } from "./utils";
+import {
+ APP_NAME_MESSAGE,
+ APP_NAME_REGEX,
+ DATABASE_PASSWORD_MESSAGE,
+ DATABASE_PASSWORD_REGEX,
+ generateAppName,
+} from "./utils";
export const mariadb = pgTable("mariadb", {
mariadbId: text("mariadbId")
@@ -110,15 +116,13 @@ const createSchema = createInsertSchema(mariadb, {
databaseUser: z.string().min(1),
databasePassword: z
.string()
- .regex(/^[a-zA-Z0-9@#%^&*()_+\-=[\]{}|;:,.<>?~`]*$/, {
- message:
- "Password contains invalid characters. Please avoid: $ ! ' \" \\ / and space characters for database compatibility",
+ .regex(DATABASE_PASSWORD_REGEX, {
+ message: DATABASE_PASSWORD_MESSAGE,
}),
databaseRootPassword: z
.string()
- .regex(/^[a-zA-Z0-9@#%^&*()_+\-=[\]{}|;:,.<>?~`]*$/, {
- message:
- "Password contains invalid characters. Please avoid: $ ! ' \" \\ / and space characters for database compatibility",
+ .regex(DATABASE_PASSWORD_REGEX, {
+ message: DATABASE_PASSWORD_MESSAGE,
})
.optional(),
dockerImage: z.string().default("mariadb:6"),
diff --git a/packages/server/src/db/schema/mongo.ts b/packages/server/src/db/schema/mongo.ts
index 4599cedb2..af9d5b12f 100644
--- a/packages/server/src/db/schema/mongo.ts
+++ b/packages/server/src/db/schema/mongo.ts
@@ -35,7 +35,13 @@ import {
type UpdateConfigSwarm,
UpdateConfigSwarmSchema,
} from "./shared";
-import { APP_NAME_MESSAGE, APP_NAME_REGEX, generateAppName } from "./utils";
+import {
+ APP_NAME_MESSAGE,
+ APP_NAME_REGEX,
+ DATABASE_PASSWORD_MESSAGE,
+ DATABASE_PASSWORD_REGEX,
+ generateAppName,
+} from "./utils";
export const mongo = pgTable("mongo", {
mongoId: text("mongoId")
@@ -112,9 +118,8 @@ const createSchema = createInsertSchema(mongo, {
name: z.string().min(1),
databasePassword: z
.string()
- .regex(/^[a-zA-Z0-9@#%^&*()_+\-=[\]{}|;:,.<>?~`]*$/, {
- message:
- "Password contains invalid characters. Please avoid: $ ! ' \" \\ / and space characters for database compatibility",
+ .regex(DATABASE_PASSWORD_REGEX, {
+ message: DATABASE_PASSWORD_MESSAGE,
}),
databaseUser: z.string().min(1),
dockerImage: z.string().default("mongo:15"),
diff --git a/packages/server/src/db/schema/mysql.ts b/packages/server/src/db/schema/mysql.ts
index 90b38e6fa..618a78b4f 100644
--- a/packages/server/src/db/schema/mysql.ts
+++ b/packages/server/src/db/schema/mysql.ts
@@ -28,7 +28,13 @@ import {
type UpdateConfigSwarm,
UpdateConfigSwarmSchema,
} from "./shared";
-import { APP_NAME_MESSAGE, APP_NAME_REGEX, generateAppName } from "./utils";
+import {
+ APP_NAME_MESSAGE,
+ APP_NAME_REGEX,
+ DATABASE_PASSWORD_MESSAGE,
+ DATABASE_PASSWORD_REGEX,
+ generateAppName,
+} from "./utils";
export const mysql = pgTable("mysql", {
mysqlId: text("mysqlId")
@@ -108,15 +114,13 @@ const createSchema = createInsertSchema(mysql, {
databaseUser: z.string().min(1),
databasePassword: z
.string()
- .regex(/^[a-zA-Z0-9@#%^&*()_+\-=[\]{}|;:,.<>?~`]*$/, {
- message:
- "Password contains invalid characters. Please avoid: $ ! ' \" \\ / and space characters for database compatibility",
+ .regex(DATABASE_PASSWORD_REGEX, {
+ message: DATABASE_PASSWORD_MESSAGE,
}),
databaseRootPassword: z
.string()
- .regex(/^[a-zA-Z0-9@#%^&*()_+\-=[\]{}|;:,.<>?~`]*$/, {
- message:
- "Password contains invalid characters. Please avoid: $ ! ' \" \\ / and space characters for database compatibility",
+ .regex(DATABASE_PASSWORD_REGEX, {
+ message: DATABASE_PASSWORD_MESSAGE,
})
.optional(),
dockerImage: z.string().default("mysql:8"),
diff --git a/packages/server/src/db/schema/postgres.ts b/packages/server/src/db/schema/postgres.ts
index 5cb3015ce..13d35ddef 100644
--- a/packages/server/src/db/schema/postgres.ts
+++ b/packages/server/src/db/schema/postgres.ts
@@ -28,7 +28,13 @@ import {
type UpdateConfigSwarm,
UpdateConfigSwarmSchema,
} from "./shared";
-import { APP_NAME_MESSAGE, APP_NAME_REGEX, generateAppName } from "./utils";
+import {
+ APP_NAME_MESSAGE,
+ APP_NAME_REGEX,
+ DATABASE_PASSWORD_MESSAGE,
+ DATABASE_PASSWORD_REGEX,
+ generateAppName,
+} from "./utils";
export const postgres = pgTable("postgres", {
postgresId: text("postgresId")
@@ -105,9 +111,8 @@ const createSchema = createInsertSchema(postgres, {
.optional(),
databasePassword: z
.string()
- .regex(/^[a-zA-Z0-9@#%^&*()_+\-=[\]{}|;:,.<>?~`]*$/, {
- message:
- "Password contains invalid characters. Please avoid: $ ! ' \" \\ / and space characters for database compatibility",
+ .regex(DATABASE_PASSWORD_REGEX, {
+ message: DATABASE_PASSWORD_MESSAGE,
}),
databaseName: z.string().min(1),
databaseUser: z.string().min(1),
diff --git a/packages/server/src/db/schema/utils.ts b/packages/server/src/db/schema/utils.ts
index 811d3f767..30babea6d 100644
--- a/packages/server/src/db/schema/utils.ts
+++ b/packages/server/src/db/schema/utils.ts
@@ -12,6 +12,13 @@ export const APP_NAME_REGEX = /^[a-zA-Z0-9._-]+$/;
export const APP_NAME_MESSAGE =
"App name can only contain letters, numbers, dots, underscores and hyphens";
+/** Database password: blocks shell-dangerous characters like $ ! ' " \ / and spaces. */
+export const DATABASE_PASSWORD_REGEX =
+ /^[a-zA-Z0-9@#%^&*()_+\-=[\]{}|;:,.<>?~`]*$/;
+
+export const DATABASE_PASSWORD_MESSAGE =
+ "Password contains invalid characters. Please avoid: $ ! ' \" \\ / and space characters for database compatibility";
+
export const generateAppName = (type: string) => {
const verb = faker.hacker.verb().replace(/ /g, "-");
const adjective = faker.hacker.adjective().replace(/ /g, "-");