@wtfalch/foundry 0.41.0 → 0.41.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/plan/executor.js
CHANGED
|
@@ -5975,6 +5975,7 @@ export class FoundryStepExecutor {
|
|
|
5975
5975
|
apex: ownHostnames(org).zone,
|
|
5976
5976
|
version: action.desired.version,
|
|
5977
5977
|
project: { ensure: () => this.ensureCoolifyProject(org, context) },
|
|
5978
|
+
...(context.serverIpv4 ? { serverIpv4: context.serverIpv4 } : {}),
|
|
5978
5979
|
});
|
|
5979
5980
|
}
|
|
5980
5981
|
async jobsRegistration(action, org, context) {
|
package/dist/plan/own-diff.d.ts
CHANGED
|
@@ -135,7 +135,7 @@ export interface PlanOwnSfuOptions {
|
|
|
135
135
|
/**
|
|
136
136
|
* An own org (`services.own`) with calls on runs its own LiveKit media server
|
|
137
137
|
* as a Coolify app. Applied once, and again when the pinned LiveKit version,
|
|
138
|
-
* the slot or the hostname changed, or an earlier run died before the deploy
|
|
138
|
+
* the slot or the hostname changed, no `node_ip` is recorded (applied before 0.41.2), or an earlier run died before the deploy
|
|
139
139
|
* finished. `firewall` is the one line that says which ports the server must
|
|
140
140
|
* have open: foundry opens none, so it stays until the host confirms them.
|
|
141
141
|
* Every line is fixed text: it is part of the stale-plan comparison.
|
package/dist/plan/own-diff.js
CHANGED
|
@@ -9,7 +9,7 @@ import { OWN_MAIL_SMTP_INTERNAL_SCOPE_KEY, OWN_MAIL_SMTP_PORT_BASE, OWN_MAIL_SMT
|
|
|
9
9
|
import { mailStoreIsLegacy, mailStoreSwitchDescription } from './mail-store.js';
|
|
10
10
|
import { ownHostnames } from './own-hostnames.js';
|
|
11
11
|
import { OWN_FILES_R2_SCOPE_KEY, OWN_SERVICES_APPLIED_SCOPE_KEY, orgTarget, } from './own-services.js';
|
|
12
|
-
import { OWN_SFU_APPLIED_HOSTNAME_SCOPE_KEY, OWN_SFU_APPLIED_SLOT_SCOPE_KEY, OWN_SFU_APPLIED_VERSION_SCOPE_KEY, OWN_SFU_DEPLOY_PENDING_SCOPE_KEY, OWN_SFU_KEYS_UNDELIVERED_SCOPE_KEY, SFU_INTERNAL_URL_SCOPE_KEY, SFU_PUBLIC_URL_SCOPE_KEY, } from './own-sfu.js';
|
|
12
|
+
import { OWN_SFU_APPLIED_HOSTNAME_SCOPE_KEY, OWN_SFU_APPLIED_NODE_IP_SCOPE_KEY, OWN_SFU_APPLIED_SLOT_SCOPE_KEY, OWN_SFU_APPLIED_VERSION_SCOPE_KEY, OWN_SFU_DEPLOY_PENDING_SCOPE_KEY, OWN_SFU_KEYS_UNDELIVERED_SCOPE_KEY, SFU_INTERNAL_URL_SCOPE_KEY, SFU_PUBLIC_URL_SCOPE_KEY, } from './own-sfu.js';
|
|
13
13
|
import { AUTH_ZITADEL_RUN_OPTIONS, JOBS_DEPLOY_PENDING_SCOPE_KEY, JOBS_INTERNAL_URL_SCOPE_KEY, PLATFORM_AUTH_ADMIN_UNDELIVERED_SCOPE_KEY, PLATFORM_AUTH_ADMIN_USER_SCOPE_KEY, PLATFORM_AUTH_BROKER_SCOPE_KEY, PLATFORM_AUTH_CONNECTOR_APP_SCOPE_KEY, PLATFORM_AUTH_INSTANCE_SCOPE_KEY, PLATFORM_AUTH_INSTANCE_UNDELIVERED_SCOPE_KEY, PLATFORM_AUTH_LOGIN_CLIENT_UNDELIVERED_SCOPE_KEY, PLATFORM_AUTH_LOGIN_CLIENT_USER_SCOPE_KEY, PLATFORM_AUTH_SMTP_SCOPE_KEY, PLATFORM_AUTH_ZITADEL_RUN_OPTIONS_SCOPE_KEY, PLATFORM_FILES_APPLIED_GIT_REF_SCOPE_KEY, PLATFORM_FILES_APPLIED_HOSTNAME_SCOPE_KEY, PLATFORM_FILES_INTERNAL_URL_SCOPE_KEY, PLATFORM_FILES_INTROSPECTION_SCOPE_KEY, PLATFORM_FILES_INTROSPECTION_UNDELIVERED_SCOPE_KEY, PLATFORM_FILES_MANAGEMENT_KEY_SCOPE_KEY, PLATFORM_FILES_MANAGEMENT_UNDELIVERED_SCOPE_KEY, PLATFORM_MAIL_ADMIN_KEY_SCOPE_KEY, PLATFORM_MAIL_ADMIN_UNDELIVERED_SCOPE_KEY, PLATFORM_MAIL_APPLIED_GIT_REF_SCOPE_KEY, PLATFORM_MAIL_APPLIED_HOSTNAME_SCOPE_KEY, PLATFORM_MAIL_INTERNAL_URL_SCOPE_KEY, platformMailMxHost, } from './platform-diff.js';
|
|
14
14
|
import { OWN_FILES_RUNNER_SCOPE_KEY } from './platform-org.js';
|
|
15
15
|
import { JOBS_ADMIN_TOKEN_UNDELIVERED_SCOPE_KEY, JOBS_APPLIED_GIT_REF_SCOPE_KEY, PLATFORM_AUTH_DB_SCOPE_KEY, PLATFORM_AUTH_ZITADEL_SCOPE_KEY, PLATFORM_FILES_SHARE_DOMAINS_SCOPE_KEY, filesShareDomains, } from './platform-providers.js';
|
|
@@ -312,7 +312,7 @@ export const OWN_SFU_FIREWALL_KEY = 'own-sfu:firewall';
|
|
|
312
312
|
/**
|
|
313
313
|
* An own org (`services.own`) with calls on runs its own LiveKit media server
|
|
314
314
|
* as a Coolify app. Applied once, and again when the pinned LiveKit version,
|
|
315
|
-
* the slot or the hostname changed, or an earlier run died before the deploy
|
|
315
|
+
* the slot or the hostname changed, no `node_ip` is recorded (applied before 0.41.2), or an earlier run died before the deploy
|
|
316
316
|
* finished. `firewall` is the one line that says which ports the server must
|
|
317
317
|
* have open: foundry opens none, so it stays until the host confirms them.
|
|
318
318
|
* Every line is fixed text: it is part of the stale-plan comparison.
|
|
@@ -361,6 +361,7 @@ export function planOwnSfu(options) {
|
|
|
361
361
|
recordedIds[OWN_SFU_APPLIED_VERSION_SCOPE_KEY] === version &&
|
|
362
362
|
recordedIds[OWN_SFU_APPLIED_SLOT_SCOPE_KEY] === String(slot) &&
|
|
363
363
|
recordedIds[OWN_SFU_APPLIED_HOSTNAME_SCOPE_KEY] === hostname &&
|
|
364
|
+
Boolean(recordedIds[OWN_SFU_APPLIED_NODE_IP_SCOPE_KEY]) &&
|
|
364
365
|
!recordedIds[OWN_SFU_DEPLOY_PENDING_SCOPE_KEY] &&
|
|
365
366
|
Boolean(recordedIds[SFU_INTERNAL_URL_SCOPE_KEY]) &&
|
|
366
367
|
Boolean(recordedIds[SFU_PUBLIC_URL_SCOPE_KEY]);
|
package/dist/plan/own-sfu.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ export declare const OWN_SFU_DEPLOY_PENDING_SCOPE_KEY = "own_sfu_deploy_pending"
|
|
|
21
21
|
export declare const OWN_SFU_APPLIED_VERSION_SCOPE_KEY = "own_sfu_applied_version";
|
|
22
22
|
export declare const OWN_SFU_APPLIED_SLOT_SCOPE_KEY = "own_sfu_applied_slot";
|
|
23
23
|
export declare const OWN_SFU_APPLIED_HOSTNAME_SCOPE_KEY = "own_sfu_applied_hostname";
|
|
24
|
+
/** LiveKit's `node_ip` as last applied. Absent: applied before 0.41.2, when it could be `host.docker.internal`. */
|
|
25
|
+
export declare const OWN_SFU_APPLIED_NODE_IP_SCOPE_KEY = "own_sfu_applied_node_ip";
|
|
24
26
|
export declare const SFU_INTERNAL_URL_SCOPE_KEY = "sfu_internal_url";
|
|
25
27
|
export declare const SFU_PUBLIC_URL_SCOPE_KEY = "sfu_public_url";
|
|
26
28
|
export interface SfuAppDeps {
|
|
@@ -45,6 +47,8 @@ export interface SfuAppInput {
|
|
|
45
47
|
/** The pinned LiveKit release tag. */
|
|
46
48
|
version: string;
|
|
47
49
|
project: ProjectSource;
|
|
50
|
+
/** The platform's declared public IPv4: LiveKit's `node_ip`. Absent: the Coolify server's ip, when it is an IPv4. */
|
|
51
|
+
serverIpv4?: string;
|
|
48
52
|
}
|
|
49
53
|
/** The compose `ports` lines for a slot: the UDP range and the TCP fallback port, one to one. */
|
|
50
54
|
export declare function sfuComposePorts(slot: number): string[];
|
package/dist/plan/own-sfu.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isIPv4 } from 'node:net';
|
|
1
2
|
import { DIGESTS, VERSIONS } from '../bootstrap/versions.js';
|
|
2
3
|
import { mintLivekitCredentials } from '../calls-sfu-keys.js';
|
|
3
4
|
import { LIVEKIT_SIGNALLING_PORT, sfuSlotPorts } from '../calls-sfu.js';
|
|
@@ -22,6 +23,8 @@ export const OWN_SFU_DEPLOY_PENDING_SCOPE_KEY = 'own_sfu_deploy_pending';
|
|
|
22
23
|
export const OWN_SFU_APPLIED_VERSION_SCOPE_KEY = 'own_sfu_applied_version';
|
|
23
24
|
export const OWN_SFU_APPLIED_SLOT_SCOPE_KEY = 'own_sfu_applied_slot';
|
|
24
25
|
export const OWN_SFU_APPLIED_HOSTNAME_SCOPE_KEY = 'own_sfu_applied_hostname';
|
|
26
|
+
/** LiveKit's `node_ip` as last applied. Absent: applied before 0.41.2, when it could be `host.docker.internal`. */
|
|
27
|
+
export const OWN_SFU_APPLIED_NODE_IP_SCOPE_KEY = 'own_sfu_applied_node_ip';
|
|
25
28
|
export const SFU_INTERNAL_URL_SCOPE_KEY = 'sfu_internal_url';
|
|
26
29
|
export const SFU_PUBLIC_URL_SCOPE_KEY = 'sfu_public_url';
|
|
27
30
|
const KEYS_DELIVERY_ATTEMPTS = 3;
|
|
@@ -132,8 +135,12 @@ export async function provisionSfuApp(scope, deps, target, input) {
|
|
|
132
135
|
const server = servers.find((s) => s.is_usable && s.is_reachable) ?? servers[0];
|
|
133
136
|
if (!server)
|
|
134
137
|
throw new Error(`${label}: no usable Coolify server is registered`);
|
|
135
|
-
|
|
136
|
-
|
|
138
|
+
// Coolify reports its localhost server as `host.docker.internal`, which LiveKit refuses as `node_ip`
|
|
139
|
+
// and then restarts forever; the declared address wins, the same rule as the platform's mail server.
|
|
140
|
+
const nodeIp = input.serverIpv4 ?? (server.ip && isIPv4(server.ip) ? server.ip : undefined);
|
|
141
|
+
if (!nodeIp) {
|
|
142
|
+
throw new Error(`${label}: no public IPv4 to give LiveKit; declare the server's public IPv4 as serverIpv4 in the platform config`);
|
|
143
|
+
}
|
|
137
144
|
const compose = sfuCompose({
|
|
138
145
|
serviceName: target.internal.sfu,
|
|
139
146
|
slot: input.slot,
|
|
@@ -213,7 +220,7 @@ export async function provisionSfuApp(scope, deps, target, input) {
|
|
|
213
220
|
keysJustSet = true;
|
|
214
221
|
}
|
|
215
222
|
}
|
|
216
|
-
const config = sfuConfig({ slot: input.slot, nodeIp
|
|
223
|
+
const config = sfuConfig({ slot: input.slot, nodeIp, keys });
|
|
217
224
|
deps.onSecret?.(config);
|
|
218
225
|
const envChanged = liveConfig !== config;
|
|
219
226
|
const pending = Boolean(scope.recordedIds()[OWN_SFU_DEPLOY_PENDING_SCOPE_KEY]) || changed || envChanged;
|
|
@@ -278,6 +285,7 @@ export async function provisionSfuApp(scope, deps, target, input) {
|
|
|
278
285
|
scope.recordScopeId(OWN_SFU_APPLIED_VERSION_SCOPE_KEY, input.version);
|
|
279
286
|
scope.recordScopeId(OWN_SFU_APPLIED_SLOT_SCOPE_KEY, String(input.slot));
|
|
280
287
|
scope.recordScopeId(OWN_SFU_APPLIED_HOSTNAME_SCOPE_KEY, input.hostname);
|
|
288
|
+
scope.recordScopeId(OWN_SFU_APPLIED_NODE_IP_SCOPE_KEY, nodeIp);
|
|
281
289
|
scope.recordScopeId(SFU_INTERNAL_URL_SCOPE_KEY, signalling);
|
|
282
290
|
scope.recordScopeId(SFU_PUBLIC_URL_SCOPE_KEY, `https://${input.hostname}`);
|
|
283
291
|
return { resourceId: serviceId };
|
|
@@ -130,6 +130,12 @@ export interface StepExecutionContext {
|
|
|
130
130
|
* platform's Docker network, not on `co-<slug>`, so Archon reaches its database. Absent: false.
|
|
131
131
|
*/
|
|
132
132
|
readonly ownerCompany?: boolean;
|
|
133
|
+
/**
|
|
134
|
+
* The platform's declared public IPv4 (`DeclaredPlatform.serverIpv4`). A company's media server
|
|
135
|
+
* gives it to LiveKit as `node_ip`: Coolify reports its localhost server as `host.docker.internal`,
|
|
136
|
+
* which LiveKit refuses. Absent: none declared.
|
|
137
|
+
*/
|
|
138
|
+
readonly serverIpv4?: string;
|
|
133
139
|
/**
|
|
134
140
|
* Every id foundry has recorded for this org so far — both `system:kind:key`
|
|
135
141
|
* resource ids (`runSteps` records these itself from `execute`'s own return
|
package/dist/plan/plan-apply.js
CHANGED
|
@@ -908,10 +908,13 @@ export class FoundryPlanApply {
|
|
|
908
908
|
const checkpoints = [];
|
|
909
909
|
// Backed by the very `serviceIds` map this method persists once, at the
|
|
910
910
|
// end — see `StepExecutionContext`'s doc comment for why.
|
|
911
|
-
const
|
|
911
|
+
const declaredPlatform = await this.platformDeps?.store.get();
|
|
912
|
+
const ownerCompany = declaredPlatform?.ownerOrgId === orgId;
|
|
913
|
+
const serverIpv4 = declaredPlatform?.serverIpv4 ?? undefined;
|
|
912
914
|
const context = {
|
|
913
915
|
org,
|
|
914
916
|
ownerCompany,
|
|
917
|
+
...(serverIpv4 ? { serverIpv4 } : {}),
|
|
915
918
|
recordedIds: () => ({ ...serviceIds }),
|
|
916
919
|
now: () => this.now().getTime(),
|
|
917
920
|
recordScopeId: (key, id) => {
|