From 94c947e288d098b0d54aa5b015d62de96a0699b4 Mon Sep 17 00:00:00 2001 From: vicke4 Date: Thu, 3 Apr 2025 11:41:21 +0530 Subject: [PATCH 01/27] fix(backups): web-server backups auto-deletion --- packages/server/src/utils/backups/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/server/src/utils/backups/index.ts b/packages/server/src/utils/backups/index.ts index b83d8279..e7510def 100644 --- a/packages/server/src/utils/backups/index.ts +++ b/packages/server/src/utils/backups/index.ts @@ -106,8 +106,8 @@ export const keepLatestNBackups = async ( backup.prefix, ); - // --include "*.sql.gz" ensures nothing else other than the db backup files are touched by rclone - const rcloneList = `rclone lsf ${rcloneFlags.join(" ")} --include "*.sql.gz" ${backupFilesPath}`; + // --include "*.sql.gz" or "*.zip" ensures nothing else other than the dokploy backup files are touched by rclone + const rcloneList = `rclone lsf ${rcloneFlags.join(" ")} --include "*${backup.databaseType === "web-server" ? '.zip' : '.sql.gz'}" ${backupFilesPath}`; // when we pipe the above command with this one, we only get the list of files we want to delete const sortAndPickUnwantedBackups = `sort -r | tail -n +$((${backup.keepLatestCount}+1)) | xargs -I{}`; // this command deletes the files From e176def5b67ca74846fccb364a11b7bf2d1b9012 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Thu, 3 Apr 2025 06:12:08 +0000 Subject: [PATCH 02/27] [autofix.ci] apply automated fixes --- packages/server/src/utils/backups/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/utils/backups/index.ts b/packages/server/src/utils/backups/index.ts index e7510def..6c940406 100644 --- a/packages/server/src/utils/backups/index.ts +++ b/packages/server/src/utils/backups/index.ts @@ -107,7 +107,7 @@ export const keepLatestNBackups = async ( ); // --include "*.sql.gz" or "*.zip" ensures nothing else other than the dokploy backup files are touched by rclone - const rcloneList = `rclone lsf ${rcloneFlags.join(" ")} --include "*${backup.databaseType === "web-server" ? '.zip' : '.sql.gz'}" ${backupFilesPath}`; + const rcloneList = `rclone lsf ${rcloneFlags.join(" ")} --include "*${backup.databaseType === "web-server" ? ".zip" : ".sql.gz"}" ${backupFilesPath}`; // when we pipe the above command with this one, we only get the list of files we want to delete const sortAndPickUnwantedBackups = `sort -r | tail -n +$((${backup.keepLatestCount}+1)) | xargs -I{}`; // this command deletes the files From eff2657e70fc76429e15a67e3f433d3c24d27442 Mon Sep 17 00:00:00 2001 From: krokodaws <46326151+krokodaws@users.noreply.github.com> Date: Fri, 4 Apr 2025 19:21:30 +0300 Subject: [PATCH 03/27] fix: resolve incorrect endpoints for database bulk actions (#1626) Update bulk action endpoints for database services: - Use `/api/trpc/redis.start` and `/api/trpc/redis.stop` for Redis - Use `/api/trpc/postgres.start` and `/api/trpc/postgres.stop` for PostgreSQL - Retain `/api/trpc/compose.start` and `/api/trpc/compose.stop` for Docker Compose services Tested with a project including Gitea, Redis, and PostgreSQL. Bulk start/stop operations now function correctly for all service types. Closes #1626 --- .../pages/dashboard/project/[projectId].tsx | 66 ++++++++++++++++++- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/apps/dokploy/pages/dashboard/project/[projectId].tsx b/apps/dokploy/pages/dashboard/project/[projectId].tsx index e3cfce16..6c4ac4bc 100644 --- a/apps/dokploy/pages/dashboard/project/[projectId].tsx +++ b/apps/dokploy/pages/dashboard/project/[projectId].tsx @@ -314,31 +314,43 @@ const Project = ( }; const applicationActions = { + start: api.application.start.useMutation(), + stop: api.application.stop.useMutation(), move: api.application.move.useMutation(), delete: api.application.delete.useMutation(), }; const postgresActions = { + start: api.postgres.start.useMutation(), + stop: api.postgres.stop.useMutation(), move: api.postgres.move.useMutation(), delete: api.postgres.remove.useMutation(), }; const mysqlActions = { + start: api.mysql.start.useMutation(), + stop: api.mysql.stop.useMutation(), move: api.mysql.move.useMutation(), delete: api.mysql.remove.useMutation(), }; const mariadbActions = { + start: api.mariadb.start.useMutation(), + stop: api.mariadb.stop.useMutation(), move: api.mariadb.move.useMutation(), delete: api.mariadb.remove.useMutation(), }; const redisActions = { + start: api.redis.start.useMutation(), + stop: api.redis.stop.useMutation(), move: api.redis.move.useMutation(), delete: api.redis.remove.useMutation(), }; const mongoActions = { + start: api.mongo.start.useMutation(), + stop: api.mongo.stop.useMutation(), move: api.mongo.move.useMutation(), delete: api.mongo.remove.useMutation(), }; @@ -348,7 +360,32 @@ const Project = ( setIsBulkActionLoading(true); for (const serviceId of selectedServices) { try { - await composeActions.start.mutateAsync({ composeId: serviceId }); + const service = filteredServices.find((s) => s.id === serviceId); + if (!service) continue; + + switch (service.type) { + case "application": + await applicationActions.start.mutateAsync({ applicationId: serviceId }); + break; + case "compose": + await composeActions.start.mutateAsync({ composeId: serviceId }); + break; + case "postgres": + await postgresActions.start.mutateAsync({ postgresId: serviceId }); + break; + case "mysql": + await mysqlActions.start.mutateAsync({ mysqlId: serviceId }); + break; + case "mariadb": + await mariadbActions.start.mutateAsync({ mariadbId: serviceId }); + break; + case "redis": + await redisActions.start.mutateAsync({ redisId: serviceId }); + break; + case "mongo": + await mongoActions.start.mutateAsync({ mongoId: serviceId }); + break; + } success++; } catch (_error) { toast.error(`Error starting service ${serviceId}`); @@ -368,7 +405,32 @@ const Project = ( setIsBulkActionLoading(true); for (const serviceId of selectedServices) { try { - await composeActions.stop.mutateAsync({ composeId: serviceId }); + const service = filteredServices.find((s) => s.id === serviceId); + if (!service) continue; + + switch (service.type) { + case "application": + await applicationActions.stop.mutateAsync({ applicationId: serviceId }); + break; + case "compose": + await composeActions.stop.mutateAsync({ composeId: serviceId }); + break; + case "postgres": + await postgresActions.stop.mutateAsync({ postgresId: serviceId }); + break; + case "mysql": + await mysqlActions.stop.mutateAsync({ mysqlId: serviceId }); + break; + case "mariadb": + await mariadbActions.stop.mutateAsync({ mariadbId: serviceId }); + break; + case "redis": + await redisActions.stop.mutateAsync({ redisId: serviceId }); + break; + case "mongo": + await mongoActions.stop.mutateAsync({ mongoId: serviceId }); + break; + } success++; } catch (_error) { toast.error(`Error stopping service ${serviceId}`); From 5863e45c13916845c1b7581faae44c6c1a0b2a1c Mon Sep 17 00:00:00 2001 From: Lorenzo Migliorero Date: Fri, 4 Apr 2025 20:18:56 +0200 Subject: [PATCH 04/27] remove sensitive files on static build --- packages/server/src/utils/builders/static.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/server/src/utils/builders/static.ts b/packages/server/src/utils/builders/static.ts index c46bdf2e..f7fc87ca 100644 --- a/packages/server/src/utils/builders/static.ts +++ b/packages/server/src/utils/builders/static.ts @@ -25,6 +25,12 @@ export const buildStatic = async ( ].join("\n"), ); + createFile( + buildAppDirectory, + ".dockerignore", + [".git", ".env", "Dockerfile", ".dockerignore"].join("\n"), + ); + await buildCustomDocker( { ...application, From cb20950dd9222dba19e3f48404416e4414f7eabb Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sat, 5 Apr 2025 23:03:57 -0600 Subject: [PATCH 05/27] feat(registry): refactor Docker login command execution to use execFileAsync for improved input handling --- apps/dokploy/server/api/routers/registry.ts | 19 +++++++-- .../server/src/utils/process/execAsync.ts | 41 ++++++++++++++++++- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/apps/dokploy/server/api/routers/registry.ts b/apps/dokploy/server/api/routers/registry.ts index a9a6be89..5486f37c 100644 --- a/apps/dokploy/server/api/routers/registry.ts +++ b/apps/dokploy/server/api/routers/registry.ts @@ -10,8 +10,8 @@ import { import { IS_CLOUD, createRegistry, - execAsync, execAsyncRemote, + execFileAsync, findRegistryById, removeRegistry, updateRegistry, @@ -83,7 +83,13 @@ export const registryRouter = createTRPCRouter({ .input(apiTestRegistry) .mutation(async ({ input }) => { try { - const loginCommand = `echo ${input.password} | docker login ${input.registryUrl} --username ${input.username} --password-stdin`; + const args = [ + "login", + input.registryUrl, + "--username", + input.username, + "--password-stdin", + ]; if (IS_CLOUD && !input.serverId) { throw new TRPCError({ @@ -93,9 +99,14 @@ export const registryRouter = createTRPCRouter({ } if (input.serverId && input.serverId !== "none") { - await execAsyncRemote(input.serverId, loginCommand); + await execAsyncRemote( + input.serverId, + `echo ${input.password} | docker ${args.join(" ")}`, + ); } else { - await execAsync(loginCommand); + await execFileAsync("docker", args, { + input: Buffer.from(input.password).toString(), + }); } return true; diff --git a/packages/server/src/utils/process/execAsync.ts b/packages/server/src/utils/process/execAsync.ts index aee1e821..c3e40907 100644 --- a/packages/server/src/utils/process/execAsync.ts +++ b/packages/server/src/utils/process/execAsync.ts @@ -1,9 +1,48 @@ -import { exec } from "node:child_process"; +import { exec, execFile } from "node:child_process"; import util from "node:util"; import { findServerById } from "@dokploy/server/services/server"; import { Client } from "ssh2"; + export const execAsync = util.promisify(exec); +export const execFileAsync = async ( + command: string, + args: string[], + options: { input?: string } = {}, +): Promise<{ stdout: string; stderr: string }> => { + const child = execFile(command, args); + + if (options.input && child.stdin) { + child.stdin.write(options.input); + child.stdin.end(); + } + + return new Promise((resolve, reject) => { + let stdout = ""; + let stderr = ""; + + child.stdout?.on("data", (data) => { + stdout += data.toString(); + }); + + child.stderr?.on("data", (data) => { + stderr += data.toString(); + }); + + child.on("close", (code) => { + if (code === 0) { + resolve({ stdout, stderr }); + } else { + reject( + new Error(`Command failed with code ${code}. Stderr: ${stderr}`), + ); + } + }); + + child.on("error", reject); + }); +}; + export const execAsyncRemote = async ( serverId: string | null, command: string, From 14bc26e065dc572b839c6cbd44b1a6ed26d80613 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sun, 6 Apr 2025 00:07:41 -0600 Subject: [PATCH 06/27] feat(websocket): enhance WebSocket server with request validation and client instantiation - Added request validation to ensure user authentication before establishing WebSocket connections. - Refactored WebSocket client instantiation to simplify connection management. --- apps/dokploy/server/wss/drawer-logs.ts | 14 +++++++++---- apps/dokploy/utils/api.ts | 27 +++++++------------------- 2 files changed, 17 insertions(+), 24 deletions(-) diff --git a/apps/dokploy/server/wss/drawer-logs.ts b/apps/dokploy/server/wss/drawer-logs.ts index dcdeaad7..0202ae52 100644 --- a/apps/dokploy/server/wss/drawer-logs.ts +++ b/apps/dokploy/server/wss/drawer-logs.ts @@ -3,6 +3,7 @@ import { applyWSSHandler } from "@trpc/server/adapters/ws"; import { WebSocketServer } from "ws"; import { appRouter } from "../api/root"; import { createTRPCContext } from "../api/trpc"; +import { validateRequest } from "@dokploy/server/lib/auth"; export const setupDrawerLogsWebSocketServer = ( server: http.Server, @@ -32,8 +33,13 @@ export const setupDrawerLogsWebSocketServer = ( } }); - // Return cleanup function - return () => { - wssTerm.close(); - }; + wssTerm.on("connection", async (ws, req) => { + const _url = new URL(req.url || "", `http://${req.headers.host}`); + const { user, session } = await validateRequest(req); + + if (!user || !session) { + ws.close(); + return; + } + }); }; diff --git a/apps/dokploy/utils/api.ts b/apps/dokploy/utils/api.ts index 7c003f48..56197528 100644 --- a/apps/dokploy/utils/api.ts +++ b/apps/dokploy/utils/api.ts @@ -27,28 +27,15 @@ const getWsUrl = () => { const protocol = window.location.protocol === "https:" ? "wss:" : "ws:"; const host = window.location.host; - // Use the base URL for all tRPC WebSocket connections return `${protocol}${host}/drawer-logs`; }; -// Singleton WebSocket client instance -let wsClientInstance: ReturnType | null = null; - -const getWsClient = () => { - if (typeof window === "undefined") return null; - - if (!wsClientInstance) { - wsClientInstance = createWSClient({ - url: getWsUrl() || "", - onClose: () => { - // Reset the instance when connection closes so it can be recreated - wsClientInstance = null; - }, - }); - } - - return wsClientInstance; -}; +const wsClient = + typeof window !== "undefined" + ? createWSClient({ + url: getWsUrl() || "", + }) + : null; /** A set of type-safe react-query hooks for your tRPC API. */ export const api = createTRPCNext({ @@ -70,7 +57,7 @@ export const api = createTRPCNext({ splitLink({ condition: (op) => op.type === "subscription", true: wsLink({ - client: getWsClient()!, + client: wsClient!, }), false: splitLink({ condition: (op) => op.input instanceof FormData, From 1605aedd6e55d6efe299b725e31317e2cbc7a916 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sun, 6 Apr 2025 01:41:47 -0600 Subject: [PATCH 07/27] feat(settings): add HTTPS support and update user schema - Introduced a new boolean field 'https' in the user schema to manage HTTPS settings. - Updated the web domain form to include an HTTPS toggle, allowing users to enable or disable HTTPS. - Enhanced validation logic to ensure certificate type is required when HTTPS is enabled. - Modified Traefik configuration to handle HTTPS routing based on user settings. --- .../dashboard/settings/web-domain.tsx | 111 +- apps/dokploy/drizzle/0084_thin_iron_lad.sql | 1 + apps/dokploy/drizzle/meta/0084_snapshot.json | 5369 +++++++++++++++++ apps/dokploy/drizzle/meta/_journal.json | 7 + apps/dokploy/server/api/routers/settings.ts | 1 + packages/server/src/db/schema/user.ts | 3 + .../server/src/utils/traefik/web-server.ts | 56 +- 7 files changed, 5500 insertions(+), 48 deletions(-) create mode 100644 apps/dokploy/drizzle/0084_thin_iron_lad.sql create mode 100644 apps/dokploy/drizzle/meta/0084_snapshot.json diff --git a/apps/dokploy/components/dashboard/settings/web-domain.tsx b/apps/dokploy/components/dashboard/settings/web-domain.tsx index a579df39..d35dae35 100644 --- a/apps/dokploy/components/dashboard/settings/web-domain.tsx +++ b/apps/dokploy/components/dashboard/settings/web-domain.tsx @@ -9,6 +9,7 @@ import { import { Form, FormControl, + FormDescription, FormField, FormItem, FormLabel, @@ -22,6 +23,7 @@ import { SelectTrigger, SelectValue, } from "@/components/ui/select"; +import { Switch } from "@/components/ui/switch"; import { api } from "@/utils/api"; import { zodResolver } from "@hookform/resolvers/zod"; import { GlobeIcon } from "lucide-react"; @@ -33,11 +35,19 @@ import { z } from "zod"; const addServerDomain = z .object({ - domain: z.string().min(1, { message: "URL is required" }), + domain: z.string(), letsEncryptEmail: z.string(), + https: z.boolean().optional(), certificateType: z.enum(["letsencrypt", "none", "custom"]), }) .superRefine((data, ctx) => { + if (data.https && !data.certificateType) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + path: ["certificateType"], + message: "Required", + }); + } if (data.certificateType === "letsencrypt" && !data.letsEncryptEmail) { ctx.addIssue({ code: z.ZodIssueCode.custom, @@ -61,15 +71,18 @@ export const WebDomain = () => { domain: "", certificateType: "none", letsEncryptEmail: "", + https: false, }, resolver: zodResolver(addServerDomain), }); + const https = form.watch("https"); useEffect(() => { if (data) { form.reset({ domain: data?.user?.host || "", certificateType: data?.user?.certificateType, letsEncryptEmail: data?.user?.letsEncryptEmail || "", + https: data?.user?.https || false, }); } }, [form, form.reset, data]); @@ -79,6 +92,7 @@ export const WebDomain = () => { host: data.domain, letsEncryptEmail: data.letsEncryptEmail, certificateType: data.certificateType, + https: data.https, }) .then(async () => { await refetch(); @@ -155,44 +169,67 @@ export const WebDomain = () => { /> { - return ( - - - {t("settings.server.domain.form.certificate.label")} - - + name="https" + render={({ field }) => ( + +
+ HTTPS + + Automatically provision SSL Certificate. + - - ); - }} +
+ + + +
+ )} /> + {https && ( + { + return ( + + + {t("settings.server.domain.form.certificate.label")} + + + + + ); + }} + /> + )}
- - - - -
- - - ); -}; - -export default Page; - -Page.getLayout = (page: ReactElement) => { - return {page}; -}; -export async function getServerSideProps( - ctx: GetServerSidePropsContext<{ serviceId: string }>, -) { - const { req, res } = ctx; - const { user, session } = await validateRequest(ctx.req); - if (!user) { - return { - redirect: { - permanent: true, - destination: "/", - }, - }; - } - if (user.role === "member") { - return { - redirect: { - permanent: true, - destination: "/dashboard/settings/profile", - }, - }; - } - - const helpers = createServerSideHelpers({ - router: appRouter, - ctx: { - req: req as any, - res: res as any, - db: null as any, - session: session as any, - user: user as any, - }, - transformer: superjson, - }); - await helpers.user.get.prefetch(); - - return { - props: { - trpcState: helpers.dehydrate(), - }, - }; -} From 8f0697b0e974048baade3f1d114b0d27490d4406 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sun, 6 Apr 2025 15:29:13 -0600 Subject: [PATCH 14/27] Update package.json --- apps/dokploy/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dokploy/package.json b/apps/dokploy/package.json index 34ca86fa..be1143be 100644 --- a/apps/dokploy/package.json +++ b/apps/dokploy/package.json @@ -1,6 +1,6 @@ { "name": "dokploy", - "version": "v0.21.3", + "version": "v0.21.4", "private": true, "license": "Apache-2.0", "type": "module", From 05f43ad06b4c7ccdb95b241f2dabe3636335e6b8 Mon Sep 17 00:00:00 2001 From: Axodouble Date: Mon, 7 Apr 2025 10:36:37 +0200 Subject: [PATCH 15/27] FEAT: Add Dutch / NL language translations --- apps/dokploy/public/locales/nl/common.json | 1 + apps/dokploy/public/locales/nl/settings.json | 58 ++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 apps/dokploy/public/locales/nl/common.json create mode 100644 apps/dokploy/public/locales/nl/settings.json diff --git a/apps/dokploy/public/locales/nl/common.json b/apps/dokploy/public/locales/nl/common.json new file mode 100644 index 00000000..69a88e3b --- /dev/null +++ b/apps/dokploy/public/locales/nl/common.json @@ -0,0 +1 @@ +{} diff --git a/apps/dokploy/public/locales/nl/settings.json b/apps/dokploy/public/locales/nl/settings.json new file mode 100644 index 00000000..34c492ec --- /dev/null +++ b/apps/dokploy/public/locales/nl/settings.json @@ -0,0 +1,58 @@ +{ + "settings.common.save": "Opslaan", + "settings.common.enterTerminal": "Terminal", + "settings.server.domain.title": "Server Domein", + "settings.server.domain.description": "Voeg een domein toe aan jouw server applicatie.", + "settings.server.domain.form.domain": "Domein", + "settings.server.domain.form.letsEncryptEmail": "Let's Encrypt Email", + "settings.server.domain.form.certificate.label": "Certificaat Aanbieder", + "settings.server.domain.form.certificate.placeholder": "Select een certificaat", + "settings.server.domain.form.certificateOptions.none": "Geen", + "settings.server.domain.form.certificateOptions.letsencrypt": "Let's Encrypt", + + "settings.server.webServer.title": "Web Server", + "settings.server.webServer.description": "Herlaad of maak de web server schoon.", + "settings.server.webServer.actions": "Acties", + "settings.server.webServer.reload": "Herladen", + "settings.server.webServer.watchLogs": "Bekijk Logs", + "settings.server.webServer.updateServerIp": "Update de Server IP", + "settings.server.webServer.server.label": "Server", + "settings.server.webServer.traefik.label": "Traefik", + "settings.server.webServer.traefik.modifyEnv": "Bewerk Omgeving", + "settings.server.webServer.traefik.managePorts": "Extra Poort Mappings", + "settings.server.webServer.traefik.managePortsDescription": "Bewerk extra Poorten voor Traefik", + "settings.server.webServer.traefik.targetPort": "Doel Poort", + "settings.server.webServer.traefik.publishedPort": "Gepubliceerde Poort", + "settings.server.webServer.traefik.addPort": "Voeg Poort toe", + "settings.server.webServer.traefik.portsUpdated": "Poorten succesvol aangepast", + "settings.server.webServer.traefik.portsUpdateError": "Poorten niet succesvol aangepast", + "settings.server.webServer.traefik.publishMode": "Publiceer Mode", + "settings.server.webServer.storage.label": "Opslag", + "settings.server.webServer.storage.cleanUnusedImages": "Maak ongebruikte images schoon", + "settings.server.webServer.storage.cleanUnusedVolumes": "Maak ongebruikte volumes schoon", + "settings.server.webServer.storage.cleanStoppedContainers": "Maak gestopte containers schoon", + "settings.server.webServer.storage.cleanDockerBuilder": "Maak Docker Builder & Systeem schoon", + "settings.server.webServer.storage.cleanMonitoring": "Maak monitoor schoon", + "settings.server.webServer.storage.cleanAll": "Maak alles schoon", + + "settings.profile.title": "Account", + "settings.profile.description": "Veramder details van account.", + "settings.profile.email": "Email", + "settings.profile.password": "Wachtwoord", + "settings.profile.avatar": "Profiel Icoon", + + "settings.appearance.title": "Uiterlijk", + "settings.appearance.description": "Verander het thema van je dashboard.", + "settings.appearance.theme": "Thema", + "settings.appearance.themeDescription": "Selecteer een thema voor je dashboard.", + "settings.appearance.themes.light": "Licht", + "settings.appearance.themes.dark": "Donker", + "settings.appearance.themes.system": "Systeem", + "settings.appearance.language": "Taal", + "settings.appearance.languageDescription": "Selecteer een taal voor je dashboard.", + + "settings.terminal.connectionSettings": "Verbindings instellingen", + "settings.terminal.ipAddress": "IP Address", + "settings.terminal.port": "Poort", + "settings.terminal.username": "Gebruikersnaam" +} From fa698d173ef0f49d54fa812f75659d7016aa7e1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20T=C3=B8n=20L=C3=B8vhaug?= Date: Tue, 8 Apr 2025 22:24:19 +0200 Subject: [PATCH 16/27] Move passHostHeader to correct position --- packages/server/src/utils/traefik/web-server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/utils/traefik/web-server.ts b/packages/server/src/utils/traefik/web-server.ts index 2a997147..1534e2f1 100644 --- a/packages/server/src/utils/traefik/web-server.ts +++ b/packages/server/src/utils/traefik/web-server.ts @@ -37,9 +37,9 @@ export const updateServerTraefik = ( servers: [ { url: `http://dokploy:${process.env.PORT || 3000}`, - passHostHeader: true, }, ], + passHostHeader: true, }, }, }; From 3ede89fe8adc42ebd0a74fd1d8bc539438102a59 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 8 Apr 2025 20:27:50 +0000 Subject: [PATCH 17/27] [autofix.ci] apply automated fixes --- apps/dokploy/pages/dashboard/project/[projectId].tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/dokploy/pages/dashboard/project/[projectId].tsx b/apps/dokploy/pages/dashboard/project/[projectId].tsx index 6c4ac4bc..728d83d1 100644 --- a/apps/dokploy/pages/dashboard/project/[projectId].tsx +++ b/apps/dokploy/pages/dashboard/project/[projectId].tsx @@ -365,7 +365,9 @@ const Project = ( switch (service.type) { case "application": - await applicationActions.start.mutateAsync({ applicationId: serviceId }); + await applicationActions.start.mutateAsync({ + applicationId: serviceId, + }); break; case "compose": await composeActions.start.mutateAsync({ composeId: serviceId }); @@ -410,7 +412,9 @@ const Project = ( switch (service.type) { case "application": - await applicationActions.stop.mutateAsync({ applicationId: serviceId }); + await applicationActions.stop.mutateAsync({ + applicationId: serviceId, + }); break; case "compose": await composeActions.stop.mutateAsync({ composeId: serviceId }); From ee6ad07c0a8efe58afa7fab5f57de167bc3b3b59 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Tue, 8 Apr 2025 22:44:17 -0600 Subject: [PATCH 18/27] Update package.json --- apps/dokploy/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dokploy/package.json b/apps/dokploy/package.json index be1143be..df9f6d53 100644 --- a/apps/dokploy/package.json +++ b/apps/dokploy/package.json @@ -1,6 +1,6 @@ { "name": "dokploy", - "version": "v0.21.4", + "version": "v0.21.5", "private": true, "license": "Apache-2.0", "type": "module", From 7a5a3de43dd6f6f437406b2c65aa8cc54748a4f3 Mon Sep 17 00:00:00 2001 From: vytenisstaugaitis <30520456+vytenisstaugaitis@users.noreply.github.com> Date: Wed, 9 Apr 2025 18:47:34 +0300 Subject: [PATCH 19/27] fix: correct message on preview deployments disabling --- .../application/preview-deployments/show-preview-settings.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dokploy/components/dashboard/application/preview-deployments/show-preview-settings.tsx b/apps/dokploy/components/dashboard/application/preview-deployments/show-preview-settings.tsx index bfc6ad2e..7bf2063b 100644 --- a/apps/dokploy/components/dashboard/application/preview-deployments/show-preview-settings.tsx +++ b/apps/dokploy/components/dashboard/application/preview-deployments/show-preview-settings.tsx @@ -298,7 +298,7 @@ export const ShowPreviewSettings = ({ applicationId }: Props) => { }) .then(() => { refetch(); - toast.success("Preview deployments enabled"); + toast.success(checked ? "Preview deployments enabled" : "Preview deployments disabled"); }) .catch((error) => { toast.error(error.message); From d335a9515d0c09b8ccc71208472cf82c347d6e04 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Wed, 9 Apr 2025 15:53:37 +0000 Subject: [PATCH 20/27] [autofix.ci] apply automated fixes --- .../preview-deployments/show-preview-settings.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/dokploy/components/dashboard/application/preview-deployments/show-preview-settings.tsx b/apps/dokploy/components/dashboard/application/preview-deployments/show-preview-settings.tsx index 7bf2063b..4c5068ee 100644 --- a/apps/dokploy/components/dashboard/application/preview-deployments/show-preview-settings.tsx +++ b/apps/dokploy/components/dashboard/application/preview-deployments/show-preview-settings.tsx @@ -298,7 +298,11 @@ export const ShowPreviewSettings = ({ applicationId }: Props) => { }) .then(() => { refetch(); - toast.success(checked ? "Preview deployments enabled" : "Preview deployments disabled"); + toast.success( + checked + ? "Preview deployments enabled" + : "Preview deployments disabled", + ); }) .catch((error) => { toast.error(error.message); From 37f9e073f084161a15b58289f37d0e43de6c749d Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sat, 12 Apr 2025 02:16:39 -0600 Subject: [PATCH 21/27] fix(railpack): update environment variable handling to include quotes for consistency --- packages/server/src/utils/builders/railpack.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/server/src/utils/builders/railpack.ts b/packages/server/src/utils/builders/railpack.ts index 612e02cf..55fd4049 100644 --- a/packages/server/src/utils/builders/railpack.ts +++ b/packages/server/src/utils/builders/railpack.ts @@ -84,7 +84,7 @@ export const buildRailpack = async ( for (const envVar of envVariables) { const [key, value] = envVar.split("="); if (key && value) { - buildArgs.push("--secret", `id=${key},env=${key}`); + buildArgs.push("--secret", `id=${key},env='${key}'`); env[key] = value; } } @@ -132,7 +132,7 @@ export const getRailpackCommand = ( ]; for (const env of envVariables) { - prepareArgs.push("--env", env); + prepareArgs.push("--env", `'${env}'`); } // Calculate secrets hash for layer invalidation @@ -164,7 +164,7 @@ export const getRailpackCommand = ( for (const envVar of envVariables) { const [key, value] = envVar.split("="); if (key && value) { - buildArgs.push("--secret", `id=${key},env=${key}`); + buildArgs.push("--secret", `id=${key},env='${key}'`); exportEnvs.push(`export ${key}=${value}`); } } From 773a610be17e96b4446a2ff8b4fc8cd3242c8627 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sat, 12 Apr 2025 02:27:43 -0600 Subject: [PATCH 22/27] fix(profile-form): disable refetch on window focus for user query --- .../settings/profile/profile-form.tsx | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/apps/dokploy/components/dashboard/settings/profile/profile-form.tsx b/apps/dokploy/components/dashboard/settings/profile/profile-form.tsx index 32179378..7a59469f 100644 --- a/apps/dokploy/components/dashboard/settings/profile/profile-form.tsx +++ b/apps/dokploy/components/dashboard/settings/profile/profile-form.tsx @@ -56,6 +56,8 @@ const randomImages = [ export const ProfileForm = () => { const _utils = api.useUtils(); const { data, refetch, isLoading } = api.user.get.useQuery(); + + console.log(data); const { mutateAsync, isLoading: isUpdating, @@ -84,12 +86,17 @@ export const ProfileForm = () => { useEffect(() => { if (data) { - form.reset({ - email: data?.user?.email || "", - password: "", - image: data?.user?.image || "", - currentPassword: "", - }); + form.reset( + { + email: data?.user?.email || "", + password: form.getValues("password") || "", + image: data?.user?.image || "", + currentPassword: form.getValues("currentPassword") || "", + }, + { + keepValues: true, + }, + ); if (data.user.email) { generateSHA256Hash(data.user.email).then((hash) => { @@ -97,8 +104,7 @@ export const ProfileForm = () => { }); } } - form.reset(); - }, [form, form.reset, data]); + }, [form, data]); const onSubmit = async (values: Profile) => { await mutateAsync({ @@ -110,7 +116,12 @@ export const ProfileForm = () => { .then(async () => { await refetch(); toast.success("Profile Updated"); - form.reset(); + form.reset({ + email: values.email, + password: "", + image: values.image, + currentPassword: "", + }); }) .catch(() => { toast.error("Error updating the profile"); From efee79888039298a84dba39e3fcb03f868bb4c4b Mon Sep 17 00:00:00 2001 From: Ron_Tayler Date: Sat, 12 Apr 2025 22:02:27 +0300 Subject: [PATCH 23/27] Fixed network search in Traefik Labels for the service --- packages/server/src/utils/docker/domain.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/server/src/utils/docker/domain.ts b/packages/server/src/utils/docker/domain.ts index 5a68146a..4f008397 100644 --- a/packages/server/src/utils/docker/domain.ts +++ b/packages/server/src/utils/docker/domain.ts @@ -249,6 +249,11 @@ export const addDomainToCompose = async ( labels.unshift("traefik.enable=true"); } labels.unshift(...httpLabels); + if (!compose.isolatedDeployment) { + if (!labels.includes("traefik.docker.network=dokploy-network")) { + labels.unshift("traefik.docker.network=dokploy-network"); + } + } } if (!compose.isolatedDeployment) { From 9b5cd0f5fe043dabb8d36558702c0b630711d1e6 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Sat, 12 Apr 2025 21:11:21 -0600 Subject: [PATCH 24/27] chore: update dependencies and enhance 2FA form - Updated `better-auth` to version 1.2.6 in multiple package.json files. - Updated `@better-auth/utils` to version 0.2.4 in server package.json. - Added optional `issuer` field to the 2FA form for enhanced user experience. - Removed unnecessary console log from the profile form component. --- .../dashboard/settings/profile/enable-2fa.tsx | 22 +++++ .../settings/profile/profile-form.tsx | 1 - apps/dokploy/package.json | 2 +- packages/server/package.json | 4 +- pnpm-lock.yaml | 88 ++++++++----------- 5 files changed, 62 insertions(+), 55 deletions(-) diff --git a/apps/dokploy/components/dashboard/settings/profile/enable-2fa.tsx b/apps/dokploy/components/dashboard/settings/profile/enable-2fa.tsx index 6cf2c6a5..1cfa7574 100644 --- a/apps/dokploy/components/dashboard/settings/profile/enable-2fa.tsx +++ b/apps/dokploy/components/dashboard/settings/profile/enable-2fa.tsx @@ -36,6 +36,7 @@ const PasswordSchema = z.object({ password: z.string().min(8, { message: "Password is required", }), + issuer: z.string().optional(), }); const PinSchema = z.object({ @@ -66,6 +67,7 @@ export const Enable2FA = () => { try { const { data: enableData, error } = await authClient.twoFactor.enable({ password: formData.password, + issuer: formData.issuer, }); if (!enableData) { @@ -217,6 +219,26 @@ export const Enable2FA = () => {
)} /> + ( + + Issuer + + + + + Enter your password to enable 2FA + + + + )} + />