Merge branch 'canary' into feat/middleware-configuration

This commit is contained in:
Mauricio Siu
2026-04-04 09:39:21 -06:00
665 changed files with 303868 additions and 37981 deletions
@@ -5,7 +5,7 @@ import { paths } from "@dokploy/server/constants";
import type { Domain } from "@dokploy/server/services/domain";
import { parse, stringify } from "yaml";
import { encodeBase64 } from "../docker/utils";
import { execAsyncRemote } from "../process/execAsync";
import { execAsync, execAsyncRemote } from "../process/execAsync";
import type { FileConfig, HttpLoadBalancerService } from "./file-types";
export const createTraefikConfig = (appName: string) => {
@@ -57,18 +57,16 @@ export const removeTraefikConfig = async (
try {
const { DYNAMIC_TRAEFIK_PATH } = paths(!!serverId);
const configPath = path.join(DYNAMIC_TRAEFIK_PATH, `${appName}.yml`);
const command = `rm -f ${configPath}`;
if (serverId) {
await execAsyncRemote(serverId, `rm ${configPath}`);
await execAsyncRemote(serverId, command);
} else {
if (fs.existsSync(configPath)) {
await fs.promises.unlink(configPath);
}
await execAsync(command);
}
if (fs.existsSync(configPath)) {
await fs.promises.unlink(configPath);
}
} catch {}
} catch (error) {
console.error(`Error removing traefik config for ${appName}:`, error);
}
};
export const removeTraefikConfigRemote = async (
@@ -78,8 +76,13 @@ export const removeTraefikConfigRemote = async (
try {
const { DYNAMIC_TRAEFIK_PATH } = paths(true);
const configPath = path.join(DYNAMIC_TRAEFIK_PATH, `${appName}.yml`);
await execAsyncRemote(serverId, `rm ${configPath}`);
} catch {}
await execAsyncRemote(serverId, `rm -f ${configPath}`);
} catch (error) {
console.error(
`Error removing remote traefik config for ${appName}:`,
error,
);
}
};
export const loadOrCreateConfig = (appName: string): FileConfig => {
+35 -16
View File
@@ -32,10 +32,10 @@ export const manageDomain = async (app: ApplicationNested, domain: Domain) => {
config.http.routers[routerName] = await createRouterConfig(
app,
domain,
"web",
domain.customEntrypoint || "web",
);
if (domain.https) {
if (!domain.customEntrypoint && domain.https) {
config.http.routers[routerNameSecure] = await createRouterConfig(
app,
domain,
@@ -104,18 +104,40 @@ export const removeDomain = async (
}
};
/**
* Converts an internationalized domain name (IDN) to ASCII punycode format.
* Traefik requires domain names in ASCII format, so non-ASCII characters
* must be converted (e.g., "тест.рф" → "xn--e1aybc.xn--p1ai").
*/
const toPunycode = (host: string): string => {
try {
return new URL(`http://${host}`).hostname;
} catch {
// If URL parsing fails, return the original host
return host;
}
};
export const createRouterConfig = async (
app: ApplicationNested,
domain: Domain,
entryPoint: "web" | "websecure",
entryPoint: string,
) => {
const { appName, redirects, security } = app;
const { certificateType } = domain;
const { host, path, https, uniqueConfigKey, internalPath, stripPath } =
domain;
const {
host,
path,
https,
uniqueConfigKey,
internalPath,
stripPath,
customEntrypoint,
} = domain;
const punycodeHost = toPunycode(host);
const routerConfig: HttpRouter = {
rule: `Host(\`${host}\`)${path !== null && path !== "/" ? ` && PathPrefix(\`${path}\`)` : ""}`,
rule: `Host(\`${punycodeHost}\`)${path !== null && path !== "/" ? ` && PathPrefix(\`${path}\`)` : ""}`,
service: `${appName}-service-${uniqueConfigKey}`,
middlewares: [],
entryPoints: [entryPoint],
@@ -137,16 +159,13 @@ export const createRouterConfig = async (
}
if ((entryPoint === "websecure" && https) || !https) {
// redirects
for (const redirect of redirects) {
let middlewareName = `redirect-${appName}-${redirect.uniqueConfigKey}`;
if (domain.domainType === "preview") {
middlewareName = `redirect-${appName.replace(
/^preview-(.+)-[^-]+$/,
"$1",
)}-${redirect.uniqueConfigKey}`;
// redirects - skip for preview deployments as wildcard subdomains
// should not inherit parent redirect rules (e.g., www-redirect)
if (domain.domainType !== "preview") {
for (const redirect of redirects) {
const middlewareName = `redirect-${appName}-${redirect.uniqueConfigKey}`;
routerConfig.middlewares?.push(middlewareName);
}
routerConfig.middlewares?.push(middlewareName);
}
// security
@@ -167,7 +186,7 @@ export const createRouterConfig = async (
}
}
if (entryPoint === "websecure") {
if (entryPoint === "websecure" || (customEntrypoint && https)) {
if (certificateType === "letsencrypt") {
routerConfig.tls = { certResolver: "letsencrypt" };
} else if (certificateType === "custom" && domain.customCertResolver) {