Working on inference resource management

This commit is contained in:
Owen
2026-08-04 11:48:36 -04:00
parent a7e44944fb
commit 0b30cfc341
6 changed files with 87 additions and 29 deletions
+14 -5
View File
@@ -1177,12 +1177,12 @@ async function syncClientExitNodeConnections(
const connectPayloads: { const connectPayloads: {
clientId: string; clientId: string;
message: { type: string; data: any }; message: { type: string; data: any };
options: { compress: boolean }; options: { compress: boolean; incrementConfigVersion: boolean };
}[] = []; }[] = [];
const disconnectPayloads: { const disconnectPayloads: {
clientId: string; clientId: string;
message: { type: string; data: any }; message: { type: string; data: any };
options: { compress: boolean }; options: { compress: boolean; incrementConfigVersion: boolean };
}[] = []; }[] = [];
for (const client of clientsData) { for (const client of clientsData) {
@@ -1218,7 +1218,10 @@ async function syncClientExitNodeConnections(
tunnelIP: client.exitNodeSubnet.split("/")[0] tunnelIP: client.exitNodeSubnet.split("/")[0]
} }
}, },
options: { compress: canCompress(olm.version, "olm") } options: {
compress: canCompress(olm.version, "olm"),
incrementConfigVersion: true
}
}); });
} else { } else {
disconnectPayloads.push({ disconnectPayloads.push({
@@ -1227,7 +1230,10 @@ async function syncClientExitNodeConnections(
type: "olm/wg/exitnode/disconnect", type: "olm/wg/exitnode/disconnect",
data: {} data: {}
}, },
options: { compress: canCompress(olm.version, "olm") } options: {
compress: canCompress(olm.version, "olm"),
incrementConfigVersion: true
}
}); });
} }
} }
@@ -1293,7 +1299,10 @@ async function syncClientExitNodeAliasUpdate(
newAliases newAliases
} }
}, },
options: { compress: canCompress(olm.version, "olm") } options: {
compress: canCompress(olm.version, "olm"),
incrementConfigVersion: true // this is important information we would need to sync
}
})); }));
if (updatePayloads.length > 0) { if (updatePayloads.length > 0) {
+35 -8
View File
@@ -1,6 +1,7 @@
import { import {
Client, Client,
db, db,
ExitNode,
exitNodes, exitNodes,
Olm, Olm,
sites, sites,
@@ -48,12 +49,26 @@ export async function sendOlmSyncMessage(olm: Olm, client: Client) {
} }
// NOTE: WE ARE HARDCODING THE RELAY PARAMETER TO FALSE HERE BUT IN THE REGISTER MESSAGE ITS DEFINED BY THE CLIENT // NOTE: WE ARE HARDCODING THE RELAY PARAMETER TO FALSE HERE BUT IN THE REGISTER MESSAGE ITS DEFINED BY THE CLIENT
const siteConfigurations = await buildSiteConfigurationForOlmClient( const { siteConfigurations, exitNodeAliases } =
client, await buildSiteConfigurationForOlmClient(
client.pubKey, client,
false, client.pubKey,
jitMode false,
); jitMode
);
// The exit node the client itself is assigned to (for site resources hosted
// on it, e.g. inference), same as what's sent in the initial olm/wg/connect
// message. This is separate from exitNodesData below, which is only the set
// of exit nodes used for hole punching to reach site peers.
let clientExitNode: ExitNode | null = null;
if (client.exitNodeId) {
[clientExitNode] = await db
.select()
.from(exitNodes)
.where(eq(exitNodes.exitNodeId, client.exitNodeId))
.limit(1);
}
// Get all exit nodes from sites where the client has peers // Get all exit nodes from sites where the client has peers
const clientSites = await db const clientSites = await db
@@ -113,11 +128,23 @@ export async function sendOlmSyncMessage(olm: Olm, client: Client) {
type: "olm/sync", type: "olm/sync",
data: { data: {
sites: siteConfigurations, sites: siteConfigurations,
exitNodes: exitNodesData exitNodes: exitNodesData, // this is for the holepunch information
// this is for the backhaul connection to the exit node
exitNode:
clientExitNode && client.exitNodeSubnet
? {
aliases: exitNodeAliases,
connect: exitNodeAliases.length > 0, // we do not need to connect to the exit node if we do not have inference resources and right now all site resources on the exit node have an alias
endpoint: `${clientExitNode.endpoint}:${clientExitNode.listenPort}`,
publicKey: clientExitNode.publicKey,
serverIP: clientExitNode.address.split("/")[0],
tunnelIP: client.exitNodeSubnet.split("/")[0]
}
: undefined
} }
}, },
{ {
compress: canCompress(olm.version, "olm") compress: canCompress(olm.version, "olm") // we dont increment the version here or we could get into a loop!
} }
).catch((error) => { ).catch((error) => {
logger.warn(`Error sending olm sync message:`, error); logger.warn(`Error sending olm sync message:`, error);
@@ -571,7 +571,7 @@ export async function createSiteResource(
} }
let tcpPortRangeStringAdjusted = tcpPortRangeString; let tcpPortRangeStringAdjusted = tcpPortRangeString;
if (mode === "http") { if (mode === "http" || mode === "inference") {
tcpPortRangeStringAdjusted = "443,80"; tcpPortRangeStringAdjusted = "443,80";
} else if (mode === "ssh") { } else if (mode === "ssh") {
tcpPortRangeStringAdjusted = destinationPort tcpPortRangeStringAdjusted = destinationPort
@@ -594,12 +594,14 @@ export async function createSiteResource(
aliasAddress, aliasAddress,
tcpPortRangeString: tcpPortRangeStringAdjusted, tcpPortRangeString: tcpPortRangeStringAdjusted,
udpPortRangeString: udpPortRangeString:
mode == "http" || mode == "ssh" mode == "http" || mode == "ssh" || mode == "inference"
? "" ? ""
: udpPortRangeString, : udpPortRangeString,
disableIcmp: disableIcmp:
disableIcmp || disableIcmp ||
(mode == "http" || mode == "ssh" ? true : false), // default to true for http resources, otherwise false (mode == "http" || mode == "ssh" || mode == "inference"
? true
: false), // default to true for http resources, otherwise false
domainId, domainId,
subdomain: finalSubdomain, subdomain: finalSubdomain,
fullDomain, fullDomain,
@@ -166,8 +166,11 @@ const updateSiteResourceSchema = z
if (data.mode === undefined && data.destination === undefined) { if (data.mode === undefined && data.destination === undefined) {
return true; return true;
} }
// destination is only optional for ssh mode with native authDaemonMode // destination is only optional for ssh mode with native authDaemonMode or inference
if (data.mode === "ssh" && data.authDaemonMode === "native") { if (
(data.mode === "ssh" && data.authDaemonMode === "native") ||
data.mode == "inference"
) {
return true; return true;
} }
return ( return (
@@ -558,8 +561,9 @@ export async function updateSiteResource(
}) })
} }
: {}; : {};
let tcpPortRangeStringAdjusted = tcpPortRangeString; let tcpPortRangeStringAdjusted = tcpPortRangeString;
if (mode === "http") { if (mode === "http" || mode == "inference") {
tcpPortRangeStringAdjusted = "443,80"; tcpPortRangeStringAdjusted = "443,80";
} else if (mode === "ssh") { } else if (mode === "ssh") {
tcpPortRangeStringAdjusted = destinationPort tcpPortRangeStringAdjusted = destinationPort
@@ -583,20 +587,20 @@ export async function updateSiteResource(
? alias ? alias
? alias.trim() ? alias.trim()
: null : null
: mode !== undefined && : undefined,
mode !== "host" &&
mode !== "ssh"
? null
: undefined,
tcpPortRangeString: tcpPortRangeStringAdjusted, tcpPortRangeString: tcpPortRangeStringAdjusted,
udpPortRangeString: udpPortRangeString:
mode == "http" || mode == "ssh" mode == "http" || mode == "ssh" || mode == "inference"
? "" ? ""
: udpPortRangeString, : udpPortRangeString,
disableIcmp: disableIcmp:
mode !== undefined mode !== undefined
? disableIcmp || ? disableIcmp ||
(mode == "http" || mode == "ssh" ? true : false) (mode == "http" ||
mode == "ssh" ||
mode == "inference"
? true
: false)
: disableIcmp, : disableIcmp,
domainId, domainId,
subdomain: finalSubdomain, subdomain: finalSubdomain,
@@ -20,9 +20,7 @@ import { useTranslations } from "next-intl";
import { useActionState, useMemo, useState } from "react"; import { useActionState, useMemo, useState } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { z } from "zod"; import { z } from "zod";
import { PrivateResourceSitesField } from "@app/components/PrivateResourceSitesField";
import { PrivateResourceInferenceDestinationFields } from "@app/components/PrivateResourceDestinationFields"; import { PrivateResourceInferenceDestinationFields } from "@app/components/PrivateResourceDestinationFields";
import { PrivateResourcePortRanges } from "@app/components/PrivateResourcePortRanges";
import { useSaveSiteResource } from "@app/hooks/useSaveSiteResource"; import { useSaveSiteResource } from "@app/hooks/useSaveSiteResource";
import { import {
asAnyControl, asAnyControl,
+19 -1
View File
@@ -211,6 +211,14 @@ export function buildCreateSiteResourcePayload(
authDaemonPort: data.authDaemonPort authDaemonPort: data.authDaemonPort
}) })
}), }),
...(data.mode === "inference" && {
alias:
data.alias &&
typeof data.alias === "string" &&
data.alias.trim()
? data.alias
: undefined
}),
...((data.mode === "host" || data.mode === "cidr") && { ...((data.mode === "host" || data.mode === "cidr") && {
tcpPortRangeString: data.tcpPortRangeString, tcpPortRangeString: data.tcpPortRangeString,
udpPortRangeString: data.udpPortRangeString, udpPortRangeString: data.udpPortRangeString,
@@ -237,7 +245,9 @@ export function buildUpdateSiteResourcePayload(
enabled: data.enabled, enabled: data.enabled,
...(isNativeSsh ...(isNativeSsh
? { destination: null, destinationPort: null } ? { destination: null, destinationPort: null }
: { destination: data.destination ?? undefined }), : data.mode !== "inference"
? { destination: data.destination ?? undefined }
: {}),
...(data.mode === "http" && { ...(data.mode === "http" && {
scheme: data.scheme, scheme: data.scheme,
ssl: data.ssl ?? false, ssl: data.ssl ?? false,
@@ -281,6 +291,14 @@ export function buildUpdateSiteResourcePayload(
authDaemonPort: data.authDaemonPort || null authDaemonPort: data.authDaemonPort || null
}) })
}), }),
...(data.mode === "inference" && {
alias:
data.alias &&
typeof data.alias === "string" &&
data.alias.trim()
? data.alias
: null
}),
...((data.mode === "host" || data.mode === "cidr") && { ...((data.mode === "host" || data.mode === "cidr") && {
tcpPortRangeString: data.tcpPortRangeString, tcpPortRangeString: data.tcpPortRangeString,
udpPortRangeString: data.udpPortRangeString, udpPortRangeString: data.udpPortRangeString,