Merge branch 'canary' into feature/custom-entrypoint

This commit is contained in:
Mauricio Siu
2026-03-30 16:10:53 -06:00
639 changed files with 267188 additions and 37714 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 => {
+22 -10
View File
@@ -104,6 +104,20 @@ 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,
@@ -121,8 +135,9 @@ export const createRouterConfig = async (
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],
@@ -144,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
@@ -1,7 +1,7 @@
import { existsSync, readFileSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { paths } from "@dokploy/server/constants";
import type { User } from "@dokploy/server/services/user";
import type { webServerSettings } from "@dokploy/server/db/schema/web-server-settings";
import { parse, stringify } from "yaml";
import {
loadOrCreateConfig,
@@ -12,10 +12,10 @@ import type { FileConfig } from "./file-types";
import type { MainTraefikConfig } from "./types";
export const updateServerTraefik = (
user: User | null,
settings: typeof webServerSettings.$inferSelect | null,
newHost: string | null,
) => {
const { https, certificateType } = user || {};
const { https, certificateType } = settings || {};
const appName = "dokploy";
const config: FileConfig = loadOrCreateConfig(appName);