Fix traefik config merge

This commit is contained in:
Owen 2025-08-16 12:07:15 -07:00
parent 7bf98c0c40
commit f07cd8aee3
No known key found for this signature in database
GPG key ID: 8271FDFFD9E0CCBD

View file

@ -94,94 +94,94 @@ export async function getTraefikConfig(exitNodeId: number): Promise<any> {
// Get all resources with related data // Get all resources with related data
const allResources = await db.transaction(async (tx) => { const allResources = await db.transaction(async (tx) => {
// Get resources with their targets and sites in a single optimized query // Get resources with their targets and sites in a single optimized query
// Start from sites on this exit node, then join to targets and resources // Start from sites on this exit node, then join to targets and resources
const resourcesWithTargetsAndSites = await tx const resourcesWithTargetsAndSites = await tx
.select({ .select({
// Resource fields // Resource fields
resourceId: resources.resourceId, resourceId: resources.resourceId,
fullDomain: resources.fullDomain, fullDomain: resources.fullDomain,
ssl: resources.ssl, ssl: resources.ssl,
http: resources.http, http: resources.http,
proxyPort: resources.proxyPort, proxyPort: resources.proxyPort,
protocol: resources.protocol, protocol: resources.protocol,
subdomain: resources.subdomain, subdomain: resources.subdomain,
domainId: resources.domainId, domainId: resources.domainId,
enabled: resources.enabled, enabled: resources.enabled,
stickySession: resources.stickySession, stickySession: resources.stickySession,
tlsServerName: resources.tlsServerName, tlsServerName: resources.tlsServerName,
setHostHeader: resources.setHostHeader, setHostHeader: resources.setHostHeader,
enableProxy: resources.enableProxy, enableProxy: resources.enableProxy,
// Target fields // Target fields
targetId: targets.targetId, targetId: targets.targetId,
targetEnabled: targets.enabled, targetEnabled: targets.enabled,
ip: targets.ip, ip: targets.ip,
method: targets.method, method: targets.method,
port: targets.port, port: targets.port,
internalPort: targets.internalPort, internalPort: targets.internalPort,
// Site fields // Site fields
siteId: sites.siteId, siteId: sites.siteId,
siteType: sites.type, siteType: sites.type,
subnet: sites.subnet, subnet: sites.subnet,
exitNodeId: sites.exitNodeId exitNodeId: sites.exitNodeId
}) })
.from(sites) .from(sites)
.innerJoin(targets, eq(targets.siteId, sites.siteId)) .innerJoin(targets, eq(targets.siteId, sites.siteId))
.innerJoin(resources, eq(resources.resourceId, targets.resourceId)) .innerJoin(resources, eq(resources.resourceId, targets.resourceId))
.where( .where(
and( and(
eq(targets.enabled, true), eq(targets.enabled, true),
eq(resources.enabled, true), eq(resources.enabled, true),
or( or(
eq(sites.exitNodeId, currentExitNodeId), eq(sites.exitNodeId, currentExitNodeId),
isNull(sites.exitNodeId) isNull(sites.exitNodeId)
)
) )
); )
);
// Group by resource and include targets with their unique site data // Group by resource and include targets with their unique site data
const resourcesMap = new Map(); const resourcesMap = new Map();
resourcesWithTargetsAndSites.forEach((row) => { resourcesWithTargetsAndSites.forEach((row) => {
const resourceId = row.resourceId; const resourceId = row.resourceId;
if (!resourcesMap.has(resourceId)) { if (!resourcesMap.has(resourceId)) {
resourcesMap.set(resourceId, { resourcesMap.set(resourceId, {
resourceId: row.resourceId,
fullDomain: row.fullDomain,
ssl: row.ssl,
http: row.http,
proxyPort: row.proxyPort,
protocol: row.protocol,
subdomain: row.subdomain,
domainId: row.domainId,
enabled: row.enabled,
stickySession: row.stickySession,
tlsServerName: row.tlsServerName,
setHostHeader: row.setHostHeader,
enableProxy: row.enableProxy,
targets: []
});
}
// Add target with its associated site data
resourcesMap.get(resourceId).targets.push({
resourceId: row.resourceId, resourceId: row.resourceId,
targetId: row.targetId, fullDomain: row.fullDomain,
ip: row.ip, ssl: row.ssl,
method: row.method, http: row.http,
port: row.port, proxyPort: row.proxyPort,
internalPort: row.internalPort, protocol: row.protocol,
enabled: row.targetEnabled, subdomain: row.subdomain,
site: { domainId: row.domainId,
siteId: row.siteId, enabled: row.enabled,
type: row.siteType, stickySession: row.stickySession,
subnet: row.subnet, tlsServerName: row.tlsServerName,
exitNodeId: row.exitNodeId setHostHeader: row.setHostHeader,
} enableProxy: row.enableProxy,
targets: []
}); });
}); }
return Array.from(resourcesMap.values()); // Add target with its associated site data
resourcesMap.get(resourceId).targets.push({
resourceId: row.resourceId,
targetId: row.targetId,
ip: row.ip,
method: row.method,
port: row.port,
internalPort: row.internalPort,
enabled: row.targetEnabled,
site: {
siteId: row.siteId,
type: row.siteType,
subnet: row.subnet,
exitNodeId: row.exitNodeId
}
});
});
return Array.from(resourcesMap.values());
}); });
if (!allResources.length) { if (!allResources.length) {
@ -299,194 +299,7 @@ export async function getTraefikConfig(exitNodeId: number): Promise<any> {
middlewares: [redirectHttpsMiddlewareName], middlewares: [redirectHttpsMiddlewareName],
service: serviceName, service: serviceName,
rule: `Host(\`${fullDomain}\`)`, rule: `Host(\`${fullDomain}\`)`,
<<<<<<< HEAD
priority: 100 priority: 100
=======
priority: 100,
...(resource.ssl ? { tls } : {})
};
if (resource.ssl) {
config_output.http.routers![routerName + "-redirect"] = {
entryPoints: [
config.getRawConfig().traefik.http_entrypoint
],
middlewares: [redirectHttpsMiddlewareName],
service: serviceName,
rule: `Host(\`${fullDomain}\`)`,
priority: 100
};
}
config_output.http.services![serviceName] = {
loadBalancer: {
servers: targets
.filter((target: TargetWithSite) => {
if (!target.enabled) {
return false;
}
if (
target.site.type === "local" ||
target.site.type === "wireguard"
) {
if (
!target.ip ||
!target.port ||
!target.method
) {
return false;
}
} else if (target.site.type === "newt") {
if (
!target.internalPort ||
!target.method ||
!target.site.subnet
) {
return false;
}
}
return true;
})
.map((target: TargetWithSite) => {
if (
target.site.type === "local" ||
target.site.type === "wireguard"
) {
return {
url: `${target.method}://${target.ip}:${target.port}`
};
} else if (target.site.type === "newt") {
const ip = target.site.subnet!.split("/")[0];
return {
url: `${target.method}://${ip}:${target.internalPort}`
};
}
}),
...(resource.stickySession
? {
sticky: {
cookie: {
name: "p_sticky", // TODO: make this configurable via config.yml like other cookies
secure: resource.ssl,
httpOnly: true
}
}
}
: {})
}
};
// Add the serversTransport if TLS server name is provided
if (resource.tlsServerName) {
if (!config_output.http.serversTransports) {
config_output.http.serversTransports = {};
}
config_output.http.serversTransports![transportName] = {
serverName: resource.tlsServerName,
//unfortunately the following needs to be set. traefik doesn't merge the default serverTransport settings
// if defined in the static config and here. if not set, self-signed certs won't work
insecureSkipVerify: true
};
config_output.http.services![
serviceName
].loadBalancer.serversTransport = transportName;
}
// Add the host header middleware
if (resource.setHostHeader) {
if (!config_output.http.middlewares) {
config_output.http.middlewares = {};
}
config_output.http.middlewares[hostHeaderMiddlewareName] = {
headers: {
customRequestHeaders: {
Host: resource.setHostHeader
}
}
};
if (!config_output.http.routers![routerName].middlewares) {
config_output.http.routers![routerName].middlewares =
[];
}
config_output.http.routers![routerName].middlewares = [
...config_output.http.routers![routerName].middlewares,
hostHeaderMiddlewareName
];
}
} else {
// Non-HTTP (TCP/UDP) configuration
if (!resource.enableProxy) {
continue;
}
const protocol = resource.protocol.toLowerCase();
const port = resource.proxyPort;
if (!port) {
continue;
}
if (!config_output[protocol]) {
config_output[protocol] = {
routers: {},
services: {}
};
}
config_output[protocol].routers[routerName] = {
entryPoints: [`${protocol}-${port}`],
service: serviceName,
...(protocol === "tcp" ? { rule: "HostSNI(`*`)" } : {})
};
config_output[protocol].services[serviceName] = {
loadBalancer: {
servers: targets
.filter((target: TargetWithSite) => {
if (!target.enabled) {
return false;
}
if (
target.site.type === "local" ||
target.site.type === "wireguard"
) {
if (!target.ip || !target.port) {
return false;
}
} else if (target.site.type === "newt") {
if (!target.internalPort || !target.site.subnet) {
return false;
}
}
return true;
})
.map((target: TargetWithSite) => {
if (
target.site.type === "local" ||
target.site.type === "wireguard"
) {
return {
address: `${target.ip}:${target.port}`
};
} else if (target.site.type === "newt") {
const ip = target.site.subnet!.split("/")[0];
return {
address: `${ip}:${target.internalPort}`
};
}
}),
...(resource.stickySession
? {
sticky: {
ipStrategy: {
depth: 0,
sourcePort: true
}
}
}
: {})
}
>>>>>>> dev
}; };
} }