mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
Compare commits
8 Commits
feat/caddy
...
1757-unabl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd4eed3507 | ||
|
|
a650bd16fb | ||
|
|
4e5b5f219e | ||
|
|
dfda934726 | ||
|
|
546c6ade82 | ||
|
|
db2e3691a5 | ||
|
|
a6dca144a8 | ||
|
|
43a17e7e75 |
@@ -65,7 +65,7 @@ export const ShowProviderForm = ({ applicationId }: Props) => {
|
|||||||
setSab(e as TabState);
|
setSab(e as TabState);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center justify-between w-full gap-4">
|
<div className="flex flex-row items-center justify-between w-full gap-4">
|
||||||
<TabsList className="md:grid md:w-fit md:grid-cols-7 max-md:overflow-x-scroll justify-start bg-transparent overflow-y-hidden">
|
<TabsList className="md:grid md:w-fit md:grid-cols-7 max-md:overflow-x-scroll justify-start bg-transparent overflow-y-hidden">
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
value="github"
|
value="github"
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export const AiForm = () => {
|
|||||||
key={config.aiId}
|
key={config.aiId}
|
||||||
className="flex items-center justify-between bg-sidebar p-1 w-full rounded-lg"
|
className="flex items-center justify-between bg-sidebar p-1 w-full rounded-lg"
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between p-3.5 rounded-lg bg-background border w-full">
|
<div className="flex items-center justify-between p-3.5 rounded-lg bg-background border w-full">
|
||||||
<div>
|
<div>
|
||||||
<span className="text-sm font-medium">
|
<span className="text-sm font-medium">
|
||||||
{config.name}
|
{config.name}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export const ShowCertificates = () => {
|
|||||||
key={certificate.certificateId}
|
key={certificate.certificateId}
|
||||||
className="flex items-center justify-between bg-sidebar p-1 w-full rounded-lg"
|
className="flex items-center justify-between bg-sidebar p-1 w-full rounded-lg"
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between p-3.5 rounded-lg bg-background border w-full">
|
<div className="flex items-center justify-between p-3.5 rounded-lg bg-background border w-full">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex gap-2 flex-col">
|
<div className="flex gap-2 flex-col">
|
||||||
<span className="text-sm font-medium">
|
<span className="text-sm font-medium">
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export const ShowRegistry = () => {
|
|||||||
key={registry.registryId}
|
key={registry.registryId}
|
||||||
className="flex items-center justify-between bg-sidebar p-1 w-full rounded-lg"
|
className="flex items-center justify-between bg-sidebar p-1 w-full rounded-lg"
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between p-3.5 rounded-lg bg-background border w-full">
|
<div className="flex items-center justify-between p-3.5 rounded-lg bg-background border w-full">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex gap-2 flex-col">
|
<div className="flex gap-2 flex-col">
|
||||||
<span className="text-sm font-medium">
|
<span className="text-sm font-medium">
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export const ShowDestinations = () => {
|
|||||||
key={destination.destinationId}
|
key={destination.destinationId}
|
||||||
className="flex items-center justify-between bg-sidebar p-1 w-full rounded-lg"
|
className="flex items-center justify-between bg-sidebar p-1 w-full rounded-lg"
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between p-3.5 rounded-lg bg-background border w-full">
|
<div className="flex items-center justify-between p-3.5 rounded-lg bg-background border w-full">
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
<span className="text-sm">
|
<span className="text-sm">
|
||||||
{index + 1}. {destination.name}
|
{index + 1}. {destination.name}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ export const ShowNotifications = () => {
|
|||||||
key={notification.notificationId}
|
key={notification.notificationId}
|
||||||
className="flex items-center justify-between bg-sidebar p-1 w-full rounded-lg"
|
className="flex items-center justify-between bg-sidebar p-1 w-full rounded-lg"
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between p-3.5 rounded-lg bg-background border w-full">
|
<div className="flex items-center justify-between p-3.5 rounded-lg bg-background border w-full">
|
||||||
<span className="text-sm flex flex-row items-center gap-4">
|
<span className="text-sm flex flex-row items-center gap-4">
|
||||||
{notification.notificationType === "slack" && (
|
{notification.notificationType === "slack" && (
|
||||||
<div className="flex items-center justify-center rounded-lg">
|
<div className="flex items-center justify-center rounded-lg">
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export const ShowDestinations = () => {
|
|||||||
key={sshKey.sshKeyId}
|
key={sshKey.sshKeyId}
|
||||||
className="flex items-center justify-between bg-sidebar p-1 w-full rounded-lg"
|
className="flex items-center justify-between bg-sidebar p-1 w-full rounded-lg"
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between p-3.5 rounded-lg bg-background border w-full">
|
<div className="flex items-center justify-between p-3.5 rounded-lg bg-background border w-full">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<span className="text-sm font-medium">
|
<span className="text-sm font-medium">
|
||||||
|
|||||||
@@ -134,16 +134,7 @@ export const UserNav = () => {
|
|||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{data?.role === "owner" && (
|
|
||||||
<DropdownMenuItem
|
|
||||||
className="cursor-pointer"
|
|
||||||
onClick={() => {
|
|
||||||
router.push("/dashboard/settings");
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Settings
|
|
||||||
</DropdownMenuItem>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</DropdownMenuGroup>
|
</DropdownMenuGroup>
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ const Service = (
|
|||||||
router.push(newPath);
|
router.push(newPath);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center justify-between w-full gap-4">
|
<div className="flex flex-row items-center justify-between w-full gap-4 overflow-x-scroll">
|
||||||
<TabsList
|
<TabsList
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex gap-8 justify-start max-xl:overflow-x-scroll overflow-y-hidden",
|
"flex gap-8 justify-start max-xl:overflow-x-scroll overflow-y-hidden",
|
||||||
|
|||||||
@@ -212,15 +212,15 @@ const Service = (
|
|||||||
router.push(newPath);
|
router.push(newPath);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center justify-between w-full gap-4">
|
<div className="flex flex-row items-center justify-between w-full gap-4 overflow-x-scroll">
|
||||||
<TabsList
|
<TabsList
|
||||||
className={cn(
|
className={cn(
|
||||||
"md:grid md:w-fit max-md:overflow-y-scroll justify-start",
|
"lg:grid lg:w-fit max-md:overflow-y-scroll justify-start",
|
||||||
isCloud && data?.serverId
|
isCloud && data?.serverId
|
||||||
? "md:grid-cols-7"
|
? "lg:grid-cols-7"
|
||||||
: data?.serverId
|
: data?.serverId
|
||||||
? "md:grid-cols-6"
|
? "lg:grid-cols-6"
|
||||||
: "md:grid-cols-7",
|
: "lg:grid-cols-7",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<TabsTrigger value="general">General</TabsTrigger>
|
<TabsTrigger value="general">General</TabsTrigger>
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ const Mariadb = (
|
|||||||
router.push(newPath, undefined, { shallow: true });
|
router.push(newPath, undefined, { shallow: true });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center justify-between w-full gap-4">
|
<div className="flex flex-row items-center justify-between w-full gap-4 overflow-x-scroll">
|
||||||
<TabsList
|
<TabsList
|
||||||
className={cn(
|
className={cn(
|
||||||
"md:grid md:w-fit max-md:overflow-y-scroll justify-start",
|
"md:grid md:w-fit max-md:overflow-y-scroll justify-start",
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ const Mongo = (
|
|||||||
router.push(newPath, undefined, { shallow: true });
|
router.push(newPath, undefined, { shallow: true });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center justify-between w-full gap-4">
|
<div className="flex flex-row items-center justify-between w-full gap-4 overflow-x-scroll">
|
||||||
<TabsList
|
<TabsList
|
||||||
className={cn(
|
className={cn(
|
||||||
"md:grid md:w-fit max-md:overflow-y-scroll justify-start",
|
"md:grid md:w-fit max-md:overflow-y-scroll justify-start",
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ const MySql = (
|
|||||||
router.push(newPath, undefined, { shallow: true });
|
router.push(newPath, undefined, { shallow: true });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center justify-between w-full gap-4">
|
<div className="flex flex-row items-center justify-between w-full gap-4 overflow-x-scroll">
|
||||||
<TabsList
|
<TabsList
|
||||||
className={cn(
|
className={cn(
|
||||||
"md:grid md:w-fit max-md:overflow-y-scroll justify-start ",
|
"md:grid md:w-fit max-md:overflow-y-scroll justify-start ",
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ const Postgresql = (
|
|||||||
router.push(newPath, undefined, { shallow: true });
|
router.push(newPath, undefined, { shallow: true });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center justify-between w-full gap-4">
|
<div className="flex flex-row items-center justify-between w-full gap-4 overflow-x-scroll">
|
||||||
<TabsList
|
<TabsList
|
||||||
className={cn(
|
className={cn(
|
||||||
"md:grid md:w-fit max-md:overflow-y-scroll justify-start",
|
"md:grid md:w-fit max-md:overflow-y-scroll justify-start",
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ const Redis = (
|
|||||||
router.push(newPath, undefined, { shallow: true });
|
router.push(newPath, undefined, { shallow: true });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex flex-row items-center justify-between w-full gap-4">
|
<div className="flex flex-row items-center justify-between w-full gap-4 overflow-x-scroll">
|
||||||
<TabsList
|
<TabsList
|
||||||
className={cn(
|
className={cn(
|
||||||
"md:grid md:w-fit max-md:overflow-y-scroll justify-start",
|
"md:grid md:w-fit max-md:overflow-y-scroll justify-start",
|
||||||
|
|||||||
@@ -12,14 +12,10 @@ export const paths = (isServer = false) => {
|
|||||||
const MAIN_TRAEFIK_PATH = `${BASE_PATH}/traefik`;
|
const MAIN_TRAEFIK_PATH = `${BASE_PATH}/traefik`;
|
||||||
const DYNAMIC_TRAEFIK_PATH = `${MAIN_TRAEFIK_PATH}/dynamic`;
|
const DYNAMIC_TRAEFIK_PATH = `${MAIN_TRAEFIK_PATH}/dynamic`;
|
||||||
|
|
||||||
const CADDY_PATH = `${BASE_PATH}/caddy`;
|
|
||||||
const CADDY_DYNAMIC_PATH = `${CADDY_PATH}/dynamic`;
|
|
||||||
return {
|
return {
|
||||||
BASE_PATH,
|
BASE_PATH,
|
||||||
MAIN_TRAEFIK_PATH,
|
MAIN_TRAEFIK_PATH,
|
||||||
DYNAMIC_TRAEFIK_PATH,
|
DYNAMIC_TRAEFIK_PATH,
|
||||||
CADDY_PATH,
|
|
||||||
CADDY_DYNAMIC_PATH,
|
|
||||||
LOGS_PATH: `${BASE_PATH}/logs`,
|
LOGS_PATH: `${BASE_PATH}/logs`,
|
||||||
APPLICATIONS_PATH: `${BASE_PATH}/applications`,
|
APPLICATIONS_PATH: `${BASE_PATH}/applications`,
|
||||||
COMPOSE_PATH: `${BASE_PATH}/compose`,
|
COMPOSE_PATH: `${BASE_PATH}/compose`,
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ const { handler, api } = betterAuth({
|
|||||||
const host =
|
const host =
|
||||||
process.env.NODE_ENV === "development"
|
process.env.NODE_ENV === "development"
|
||||||
? "http://localhost:3000"
|
? "http://localhost:3000"
|
||||||
: "https://dokploy.com";
|
: "https://app.dokploy.com";
|
||||||
const inviteLink = `${host}/invitation?token=${data.id}`;
|
const inviteLink = `${host}/invitation?token=${data.id}`;
|
||||||
|
|
||||||
await sendEmail({
|
await sendEmail({
|
||||||
|
|||||||
@@ -1,350 +0,0 @@
|
|||||||
import { chmodSync, existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
||||||
import path from "node:path";
|
|
||||||
import type { ContainerCreateOptions } from "dockerode";
|
|
||||||
import { dump } from "js-yaml";
|
|
||||||
import { paths } from "../constants";
|
|
||||||
import { getRemoteDocker } from "../utils/servers/remote-docker";
|
|
||||||
import type { FileConfig } from "../utils/traefik/file-types";
|
|
||||||
import type { MainTraefikConfig } from "../utils/traefik/types";
|
|
||||||
|
|
||||||
export const TRAEFIK_SSL_PORT =
|
|
||||||
Number.parseInt(process.env.TRAEFIK_SSL_PORT!, 10) || 443;
|
|
||||||
export const TRAEFIK_PORT =
|
|
||||||
Number.parseInt(process.env.TRAEFIK_PORT!, 10) || 80;
|
|
||||||
export const TRAEFIK_HTTP3_PORT =
|
|
||||||
Number.parseInt(process.env.TRAEFIK_HTTP3_PORT!, 10) || 443;
|
|
||||||
export const TRAEFIK_VERSION = process.env.TRAEFIK_VERSION || "3.1.2";
|
|
||||||
|
|
||||||
interface TraefikOptions {
|
|
||||||
enableDashboard?: boolean;
|
|
||||||
env?: string[];
|
|
||||||
serverId?: string;
|
|
||||||
additionalPorts?: {
|
|
||||||
targetPort: number;
|
|
||||||
publishedPort: number;
|
|
||||||
}[];
|
|
||||||
force?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const initializeCaddy = async ({
|
|
||||||
enableDashboard = false,
|
|
||||||
env,
|
|
||||||
serverId,
|
|
||||||
additionalPorts = [],
|
|
||||||
force = false,
|
|
||||||
}: TraefikOptions = {}) => {
|
|
||||||
const { CADDY_PATH, CADDY_DYNAMIC_PATH } = paths(!!serverId);
|
|
||||||
const imageName = "lucaslorentz/caddy-docker-proxy:ci-alpine";
|
|
||||||
const containerName = "dokploy-caddy";
|
|
||||||
|
|
||||||
const exposedPorts: Record<string, {}> = {
|
|
||||||
[`${TRAEFIK_PORT}/tcp`]: {},
|
|
||||||
[`${TRAEFIK_SSL_PORT}/tcp`]: {},
|
|
||||||
[`${TRAEFIK_HTTP3_PORT}/udp`]: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
const portBindings: Record<string, Array<{ HostPort: string }>> = {
|
|
||||||
[`${TRAEFIK_PORT}/tcp`]: [{ HostPort: TRAEFIK_PORT.toString() }],
|
|
||||||
[`${TRAEFIK_SSL_PORT}/tcp`]: [{ HostPort: TRAEFIK_SSL_PORT.toString() }],
|
|
||||||
[`${TRAEFIK_HTTP3_PORT}/udp`]: [
|
|
||||||
{ HostPort: TRAEFIK_HTTP3_PORT.toString() },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
if (enableDashboard) {
|
|
||||||
exposedPorts["8080/tcp"] = {};
|
|
||||||
portBindings["8080/tcp"] = [{ HostPort: "8080" }];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const port of additionalPorts) {
|
|
||||||
const portKey = `${port.targetPort}/tcp`;
|
|
||||||
exposedPorts[portKey] = {};
|
|
||||||
portBindings[portKey] = [{ HostPort: port.publishedPort.toString() }];
|
|
||||||
}
|
|
||||||
|
|
||||||
const settings: ContainerCreateOptions = {
|
|
||||||
name: containerName,
|
|
||||||
Image: imageName,
|
|
||||||
NetworkingConfig: {
|
|
||||||
EndpointsConfig: {
|
|
||||||
"dokploy-network": {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ExposedPorts: exposedPorts,
|
|
||||||
HostConfig: {
|
|
||||||
RestartPolicy: {
|
|
||||||
Name: "always",
|
|
||||||
},
|
|
||||||
Binds: [
|
|
||||||
`${CADDY_PATH}/Caddyfile:/etc/caddy/Caddyfile`,
|
|
||||||
`${CADDY_DYNAMIC_PATH}:/etc/caddy/dynamic`,
|
|
||||||
"/var/run/docker.sock:/var/run/docker.sock",
|
|
||||||
],
|
|
||||||
PortBindings: portBindings,
|
|
||||||
},
|
|
||||||
Env: env,
|
|
||||||
};
|
|
||||||
|
|
||||||
const docker = await getRemoteDocker(serverId);
|
|
||||||
try {
|
|
||||||
try {
|
|
||||||
const service = docker.getService("dokploy-caddy");
|
|
||||||
await service?.remove({ force: true });
|
|
||||||
|
|
||||||
let attempts = 0;
|
|
||||||
const maxAttempts = 5;
|
|
||||||
while (attempts < maxAttempts) {
|
|
||||||
try {
|
|
||||||
await docker.listServices({
|
|
||||||
filters: { name: ["dokploy-caddy"] },
|
|
||||||
});
|
|
||||||
console.log("Waiting for service cleanup...");
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
||||||
attempts++;
|
|
||||||
} catch (_e) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (_err) {
|
|
||||||
console.log("No existing service to remove");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then try to remove any existing container
|
|
||||||
const container = docker.getContainer(containerName);
|
|
||||||
try {
|
|
||||||
const inspect = await container.inspect();
|
|
||||||
if (inspect.State.Status === "running" && !force) {
|
|
||||||
console.log("Caddy already running");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await container.remove({ force: true });
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
||||||
} catch (_err) {
|
|
||||||
console.log("No existing container to remove");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create and start the new container
|
|
||||||
try {
|
|
||||||
await docker.createContainer(settings);
|
|
||||||
const newContainer = docker.getContainer(containerName);
|
|
||||||
await newContainer.start();
|
|
||||||
console.log("Caddy container started successfully");
|
|
||||||
} catch (error: any) {
|
|
||||||
if (error?.json?.message?.includes("port is already allocated")) {
|
|
||||||
console.log("Ports still in use, waiting longer for cleanup...");
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 10000));
|
|
||||||
// Try one more time
|
|
||||||
await docker.createContainer(settings);
|
|
||||||
const newContainer = docker.getContainer(containerName);
|
|
||||||
await newContainer.start();
|
|
||||||
console.log("Caddy container started successfully after retry");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Failed to initialize Caddy:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const createDefaultServerCaddyConfig = () => {
|
|
||||||
const { CADDY_DYNAMIC_PATH } = paths();
|
|
||||||
const configFilePath = path.join(CADDY_DYNAMIC_PATH, "Caddyfile");
|
|
||||||
|
|
||||||
if (existsSync(configFilePath)) {
|
|
||||||
console.log("Default caddy config already exists");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const appName = "dokploy";
|
|
||||||
const serviceURLDefault = `http://${appName}:${process.env.PORT || 3000}`;
|
|
||||||
const config: FileConfig = {
|
|
||||||
http: {
|
|
||||||
routers: {
|
|
||||||
[`${appName}-router-app`]: {
|
|
||||||
rule: `Host(\`${appName}.docker.localhost\`) && PathPrefix(\`/\`)`,
|
|
||||||
service: `${appName}-service-app`,
|
|
||||||
entryPoints: ["web"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
services: {
|
|
||||||
[`${appName}-service-app`]: {
|
|
||||||
loadBalancer: {
|
|
||||||
servers: [{ url: serviceURLDefault }],
|
|
||||||
passHostHeader: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const yamlStr = dump(config);
|
|
||||||
mkdirSync(CADDY_DYNAMIC_PATH, { recursive: true });
|
|
||||||
writeFileSync(path.join(CADDY_DYNAMIC_PATH, `Caddyfile`), yamlStr, "utf8");
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getDefaultCaddyConfig = () => {
|
|
||||||
const configObject: MainTraefikConfig = {
|
|
||||||
providers: {
|
|
||||||
...(process.env.NODE_ENV === "development"
|
|
||||||
? {
|
|
||||||
docker: {
|
|
||||||
defaultRule:
|
|
||||||
"Host(`{{ trimPrefix `/` .Name }}.docker.localhost`)",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
swarm: {
|
|
||||||
exposedByDefault: false,
|
|
||||||
watch: true,
|
|
||||||
},
|
|
||||||
docker: {
|
|
||||||
exposedByDefault: false,
|
|
||||||
watch: true,
|
|
||||||
network: "dokploy-network",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
file: {
|
|
||||||
directory: "/etc/dokploy/traefik/dynamic",
|
|
||||||
watch: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
entryPoints: {
|
|
||||||
web: {
|
|
||||||
address: `:${TRAEFIK_PORT}`,
|
|
||||||
},
|
|
||||||
websecure: {
|
|
||||||
address: `:${TRAEFIK_SSL_PORT}`,
|
|
||||||
http3: {
|
|
||||||
advertisedPort: TRAEFIK_HTTP3_PORT,
|
|
||||||
},
|
|
||||||
...(process.env.NODE_ENV === "production" && {
|
|
||||||
http: {
|
|
||||||
tls: {
|
|
||||||
certResolver: "letsencrypt",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
api: {
|
|
||||||
insecure: true,
|
|
||||||
},
|
|
||||||
...(process.env.NODE_ENV === "production" && {
|
|
||||||
certificatesResolvers: {
|
|
||||||
letsencrypt: {
|
|
||||||
acme: {
|
|
||||||
email: "test@localhost.com",
|
|
||||||
storage: "/etc/dokploy/traefik/dynamic/acme.json",
|
|
||||||
httpChallenge: {
|
|
||||||
entryPoint: "web",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
const yamlStr = dump(configObject);
|
|
||||||
|
|
||||||
return yamlStr;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getDefaultServerTraefikConfig = () => {
|
|
||||||
const configObject: MainTraefikConfig = {
|
|
||||||
providers: {
|
|
||||||
swarm: {
|
|
||||||
exposedByDefault: false,
|
|
||||||
watch: true,
|
|
||||||
},
|
|
||||||
docker: {
|
|
||||||
exposedByDefault: false,
|
|
||||||
watch: true,
|
|
||||||
network: "dokploy-network",
|
|
||||||
},
|
|
||||||
file: {
|
|
||||||
directory: "/etc/dokploy/traefik/dynamic",
|
|
||||||
watch: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
entryPoints: {
|
|
||||||
web: {
|
|
||||||
address: `:${TRAEFIK_PORT}`,
|
|
||||||
},
|
|
||||||
websecure: {
|
|
||||||
address: `:${TRAEFIK_SSL_PORT}`,
|
|
||||||
http3: {
|
|
||||||
advertisedPort: TRAEFIK_HTTP3_PORT,
|
|
||||||
},
|
|
||||||
http: {
|
|
||||||
tls: {
|
|
||||||
certResolver: "letsencrypt",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
api: {
|
|
||||||
insecure: true,
|
|
||||||
},
|
|
||||||
certificatesResolvers: {
|
|
||||||
letsencrypt: {
|
|
||||||
acme: {
|
|
||||||
email: "test@localhost.com",
|
|
||||||
storage: "/etc/dokploy/traefik/dynamic/acme.json",
|
|
||||||
httpChallenge: {
|
|
||||||
entryPoint: "web",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const yamlStr = dump(configObject);
|
|
||||||
|
|
||||||
return yamlStr;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const createDefaultCaddyConfig = () => {
|
|
||||||
const { CADDY_PATH, CADDY_DYNAMIC_PATH } = paths();
|
|
||||||
const mainConfig = path.join(CADDY_PATH, "Caddyfile");
|
|
||||||
const acmeJsonPath = path.join(CADDY_DYNAMIC_PATH, "acme.json");
|
|
||||||
|
|
||||||
if (existsSync(acmeJsonPath)) {
|
|
||||||
chmodSync(acmeJsonPath, "600");
|
|
||||||
}
|
|
||||||
if (existsSync(mainConfig)) {
|
|
||||||
console.log("Main config already exists");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const yamlStr = getDefaultCaddyConfig();
|
|
||||||
mkdirSync(CADDY_PATH, { recursive: true });
|
|
||||||
writeFileSync(mainConfig, yamlStr, "utf8");
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getDefaultMiddlewares = () => {
|
|
||||||
const defaultMiddlewares = {
|
|
||||||
http: {
|
|
||||||
middlewares: {
|
|
||||||
"redirect-to-https": {
|
|
||||||
redirectScheme: {
|
|
||||||
scheme: "https",
|
|
||||||
permanent: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const yamlStr = dump(defaultMiddlewares);
|
|
||||||
return yamlStr;
|
|
||||||
};
|
|
||||||
export const createDefaultMiddlewares = () => {
|
|
||||||
const { DYNAMIC_TRAEFIK_PATH } = paths();
|
|
||||||
const middlewaresPath = path.join(DYNAMIC_TRAEFIK_PATH, "middlewares.yml");
|
|
||||||
if (existsSync(middlewaresPath)) {
|
|
||||||
console.log("Default middlewares already exists");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const yamlStr = getDefaultMiddlewares();
|
|
||||||
mkdirSync(DYNAMIC_TRAEFIK_PATH, { recursive: true });
|
|
||||||
writeFileSync(middlewaresPath, yamlStr, "utf8");
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user