From 624eedd74d9f384575d9614667769a9b0e49410b Mon Sep 17 00:00:00 2001
From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com>
Date: Sat, 8 Mar 2025 20:12:28 -0600
Subject: [PATCH] feat(databases): add database rebuild functionality
- Implement RebuildDatabase component for all database types
- Create ShowDatabaseAdvancedSettings component to consolidate advanced settings
- Add rebuild API endpoints for Postgres, MySQL, MariaDB, MongoDB, and Redis
- Implement server-side database rebuild utility with volume and service removal
- Enhance database management with a dangerous zone for complete database reset
---
.../dashboard/shared/rebuild-database.tsx | 116 ++++++++++++++++++
.../show-database-advanced-settings.tsx | 20 +++
.../services/mariadb/[mariadbId].tsx | 13 +-
.../[projectId]/services/mongo/[mongoId].tsx | 10 +-
.../[projectId]/services/mysql/[mysqlId].tsx | 37 +-----
.../services/postgres/[postgresId].tsx | 37 +-----
.../[projectId]/services/redis/[redisId].tsx | 10 +-
apps/dokploy/server/api/routers/mariadb.ts | 17 ++-
apps/dokploy/server/api/routers/mongo.ts | 18 ++-
apps/dokploy/server/api/routers/mysql.ts | 17 +++
apps/dokploy/server/api/routers/postgres.ts | 20 ++-
apps/dokploy/server/api/routers/redis.ts | 17 ++-
packages/server/src/db/schema/mariadb.ts | 6 +
packages/server/src/db/schema/mongo.ts | 6 +
packages/server/src/db/schema/mysql.ts | 6 +
packages/server/src/db/schema/postgres.ts | 6 +
packages/server/src/db/schema/redis.ts | 6 +
packages/server/src/index.ts | 2 +-
.../server/src/utils/databases/rebuild.ts | 99 +++++++++++++++
19 files changed, 370 insertions(+), 93 deletions(-)
create mode 100644 apps/dokploy/components/dashboard/shared/rebuild-database.tsx
create mode 100644 apps/dokploy/components/dashboard/shared/show-database-advanced-settings.tsx
create mode 100644 packages/server/src/utils/databases/rebuild.ts
diff --git a/apps/dokploy/components/dashboard/shared/rebuild-database.tsx b/apps/dokploy/components/dashboard/shared/rebuild-database.tsx
new file mode 100644
index 00000000..15f08cdd
--- /dev/null
+++ b/apps/dokploy/components/dashboard/shared/rebuild-database.tsx
@@ -0,0 +1,116 @@
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+ AlertDialogTrigger,
+} from "@/components/ui/alert-dialog";
+import { Button } from "@/components/ui/button";
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
+import { api } from "@/utils/api";
+import { DatabaseIcon, AlertTriangle } from "lucide-react";
+import { toast } from "sonner";
+
+interface Props {
+ id: string;
+ type: "postgres" | "mysql" | "mariadb" | "mongo" | "redis";
+}
+
+export const RebuildDatabase = ({ id, type }: Props) => {
+ const utils = api.useUtils();
+
+ const mutationMap = {
+ postgres: () => api.postgres.rebuild.useMutation(),
+ mysql: () => api.mysql.rebuild.useMutation(),
+ mariadb: () => api.mariadb.rebuild.useMutation(),
+ mongo: () => api.mongo.rebuild.useMutation(),
+ redis: () => api.redis.rebuild.useMutation(),
+ };
+
+ const { mutateAsync, isLoading } = mutationMap[type]();
+
+ const handleRebuild = async () => {
+ try {
+ await mutateAsync({
+ postgresId: type === "postgres" ? id : "",
+ mysqlId: type === "mysql" ? id : "",
+ mariadbId: type === "mariadb" ? id : "",
+ mongoId: type === "mongo" ? id : "",
+ redisId: type === "redis" ? id : "",
+ });
+ toast.success("Database rebuilt successfully");
+ await utils.invalidate();
+ } catch (error) {
+ toast.error("Error rebuilding database", {
+ description: error instanceof Error ? error.message : "Unknown error",
+ });
+ }
+ };
+
+ return (
+
+
+
+
+ Danger Zone
+
+
+
+
+
+
Rebuild Database
+
+ This action will completely reset your database to its initial
+ state. All data, tables, and configurations will be removed.
+
+
+
+
+
+
+
+
+
+
+ Are you absolutely sure?
+
+
+ This action will:
+
+ - Stop the current database service
+ - Delete all existing data and volumes
+ - Reset to the default configuration
+ - Restart the service with a clean state
+
+
+ This action cannot be undone.
+
+
+
+
+ Cancel
+
+ {isLoading ? "Rebuilding..." : "Yes, rebuild database"}
+
+
+
+
+
+
+
+ );
+};
diff --git a/apps/dokploy/components/dashboard/shared/show-database-advanced-settings.tsx b/apps/dokploy/components/dashboard/shared/show-database-advanced-settings.tsx
new file mode 100644
index 00000000..c6c4c414
--- /dev/null
+++ b/apps/dokploy/components/dashboard/shared/show-database-advanced-settings.tsx
@@ -0,0 +1,20 @@
+import { ShowCustomCommand } from "@/components/dashboard/postgres/advanced/show-custom-command";
+import { ShowResources } from "@/components/dashboard/application/advanced/show-resources";
+import { ShowVolumes } from "@/components/dashboard/application/advanced/volumes/show-volumes";
+import { RebuildDatabase } from "./rebuild-database";
+
+interface Props {
+ id: string;
+ type: "postgres" | "mysql" | "mariadb" | "mongo" | "redis";
+}
+
+export const ShowDatabaseAdvancedSettings = ({ id, type }: Props) => {
+ return (
+
+
+
+
+
+
+ );
+};
diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/services/mariadb/[mariadbId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/services/mariadb/[mariadbId].tsx
index d3930bbc..43803f1d 100644
--- a/apps/dokploy/pages/dashboard/project/[projectId]/services/mariadb/[mariadbId].tsx
+++ b/apps/dokploy/pages/dashboard/project/[projectId]/services/mariadb/[mariadbId].tsx
@@ -1,5 +1,3 @@
-import { ShowResources } from "@/components/dashboard/application/advanced/show-resources";
-import { ShowVolumes } from "@/components/dashboard/application/advanced/volumes/show-volumes";
import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment";
import { ShowDockerLogs } from "@/components/dashboard/application/logs/show";
import { DeleteService } from "@/components/dashboard/compose/delete-service";
@@ -10,7 +8,7 @@ import { ShowInternalMariadbCredentials } from "@/components/dashboard/mariadb/g
import { UpdateMariadb } from "@/components/dashboard/mariadb/update-mariadb";
import { ContainerFreeMonitoring } from "@/components/dashboard/monitoring/free/container/show-free-container-monitoring";
import { ContainerPaidMonitoring } from "@/components/dashboard/monitoring/paid/container/show-paid-container-monitoring";
-import { ShowCustomCommand } from "@/components/dashboard/postgres/advanced/show-custom-command";
+import { ShowDatabaseAdvancedSettings } from "@/components/dashboard/shared/show-database-advanced-settings";
import { MariadbIcon } from "@/components/icons/data-tools-icons";
import { ProjectLayout } from "@/components/layouts/project-layout";
import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
@@ -278,11 +276,10 @@ const Mariadb = (
diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/services/mongo/[mongoId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/services/mongo/[mongoId].tsx
index 4bc1d0ce..1df3c390 100644
--- a/apps/dokploy/pages/dashboard/project/[projectId]/services/mongo/[mongoId].tsx
+++ b/apps/dokploy/pages/dashboard/project/[projectId]/services/mongo/[mongoId].tsx
@@ -1,5 +1,3 @@
-import { ShowResources } from "@/components/dashboard/application/advanced/show-resources";
-import { ShowVolumes } from "@/components/dashboard/application/advanced/volumes/show-volumes";
import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment";
import { ShowDockerLogs } from "@/components/dashboard/application/logs/show";
import { DeleteService } from "@/components/dashboard/compose/delete-service";
@@ -10,7 +8,7 @@ import { ShowInternalMongoCredentials } from "@/components/dashboard/mongo/gener
import { UpdateMongo } from "@/components/dashboard/mongo/update-mongo";
import { ContainerFreeMonitoring } from "@/components/dashboard/monitoring/free/container/show-free-container-monitoring";
import { ContainerPaidMonitoring } from "@/components/dashboard/monitoring/paid/container/show-paid-container-monitoring";
-import { ShowCustomCommand } from "@/components/dashboard/postgres/advanced/show-custom-command";
+import { ShowDatabaseAdvancedSettings } from "@/components/dashboard/shared/show-database-advanced-settings";
import { MongodbIcon } from "@/components/icons/data-tools-icons";
import { ProjectLayout } from "@/components/layouts/project-layout";
import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
@@ -279,11 +277,7 @@ const Mongo = (
diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/services/mysql/[mysqlId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/services/mysql/[mysqlId].tsx
index 5440fc5e..7bed196d 100644
--- a/apps/dokploy/pages/dashboard/project/[projectId]/services/mysql/[mysqlId].tsx
+++ b/apps/dokploy/pages/dashboard/project/[projectId]/services/mysql/[mysqlId].tsx
@@ -1,5 +1,3 @@
-import { ShowResources } from "@/components/dashboard/application/advanced/show-resources";
-import { ShowVolumes } from "@/components/dashboard/application/advanced/volumes/show-volumes";
import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment";
import { ShowDockerLogs } from "@/components/dashboard/application/logs/show";
import { DeleteService } from "@/components/dashboard/compose/delete-service";
@@ -10,7 +8,7 @@ import { ShowExternalMysqlCredentials } from "@/components/dashboard/mysql/gener
import { ShowGeneralMysql } from "@/components/dashboard/mysql/general/show-general-mysql";
import { ShowInternalMysqlCredentials } from "@/components/dashboard/mysql/general/show-internal-mysql-credentials";
import { UpdateMysql } from "@/components/dashboard/mysql/update-mysql";
-import { ShowCustomCommand } from "@/components/dashboard/postgres/advanced/show-custom-command";
+import { ShowDatabaseAdvancedSettings } from "@/components/dashboard/shared/show-database-advanced-settings";
import { MysqlIcon } from "@/components/icons/data-tools-icons";
import { ProjectLayout } from "@/components/layouts/project-layout";
import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
@@ -236,33 +234,9 @@ const MySql = (
/>
) : (
<>
- {/* {monitoring?.enabledFeatures && (
-
-
-
-
- )}
-
- {toggleMonitoring ? (
-
- ) : (
- */}
- {/*
*/}
- {/* )} */}
>
)}
@@ -283,11 +257,10 @@ const MySql = (
diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/services/postgres/[postgresId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/services/postgres/[postgresId].tsx
index 635f8b4e..75337464 100644
--- a/apps/dokploy/pages/dashboard/project/[projectId]/services/postgres/[postgresId].tsx
+++ b/apps/dokploy/pages/dashboard/project/[projectId]/services/postgres/[postgresId].tsx
@@ -1,12 +1,9 @@
-import { ShowResources } from "@/components/dashboard/application/advanced/show-resources";
-import { ShowVolumes } from "@/components/dashboard/application/advanced/volumes/show-volumes";
import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment";
import { ShowDockerLogs } from "@/components/dashboard/application/logs/show";
import { DeleteService } from "@/components/dashboard/compose/delete-service";
import { ShowBackups } from "@/components/dashboard/database/backups/show-backups";
import { ContainerFreeMonitoring } from "@/components/dashboard/monitoring/free/container/show-free-container-monitoring";
import { ContainerPaidMonitoring } from "@/components/dashboard/monitoring/paid/container/show-paid-container-monitoring";
-import { ShowCustomCommand } from "@/components/dashboard/postgres/advanced/show-custom-command";
import { ShowExternalPostgresCredentials } from "@/components/dashboard/postgres/general/show-external-postgres-credentials";
import { ShowGeneralPostgres } from "@/components/dashboard/postgres/general/show-general-postgres";
import { ShowInternalPostgresCredentials } from "@/components/dashboard/postgres/general/show-internal-postgres-credentials";
@@ -15,6 +12,7 @@ import { PostgresqlIcon } from "@/components/icons/data-tools-icons";
import { ProjectLayout } from "@/components/layouts/project-layout";
import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
import { StatusTooltip } from "@/components/shared/status-tooltip";
+import { ShowDatabaseAdvancedSettings } from "@/components/dashboard/shared/show-database-advanced-settings";
import { Badge } from "@/components/ui/badge";
import {
Card,
@@ -235,33 +233,9 @@ const Postgresql = (
/>
) : (
<>
- {/* {monitoring?.enabledFeatures && (
-
-
-
-
- )}
-
- {toggleMonitoring ? (
-
- ) : (
- */}
- {/*
*/}
- {/* )} */}
>
)}
@@ -282,11 +256,10 @@ const Postgresql = (
diff --git a/apps/dokploy/pages/dashboard/project/[projectId]/services/redis/[redisId].tsx b/apps/dokploy/pages/dashboard/project/[projectId]/services/redis/[redisId].tsx
index c7084d52..7c624ef0 100644
--- a/apps/dokploy/pages/dashboard/project/[projectId]/services/redis/[redisId].tsx
+++ b/apps/dokploy/pages/dashboard/project/[projectId]/services/redis/[redisId].tsx
@@ -1,15 +1,13 @@
-import { ShowResources } from "@/components/dashboard/application/advanced/show-resources";
-import { ShowVolumes } from "@/components/dashboard/application/advanced/volumes/show-volumes";
import { ShowEnvironment } from "@/components/dashboard/application/environment/show-enviroment";
import { ShowDockerLogs } from "@/components/dashboard/application/logs/show";
import { DeleteService } from "@/components/dashboard/compose/delete-service";
import { ContainerFreeMonitoring } from "@/components/dashboard/monitoring/free/container/show-free-container-monitoring";
import { ContainerPaidMonitoring } from "@/components/dashboard/monitoring/paid/container/show-paid-container-monitoring";
-import { ShowCustomCommand } from "@/components/dashboard/postgres/advanced/show-custom-command";
import { ShowExternalRedisCredentials } from "@/components/dashboard/redis/general/show-external-redis-credentials";
import { ShowGeneralRedis } from "@/components/dashboard/redis/general/show-general-redis";
import { ShowInternalRedisCredentials } from "@/components/dashboard/redis/general/show-internal-redis-credentials";
import { UpdateRedis } from "@/components/dashboard/redis/update-redis";
+import { ShowDatabaseAdvancedSettings } from "@/components/dashboard/shared/show-database-advanced-settings";
import { RedisIcon } from "@/components/icons/data-tools-icons";
import { ProjectLayout } from "@/components/layouts/project-layout";
import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar";
@@ -272,11 +270,7 @@ const Redis = (
diff --git a/apps/dokploy/server/api/routers/mariadb.ts b/apps/dokploy/server/api/routers/mariadb.ts
index 21794bc7..c3ba8c13 100644
--- a/apps/dokploy/server/api/routers/mariadb.ts
+++ b/apps/dokploy/server/api/routers/mariadb.ts
@@ -8,6 +8,7 @@ import {
apiSaveEnvironmentVariablesMariaDB,
apiSaveExternalPortMariaDB,
apiUpdateMariaDB,
+ apiRebuildMariadb,
mariadb as mariadbTable,
} from "@/server/db/schema";
import { cancelJobs } from "@/server/utils/backup";
@@ -34,7 +35,7 @@ import { observable } from "@trpc/server/observable";
import { z } from "zod";
import { eq } from "drizzle-orm";
import { db } from "@/server/db";
-
+import { rebuildDatabase } from "@dokploy/server";
export const mariadbRouter = createTRPCRouter({
create: protectedProcedure
.input(apiCreateMariaDB)
@@ -369,4 +370,18 @@ export const mariadbRouter = createTRPCRouter({
return updatedMariadb;
}),
+ rebuild: protectedProcedure
+ .input(apiRebuildMariadb)
+ .mutation(async ({ input, ctx }) => {
+ const mariadb = await findMariadbById(input.mariadbId);
+ if (mariadb.project.organizationId !== ctx.session.activeOrganizationId) {
+ throw new TRPCError({
+ code: "UNAUTHORIZED",
+ message: "You are not authorized to rebuild this MariaDB database",
+ });
+ }
+
+ await rebuildDatabase(mariadb.mariadbId, "mariadb");
+ return true;
+ }),
});
diff --git a/apps/dokploy/server/api/routers/mongo.ts b/apps/dokploy/server/api/routers/mongo.ts
index 4301e407..de6c03e5 100644
--- a/apps/dokploy/server/api/routers/mongo.ts
+++ b/apps/dokploy/server/api/routers/mongo.ts
@@ -4,6 +4,7 @@ import {
apiCreateMongo,
apiDeployMongo,
apiFindOneMongo,
+ apiRebuildMongo,
apiResetMongo,
apiSaveEnvironmentVariablesMongo,
apiSaveExternalPortMongo,
@@ -34,7 +35,7 @@ import { observable } from "@trpc/server/observable";
import { z } from "zod";
import { eq } from "drizzle-orm";
import { db } from "@/server/db";
-
+import { rebuildDatabase } from "@dokploy/server";
export const mongoRouter = createTRPCRouter({
create: protectedProcedure
.input(apiCreateMongo)
@@ -383,4 +384,19 @@ export const mongoRouter = createTRPCRouter({
return updatedMongo;
}),
+ rebuild: protectedProcedure
+ .input(apiRebuildMongo)
+ .mutation(async ({ input, ctx }) => {
+ const mongo = await findMongoById(input.mongoId);
+ if (mongo.project.organizationId !== ctx.session.activeOrganizationId) {
+ throw new TRPCError({
+ code: "UNAUTHORIZED",
+ message: "You are not authorized to rebuild this MongoDB database",
+ });
+ }
+
+ await rebuildDatabase(mongo.mongoId, "mongo");
+
+ return true;
+ }),
});
diff --git a/apps/dokploy/server/api/routers/mysql.ts b/apps/dokploy/server/api/routers/mysql.ts
index 3fa1eb92..0c66b71c 100644
--- a/apps/dokploy/server/api/routers/mysql.ts
+++ b/apps/dokploy/server/api/routers/mysql.ts
@@ -4,6 +4,7 @@ import {
apiCreateMySql,
apiDeployMySql,
apiFindOneMySql,
+ apiRebuildMysql,
apiResetMysql,
apiSaveEnvironmentVariablesMySql,
apiSaveExternalPortMySql,
@@ -24,6 +25,7 @@ import {
findBackupsByDbId,
findMySqlById,
findProjectById,
+ rebuildDatabase,
removeMySqlById,
removeService,
startService,
@@ -379,4 +381,19 @@ export const mysqlRouter = createTRPCRouter({
return updatedMysql;
}),
+ rebuild: protectedProcedure
+ .input(apiRebuildMysql)
+ .mutation(async ({ input, ctx }) => {
+ const mysql = await findMySqlById(input.mysqlId);
+ if (mysql.project.organizationId !== ctx.session.activeOrganizationId) {
+ throw new TRPCError({
+ code: "UNAUTHORIZED",
+ message: "You are not authorized to rebuild this MySQL database",
+ });
+ }
+
+ await rebuildDatabase(mysql.mysqlId, "mysql");
+
+ return true;
+ }),
});
diff --git a/apps/dokploy/server/api/routers/postgres.ts b/apps/dokploy/server/api/routers/postgres.ts
index b3cd5b82..8159447f 100644
--- a/apps/dokploy/server/api/routers/postgres.ts
+++ b/apps/dokploy/server/api/routers/postgres.ts
@@ -4,6 +4,7 @@ import {
apiCreatePostgres,
apiDeployPostgres,
apiFindOnePostgres,
+ apiRebuildPostgres,
apiResetPostgres,
apiSaveEnvironmentVariablesPostgres,
apiSaveExternalPortPostgres,
@@ -21,6 +22,7 @@ import {
findBackupsByDbId,
findPostgresById,
findProjectById,
+ rebuildDatabase,
removePostgresById,
removeService,
startService,
@@ -34,7 +36,6 @@ import { observable } from "@trpc/server/observable";
import { z } from "zod";
import { eq } from "drizzle-orm";
import { db } from "@/server/db";
-
export const postgresRouter = createTRPCRouter({
create: protectedProcedure
.input(apiCreatePostgres)
@@ -401,4 +402,21 @@ export const postgresRouter = createTRPCRouter({
return updatedPostgres;
}),
+ rebuild: protectedProcedure
+ .input(apiRebuildPostgres)
+ .mutation(async ({ input, ctx }) => {
+ const postgres = await findPostgresById(input.postgresId);
+ if (
+ postgres.project.organizationId !== ctx.session.activeOrganizationId
+ ) {
+ throw new TRPCError({
+ code: "UNAUTHORIZED",
+ message: "You are not authorized to rebuild this Postgres database",
+ });
+ }
+
+ await rebuildDatabase(postgres.postgresId, "postgres");
+
+ return true;
+ }),
});
diff --git a/apps/dokploy/server/api/routers/redis.ts b/apps/dokploy/server/api/routers/redis.ts
index d7d9d78d..c310a6dd 100644
--- a/apps/dokploy/server/api/routers/redis.ts
+++ b/apps/dokploy/server/api/routers/redis.ts
@@ -9,6 +9,7 @@ import {
apiSaveExternalPortRedis,
apiUpdateRedis,
redis as redisTable,
+ apiRebuildRedis,
} from "@/server/db/schema";
import { TRPCError } from "@trpc/server";
@@ -34,7 +35,7 @@ import { observable } from "@trpc/server/observable";
import { eq } from "drizzle-orm";
import { db } from "@/server/db";
import { z } from "zod";
-
+import { rebuildDatabase } from "@dokploy/server";
export const redisRouter = createTRPCRouter({
create: protectedProcedure
.input(apiCreateRedis)
@@ -363,4 +364,18 @@ export const redisRouter = createTRPCRouter({
return updatedRedis;
}),
+ rebuild: protectedProcedure
+ .input(apiRebuildRedis)
+ .mutation(async ({ input, ctx }) => {
+ const redis = await findRedisById(input.redisId);
+ if (redis.project.organizationId !== ctx.session.activeOrganizationId) {
+ throw new TRPCError({
+ code: "UNAUTHORIZED",
+ message: "You are not authorized to rebuild this Redis database",
+ });
+ }
+
+ await rebuildDatabase(redis.redisId, "redis");
+ return true;
+ }),
});
diff --git a/packages/server/src/db/schema/mariadb.ts b/packages/server/src/db/schema/mariadb.ts
index 46357faf..ce10f0f9 100644
--- a/packages/server/src/db/schema/mariadb.ts
+++ b/packages/server/src/db/schema/mariadb.ts
@@ -146,3 +146,9 @@ export const apiUpdateMariaDB = createSchema
mariadbId: z.string().min(1),
})
.omit({ serverId: true });
+
+export const apiRebuildMariadb = createSchema
+ .pick({
+ mariadbId: true,
+ })
+ .required();
diff --git a/packages/server/src/db/schema/mongo.ts b/packages/server/src/db/schema/mongo.ts
index 8515dbff..4eefc022 100644
--- a/packages/server/src/db/schema/mongo.ts
+++ b/packages/server/src/db/schema/mongo.ts
@@ -141,3 +141,9 @@ export const apiResetMongo = createSchema
appName: true,
})
.required();
+
+export const apiRebuildMongo = createSchema
+ .pick({
+ mongoId: true,
+ })
+ .required();
diff --git a/packages/server/src/db/schema/mysql.ts b/packages/server/src/db/schema/mysql.ts
index 2c5cabe8..1610b7f0 100644
--- a/packages/server/src/db/schema/mysql.ts
+++ b/packages/server/src/db/schema/mysql.ts
@@ -144,3 +144,9 @@ export const apiUpdateMySql = createSchema
mysqlId: z.string().min(1),
})
.omit({ serverId: true });
+
+export const apiRebuildMysql = createSchema
+ .pick({
+ mysqlId: true,
+ })
+ .required();
diff --git a/packages/server/src/db/schema/postgres.ts b/packages/server/src/db/schema/postgres.ts
index 213dc2b5..0ea7dcc1 100644
--- a/packages/server/src/db/schema/postgres.ts
+++ b/packages/server/src/db/schema/postgres.ts
@@ -140,3 +140,9 @@ export const apiUpdatePostgres = createSchema
postgresId: z.string().min(1),
})
.omit({ serverId: true });
+
+export const apiRebuildPostgres = createSchema
+ .pick({
+ postgresId: true,
+ })
+ .required();
diff --git a/packages/server/src/db/schema/redis.ts b/packages/server/src/db/schema/redis.ts
index ed8276a5..85c27609 100644
--- a/packages/server/src/db/schema/redis.ts
+++ b/packages/server/src/db/schema/redis.ts
@@ -133,3 +133,9 @@ export const apiUpdateRedis = createSchema
redisId: z.string().min(1),
})
.omit({ serverId: true });
+
+export const apiRebuildRedis = createSchema
+ .pick({
+ redisId: true,
+ })
+ .required();
diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts
index c8337dc2..a4c86ca6 100644
--- a/packages/server/src/index.ts
+++ b/packages/server/src/index.ts
@@ -30,7 +30,7 @@ export * from "./services/github";
export * from "./services/gitlab";
export * from "./services/server";
export * from "./services/application";
-
+export * from "./utils/databases/rebuild";
export * from "./setup/config-paths";
export * from "./setup/postgres-setup";
export * from "./setup/redis-setup";
diff --git a/packages/server/src/utils/databases/rebuild.ts b/packages/server/src/utils/databases/rebuild.ts
new file mode 100644
index 00000000..12c907b7
--- /dev/null
+++ b/packages/server/src/utils/databases/rebuild.ts
@@ -0,0 +1,99 @@
+import { deployPostgres } from "@dokploy/server/services/postgres";
+import { execAsyncRemote } from "../process/execAsync";
+import { execAsync } from "../process/execAsync";
+import { deployMySql } from "@dokploy/server/services/mysql";
+import { deployMariadb } from "@dokploy/server/services/mariadb";
+import { deployMongo } from "@dokploy/server/services/mongo";
+import { deployRedis } from "@dokploy/server/services/redis";
+import { removeService } from "../docker/utils";
+import { db } from "@dokploy/server/db";
+import {
+ postgres,
+ mysql,
+ mariadb,
+ mongo,
+ redis,
+} from "@dokploy/server/db/schema";
+import { eq } from "drizzle-orm";
+
+type DatabaseType = "postgres" | "mysql" | "mariadb" | "mongo" | "redis";
+
+export const rebuildDatabase = async (
+ databaseId: string,
+ type: DatabaseType,
+) => {
+ const database = await findDatabaseById(databaseId, type);
+
+ if (!database) {
+ throw new Error("Database not found");
+ }
+
+ await removeService(database.appName, database.serverId);
+ await new Promise((resolve) => setTimeout(resolve, 6000));
+
+ for (const mount of database.mounts) {
+ if (mount.type === "volume") {
+ const command = `docker volume rm ${mount?.volumeName} --force`;
+ if (database.serverId) {
+ await execAsyncRemote(database.serverId, command);
+ } else {
+ await execAsync(command);
+ }
+ }
+ }
+
+ if (type === "postgres") {
+ await deployPostgres(databaseId);
+ } else if (type === "mysql") {
+ await deployMySql(databaseId);
+ } else if (type === "mariadb") {
+ await deployMariadb(databaseId);
+ } else if (type === "mongo") {
+ await deployMongo(databaseId);
+ } else if (type === "redis") {
+ await deployRedis(databaseId);
+ }
+};
+
+const findDatabaseById = async (databaseId: string, type: DatabaseType) => {
+ if (type === "postgres") {
+ return await db.query.postgres.findFirst({
+ where: eq(postgres.postgresId, databaseId),
+ with: {
+ mounts: true,
+ },
+ });
+ }
+ if (type === "mysql") {
+ return await db.query.mysql.findFirst({
+ where: eq(mysql.mysqlId, databaseId),
+ with: {
+ mounts: true,
+ },
+ });
+ }
+ if (type === "mariadb") {
+ return await db.query.mariadb.findFirst({
+ where: eq(mariadb.mariadbId, databaseId),
+ with: {
+ mounts: true,
+ },
+ });
+ }
+ if (type === "mongo") {
+ return await db.query.mongo.findFirst({
+ where: eq(mongo.mongoId, databaseId),
+ with: {
+ mounts: true,
+ },
+ });
+ }
+ if (type === "redis") {
+ return await db.query.redis.findFirst({
+ where: eq(redis.redisId, databaseId),
+ with: {
+ mounts: true,
+ },
+ });
+ }
+};