diff --git a/apps/dokploy/__test__/traefik/server/update-server-config.test.ts b/apps/dokploy/__test__/traefik/server/update-server-config.test.ts index f33b37fd..201aee1e 100644 --- a/apps/dokploy/__test__/traefik/server/update-server-config.test.ts +++ b/apps/dokploy/__test__/traefik/server/update-server-config.test.ts @@ -14,6 +14,7 @@ import { import { beforeEach, expect, test, vi } from "vitest"; const baseAdmin: User = { + https: false, enablePaidFeatures: false, metricsConfig: { containers: { @@ -73,7 +74,6 @@ beforeEach(() => { test("Should read the configuration file", () => { const config: FileConfig = loadOrCreateConfig("dokploy"); - expect(config.http?.routers?.["dokploy-router-app"]?.service).toBe( "dokploy-service-app", ); @@ -83,6 +83,7 @@ test("Should apply redirect-to-https", () => { updateServerTraefik( { ...baseAdmin, + https: true, certificateType: "letsencrypt", }, "example.com", 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")} + + + + + ); + }} + /> + )}