Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
3320663
refactor(web-server): provider-neutral abstraction (Traefik-only, zer…
masonjames Jun 10, 2026
9510019
fix(db): fail closed on runtime migration errors
masonjames Jun 10, 2026
1f4da76
feat(caddy): core provider — setup, config generation, domain/compose…
masonjames Jun 10, 2026
cee43a4
feat(caddy): guarded Traefik→Caddy migration — dry-run, preflight, ap…
masonjames Jun 10, 2026
d43f859
feat(caddy): settings UI — provider selector, migration panel, dashbo…
masonjames Jun 10, 2026
96d9fdc
feat(caddy): request analytics and provider-aware access logs
masonjames Jun 10, 2026
8531176
test(caddy): migration, certs, trusted proxies, dashboard isolation
masonjames Jun 10, 2026
0dcc5f9
chore(db): regenerate drizzle snapshot
masonjames Jun 10, 2026
3dac46f
fix(caddy): emit trusted_proxies_strict as int — booleans fail caddy …
masonjames Jun 10, 2026
5493033
fix(caddy): inherit application domain port
masonjames Jun 24, 2026
e452f4b
Merge upstream/canary into caddy web server PR
masonjames Jul 3, 2026
9ff06c8
fix(caddy): serialize fragment and config writes per server
masonjames Jul 3, 2026
9209b84
refactor(settings): extract web-server procedures into their own module
masonjames Jul 3, 2026
e4be3b3
fix(caddy): let org members resolve the active web-server provider
masonjames Jul 3, 2026
06d544b
style(caddy): align provider components with tailwind v4 classes
masonjames Jul 3, 2026
8619f07
Merge upstream v0.29.10 into Caddy web server branch
masonjames Jul 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
ENV NODE_ENV=production
RUN pnpm --filter=@dokploy/server build
RUN pnpm --filter=./apps/dokploy run build
RUN test -f /usr/src/app/apps/dokploy/dist/caddy-migration-rollback.mjs

RUN pnpm --filter=./apps/dokploy --prod deploy --legacy /prod/dokploy

Expand All @@ -43,7 +44,8 @@ COPY --from=build /prod/dokploy/drizzle ./drizzle
COPY .env.production ./.env
COPY --from=build /prod/dokploy/components.json ./components.json
COPY --from=build /prod/dokploy/node_modules ./node_modules

RUN test -f /app/dist/caddy-migration-rollback.mjs \
&& node -r dotenv/config /app/dist/caddy-migration-rollback.mjs --help | grep -q "Usage: caddy-migration-rollback"

# Install docker
RUN curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh --version 28.5.2 && rm get-docker.sh && curl https://rclone.org/install.sh | bash
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { readFileSync } from "node:fs";
import { expect, test, vi } from "vitest";
import { invalidateApplicationWebServerConfig } from "@/components/dashboard/application/web-server-config-cache";

const createUtils = () => ({
application: {
readTraefikConfig: {
invalidate: vi.fn(),
},
readWebServerConfig: {
invalidate: vi.fn(),
},
},
});

test("invalidates legacy Traefik and provider-aware application web-server config caches", async () => {
const utils = createUtils();

await invalidateApplicationWebServerConfig(utils, "app-1");

expect(utils.application.readTraefikConfig.invalidate).toHaveBeenCalledWith({
applicationId: "app-1",
});
expect(utils.application.readWebServerConfig.invalidate).toHaveBeenCalledWith(
{ applicationId: "app-1" },
);
});

test("awaits both application web-server config cache invalidations", async () => {
const calls: string[] = [];
const utils = createUtils();
utils.application.readTraefikConfig.invalidate.mockImplementation(
async () => {
await Promise.resolve();
calls.push("traefik");
},
);
utils.application.readWebServerConfig.invalidate.mockImplementation(
async () => {
await Promise.resolve();
calls.push("web-server");
},
);

await invalidateApplicationWebServerConfig(utils, "app-1");

expect(calls).toEqual(["traefik", "web-server"]);
});

test("propagates application web-server config cache invalidation failures", async () => {
const utils = createUtils();
utils.application.readWebServerConfig.invalidate.mockRejectedValueOnce(
new Error("provider-aware cache failed"),
);

await expect(
invalidateApplicationWebServerConfig(utils, "app-1"),
).rejects.toThrow("provider-aware cache failed");
expect(utils.application.readTraefikConfig.invalidate).toHaveBeenCalledWith({
applicationId: "app-1",
});
});

const applicationMutationHandlers = [
[
"domain handler",
"../../components/dashboard/application/domains/handle-domain.tsx",
],
[
"redirect form handler",
"../../components/dashboard/application/advanced/redirects/handle-redirect.tsx",
],
[
"redirect delete handler",
"../../components/dashboard/application/advanced/redirects/show-redirects.tsx",
],
[
"security form handler",
"../../components/dashboard/application/advanced/security/handle-security.tsx",
],
[
"security delete handler",
"../../components/dashboard/application/advanced/security/show-security.tsx",
],
] as const;

test.each(applicationMutationHandlers)(
"%s uses the shared application web-server cache invalidation helper",
(_name, filePath) => {
const source = readFileSync(new URL(filePath, import.meta.url), "utf8");

expect(source).toContain("invalidateApplicationWebServerConfig");
expect(source).not.toMatch(/readTraefikConfig\.invalidate/);
expect(source).not.toMatch(/readWebServerConfig\.invalidate/);
},
);
Loading