From 43f9f545c684e067e367ad4d07f0307734291ca4 Mon Sep 17 00:00:00 2001 From: Yandi Date: Sun, 22 Feb 2026 19:56:29 +0700 Subject: [PATCH 001/130] fix: use lazy initializer for useState with function calls Calling getTerminalKey() and getDefaultDateRange() directly in useState re-runs them on every render. Wrap in an arrow function so they execute only once during component initialization. --- apps/dokploy/components/dashboard/requests/show-requests.tsx | 2 +- .../dashboard/settings/web-server/terminal-modal.tsx | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/dokploy/components/dashboard/requests/show-requests.tsx b/apps/dokploy/components/dashboard/requests/show-requests.tsx index cc4f1764a..076ed33cc 100644 --- a/apps/dokploy/components/dashboard/requests/show-requests.tsx +++ b/apps/dokploy/components/dashboard/requests/show-requests.tsx @@ -63,7 +63,7 @@ export const ShowRequests = () => { const [dateRange, setDateRange] = useState<{ from: Date | undefined; to: Date | undefined; - }>(getDefaultDateRange()); + }>(() => getDefaultDateRange()); // Check if logs exist to determine if traefik has been reloaded // Only fetch when active to minimize network calls diff --git a/apps/dokploy/components/dashboard/settings/web-server/terminal-modal.tsx b/apps/dokploy/components/dashboard/settings/web-server/terminal-modal.tsx index 2647e1dc0..e90ba51f8 100644 --- a/apps/dokploy/components/dashboard/settings/web-server/terminal-modal.tsx +++ b/apps/dokploy/components/dashboard/settings/web-server/terminal-modal.tsx @@ -32,7 +32,9 @@ export const TerminalModal = ({ serverId, asButton = false, }: Props) => { - const [terminalKey, setTerminalKey] = useState(getTerminalKey()); + const [terminalKey, setTerminalKey] = useState(() => + getTerminalKey(), + ); const [isOpen, setIsOpen] = useState(false); const isLocalServer = serverId === "local"; From eb80f79862b751029de4ba3a4fe655003926850a Mon Sep 17 00:00:00 2001 From: Gabriel Vinhaes Date: Wed, 1 Apr 2026 16:37:56 -0300 Subject: [PATCH 002/130] fix: preserve server schedule failures through tee pipeline --- packages/server/src/utils/schedules/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/utils/schedules/utils.ts b/packages/server/src/utils/schedules/utils.ts index 64657c9a6..3330acb52 100644 --- a/packages/server/src/utils/schedules/utils.ts +++ b/packages/server/src/utils/schedules/utils.ts @@ -159,7 +159,7 @@ export const runCommand = async (scheduleId: string) => { const { SCHEDULES_PATH } = paths(true); const fullPath = path.join(SCHEDULES_PATH, appName || ""); const command = ` - set -e + set -euo pipefail echo "Running script" >> ${deployment.logPath}; bash -c ${fullPath}/script.sh 2>&1 | tee -a ${deployment.logPath} || { echo "❌ Command failed" >> ${deployment.logPath}; From 3e1189776238cd6fd24b75ec531146f210bc67bf Mon Sep 17 00:00:00 2001 From: Rizki Putra Date: Tue, 7 Apr 2026 08:53:47 +0700 Subject: [PATCH 003/130] fix: return a valid docker host for docker desktop --- apps/dokploy/server/utils/docker.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/dokploy/server/utils/docker.ts b/apps/dokploy/server/utils/docker.ts index 07e4e26e1..35144913a 100644 --- a/apps/dokploy/server/utils/docker.ts +++ b/apps/dokploy/server/utils/docker.ts @@ -11,10 +11,20 @@ export const isWSL = async () => { } }; +/** Returns if running in Docker Desktop. */ +export const isDockerDesktop = async () => { + try { + const { stdout } = await execAsync("getent hosts host.docker.internal"); + return !!stdout.trim(); + } catch { + return false; + } +}; + /** Returns the Docker host IP address. */ export const getDockerHost = async (): Promise => { if (process.env.NODE_ENV === "production") { - if (process.platform === "linux" && !(await isWSL())) { + if (process.platform === "linux" && !(await isWSL() || await isDockerDesktop())) { try { // Try to get the Docker bridge IP first const { stdout } = await execAsync( From e802342f5711aef5c64692cf5517139567a0e142 Mon Sep 17 00:00:00 2001 From: rpoetrap Date: Tue, 7 Apr 2026 17:04:38 +0700 Subject: [PATCH 004/130] fix sequential awaits --- apps/dokploy/server/utils/docker.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/dokploy/server/utils/docker.ts b/apps/dokploy/server/utils/docker.ts index 35144913a..084315241 100644 --- a/apps/dokploy/server/utils/docker.ts +++ b/apps/dokploy/server/utils/docker.ts @@ -24,7 +24,11 @@ export const isDockerDesktop = async () => { /** Returns the Docker host IP address. */ export const getDockerHost = async (): Promise => { if (process.env.NODE_ENV === "production") { - if (process.platform === "linux" && !(await isWSL() || await isDockerDesktop())) { + const isLinux = process.platform === "linux" + ? (await Promise.all([isWSL(), isDockerDesktop()])).every((v) => !v) + : false; + + if (isLinux) { try { // Try to get the Docker bridge IP first const { stdout } = await execAsync( From f21931da60fcd5e9f7116a6bde1d39e2dc55b5b5 Mon Sep 17 00:00:00 2001 From: Daniel Abramov Date: Wed, 8 Apr 2026 18:29:29 +0200 Subject: [PATCH 005/130] fix: add unzip to arch server set up --- packages/server/src/setup/server-setup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/setup/server-setup.ts b/packages/server/src/setup/server-setup.ts index e2d7fc3e5..620a4e62b 100644 --- a/packages/server/src/setup/server-setup.ts +++ b/packages/server/src/setup/server-setup.ts @@ -466,7 +466,7 @@ const installUtilities = () => ` case "$OS_TYPE" in arch) - $SUDO_CMD pacman -Sy --noconfirm --needed curl wget git git-lfs jq openssl >/dev/null || true + $SUDO_CMD pacman -Sy --noconfirm --needed unzip curl wget git git-lfs jq openssl >/dev/null || true ;; alpine) $SUDO_CMD sed -i '/^#.*\/community/s/^#//' /etc/apk/repositories From 9be96d4195d80819b6824c8d77fc22100bf2a2d8 Mon Sep 17 00:00:00 2001 From: Guillaume LECOMTE Date: Tue, 14 Apr 2026 11:58:21 +0200 Subject: [PATCH 006/130] fix(ui): update favicon dynamically based on app theme Add icon-light.svg and icon-dark.svg with fixed fills (black/white) instead of relying on CSS prefers-color-scheme media query. Update WhitelabelingProvider to use useTheme() and switch favicon based on resolvedTheme (dark/light/unknown). When custom faviconUrl is set, it takes precedence. Closes #4100. --- .../proprietary/whitelabeling/whitelabeling-provider.tsx | 9 ++++++++- apps/dokploy/public/icon-dark.svg | 5 +++++ apps/dokploy/public/icon-light.svg | 5 +++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 apps/dokploy/public/icon-dark.svg create mode 100644 apps/dokploy/public/icon-light.svg diff --git a/apps/dokploy/components/proprietary/whitelabeling/whitelabeling-provider.tsx b/apps/dokploy/components/proprietary/whitelabeling/whitelabeling-provider.tsx index a1a327561..23c99a78e 100644 --- a/apps/dokploy/components/proprietary/whitelabeling/whitelabeling-provider.tsx +++ b/apps/dokploy/components/proprietary/whitelabeling/whitelabeling-provider.tsx @@ -1,21 +1,28 @@ "use client"; import Head from "next/head"; +import { useTheme } from "next-themes"; import { api } from "@/utils/api"; export function WhitelabelingProvider() { + const { resolvedTheme } = useTheme(); const { data: config } = api.whitelabeling.getPublic.useQuery(undefined, { staleTime: 5 * 60 * 1000, refetchOnWindowFocus: false, }); + const faviconHref = config?.faviconUrl + ?? (resolvedTheme === "dark" ? "/icon-dark.svg" + : resolvedTheme === "light" ? "/icon-light.svg" + : "/icon.svg"); + if (!config) return null; return ( <> {config.metaTitle && {config.metaTitle}} - {config.faviconUrl && } + {config.customCss && ( diff --git a/apps/dokploy/public/icon-dark.svg b/apps/dokploy/public/icon-dark.svg new file mode 100644 index 000000000..5faafdb37 --- /dev/null +++ b/apps/dokploy/public/icon-dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/dokploy/public/icon-light.svg b/apps/dokploy/public/icon-light.svg new file mode 100644 index 000000000..6121a89dd --- /dev/null +++ b/apps/dokploy/public/icon-light.svg @@ -0,0 +1,5 @@ + + + + + From 689ae51ee75db7704f977d8e66b77687d095a867 Mon Sep 17 00:00:00 2001 From: Guillaume LECOMTE Date: Tue, 14 Apr 2026 12:16:57 +0200 Subject: [PATCH 007/130] fix(ui): remove early return to render theme-aware favicon immediately The previous implementation returned null when config was not yet loaded, preventing the theme-aware favicon from rendering during initial page load. Now uses optional chaining (config?.metaTitle, config?.customCss) throughout so the always renders with the correct theme-aware favicon regardless of config loading state. Fixes P1 issue from code review. --- .../proprietary/whitelabeling/whitelabeling-provider.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/dokploy/components/proprietary/whitelabeling/whitelabeling-provider.tsx b/apps/dokploy/components/proprietary/whitelabeling/whitelabeling-provider.tsx index 23c99a78e..7fce2a935 100644 --- a/apps/dokploy/components/proprietary/whitelabeling/whitelabeling-provider.tsx +++ b/apps/dokploy/components/proprietary/whitelabeling/whitelabeling-provider.tsx @@ -16,16 +16,14 @@ export function WhitelabelingProvider() { : resolvedTheme === "light" ? "/icon-light.svg" : "/icon.svg"); - if (!config) return null; - return ( <> - {config.metaTitle && {config.metaTitle}} + {config?.metaTitle && {config.metaTitle}} - {config.customCss && ( + {config?.customCss && (