@rakay-technology/kraft 0.7.9 → 0.7.13
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/bare-5S7IYNHZ.js +27 -0
- package/dist/{chunk-VFPLICBX.js → chunk-3AZY56JP.js} +107 -32
- package/dist/{chunk-IGTODKUA.js → chunk-5RWL7EFH.js} +5 -5
- package/dist/{chunk-ZQJU5CTZ.js → chunk-7VMXN646.js} +1 -1
- package/dist/{chunk-DJNKEVZ7.js → chunk-AADWLI2S.js} +1 -1
- package/dist/{chunk-MOSINQAM.js → chunk-AFUXAAFQ.js} +16 -388
- package/dist/{chunk-2UQFOUSZ.js → chunk-B2CUYCGY.js} +49 -16
- package/dist/{chunk-7O6MARHJ.js → chunk-B6B42QMZ.js} +9 -9
- package/dist/{chunk-HFOE2IXZ.js → chunk-BIOW6K3V.js} +1 -1
- package/dist/{chunk-YY5DEAZI.js → chunk-BQMBJ32I.js} +2 -2
- package/dist/{chunk-ULEEWX5M.js → chunk-C3LRTROB.js} +39 -8
- package/dist/{chunk-DFVWR6JM.js → chunk-C74WJ3U4.js} +2 -2
- package/dist/{chunk-K24SBFI2.js → chunk-D2IM25JV.js} +1 -1
- package/dist/{chunk-MC4X55BW.js → chunk-DNC4A3MZ.js} +3 -3
- package/dist/{chunk-3RCXJZJD.js → chunk-E3J47WO3.js} +1 -1
- package/dist/chunk-G4VGNFGV.js +27374 -0
- package/dist/{chunk-JK7KKBXI.js → chunk-KHAT3OZP.js} +4 -4
- package/dist/{chunk-7UKBMDUF.js → chunk-MK6GYBO4.js} +9 -9
- package/dist/{chunk-SPKRI7MF.js → chunk-N7AJ2D4I.js} +96 -12
- package/dist/{chunk-ZNVAHQRY.js → chunk-Q7FAE2MB.js} +6 -6
- package/dist/{chunk-2Y62WP2D.js → chunk-QCGVPIYN.js} +2 -2
- package/dist/{chunk-PCOTSRS4.js → chunk-QLPQ5NFE.js} +3 -3
- package/dist/{chunk-DI54Y66N.js → chunk-QPUEAYB3.js} +3 -3
- package/dist/{chunk-XBGSR22I.js → chunk-XAEYWDBX.js} +53 -9
- package/dist/{chunk-HLF5PMKE.js → chunk-Y2MET6MX.js} +1 -1
- package/dist/{chunk-BN23UUSF.js → chunk-YXXWTBXB.js} +1 -1
- package/dist/{detect-N4HFQZ6Y.js → detect-NDVA2MAF.js} +4 -4
- package/dist/{docker-DU7JA2AK.js → docker-Z2ILAC7A.js} +8 -8
- package/dist/{docker-edge-executor-MPIPQHNF.js → docker-edge-executor-JID2Q2HZ.js} +7 -7
- package/dist/{edge-import-RZD7MMOE.js → edge-import-WRU5JQ43.js} +22 -22
- package/dist/{edge-preflight-6YO27PPQ.js → edge-preflight-6FYNGFIH.js} +13 -13
- package/dist/{ensure-container-edge-ZKEKC47H.js → ensure-container-edge-VFCVCXW3.js} +11 -11
- package/dist/{executor-ZWF2J7GS.js → executor-LNKX5OMQ.js} +6 -6
- package/dist/{host-channel-preflight-Z64G3NIM.js → host-channel-preflight-V7Q6GPXE.js} +22 -22
- package/dist/index.js +40 -40
- package/dist/{local-executor-W3O5HDLM.js → local-executor-NPLQMF6A.js} +3 -3
- package/dist/{nginx-XLDZIG4E.js → nginx-V6DQWKON.js} +11 -9
- package/dist/{openresty-lua-ZNE6IBYU.js → openresty-lua-OECMHHON.js} +21 -7
- package/dist/{privilege-IMARWVU2.js → privilege-KI56M7OQ.js} +5 -5
- package/dist/server/index.js +1897 -58664
- package/dist/{setup-Q6GGIJ4Q.js → setup-A2LJ4IWU.js} +12 -12
- package/dist/{ssh-client-LOCZTEUC.js → ssh-client-NRBHQJVZ.js} +2 -2
- package/dist/{up-TU7622HW.js → up-XHQK2O2M.js} +25 -25
- package/package.json +1 -1
- package/dist/bare-JM3EX7S4.js +0 -27
- package/dist/chunk-ND23EK7Y.js +0 -81645
|
@@ -5,11 +5,10 @@ const require = __ospCreateRequire(import.meta.url);
|
|
|
5
5
|
import {
|
|
6
6
|
containerCommand,
|
|
7
7
|
edgeContainerExecutor,
|
|
8
|
-
isSafeCertPath,
|
|
9
8
|
readDeclaredPair,
|
|
10
9
|
readMaybeInContainer,
|
|
11
10
|
validateCertFor
|
|
12
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-3AZY56JP.js";
|
|
13
12
|
import {
|
|
14
13
|
EdgeConflictError,
|
|
15
14
|
EdgeMigrateRequested,
|
|
@@ -24,42 +23,42 @@ import {
|
|
|
24
23
|
sanitizeEdgeVhosts,
|
|
25
24
|
sq as sq2,
|
|
26
25
|
stopTargetsForStatus
|
|
27
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-QLPQ5NFE.js";
|
|
28
27
|
import {
|
|
29
28
|
privilegedExecutor,
|
|
30
29
|
rootChecked,
|
|
31
30
|
rootOrDegrade
|
|
32
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-QPUEAYB3.js";
|
|
33
32
|
import {
|
|
34
33
|
EDGE_CHALLENGE_HOST_DIR,
|
|
35
34
|
EDGE_CONTAINER_MOUNTS,
|
|
36
35
|
EDGE_HOST_PATHS,
|
|
37
36
|
OPENRESTY_DEFAULT_PATHS
|
|
38
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-XAEYWDBX.js";
|
|
39
38
|
import {
|
|
40
39
|
waitForPortListening
|
|
41
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-QCGVPIYN.js";
|
|
42
41
|
import {
|
|
43
42
|
EDGE_CONTAINER_NAME,
|
|
44
43
|
probeExec,
|
|
45
44
|
probeExecElevated,
|
|
46
45
|
tryExec,
|
|
47
46
|
withReason
|
|
48
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-E3J47WO3.js";
|
|
49
48
|
import {
|
|
50
49
|
envOps,
|
|
51
50
|
opScript
|
|
52
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-7VMXN646.js";
|
|
53
52
|
import {
|
|
54
53
|
resolveEnvironment
|
|
55
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-BQMBJ32I.js";
|
|
56
55
|
import {
|
|
57
56
|
formatDuration,
|
|
58
57
|
systemDebug
|
|
59
58
|
} from "./chunk-3CJLKL6E.js";
|
|
60
59
|
import {
|
|
61
60
|
sq
|
|
62
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-YXXWTBXB.js";
|
|
63
62
|
import {
|
|
64
63
|
AppError,
|
|
65
64
|
PROXY_DIRECTIVES,
|
|
@@ -73,7 +72,7 @@ import {
|
|
|
73
72
|
safeErrorMessage,
|
|
74
73
|
sanitizeProxySettings,
|
|
75
74
|
shellQuote
|
|
76
|
-
} from "./chunk-
|
|
75
|
+
} from "./chunk-G4VGNFGV.js";
|
|
77
76
|
|
|
78
77
|
// ../../packages/adapters/src/system/managed-image.ts
|
|
79
78
|
import { posix } from "path";
|
|
@@ -1334,237 +1333,6 @@ async function scanApache(executor) {
|
|
|
1334
1333
|
return { proxy: "apache", sites: kept, warnings };
|
|
1335
1334
|
}
|
|
1336
1335
|
|
|
1337
|
-
// ../../packages/adapters/src/system/proxy/import/traefik.ts
|
|
1338
|
-
function lowerKeys(labels) {
|
|
1339
|
-
const out = {};
|
|
1340
|
-
for (const [k, v] of Object.entries(labels)) out[k.toLowerCase()] = v;
|
|
1341
|
-
return out;
|
|
1342
|
-
}
|
|
1343
|
-
function extractHosts(rule) {
|
|
1344
|
-
const hosts = [];
|
|
1345
|
-
for (const call of rule.matchAll(/\bHost\(([^)]*)\)/gi)) {
|
|
1346
|
-
for (const m of call[1].matchAll(/[`'"]([^`'"]+)[`'"]/g)) {
|
|
1347
|
-
const h = m[1].trim();
|
|
1348
|
-
if (h) hosts.push(h);
|
|
1349
|
-
}
|
|
1350
|
-
}
|
|
1351
|
-
return [...new Set(hosts)];
|
|
1352
|
-
}
|
|
1353
|
-
function extraMatchers(rule) {
|
|
1354
|
-
const found = /* @__PURE__ */ new Set();
|
|
1355
|
-
for (const m of rule.matchAll(
|
|
1356
|
-
/\b(PathPrefix|PathRegexp|Path|HeadersRegexp|Headers|Method|Query|ClientIP|HostRegexp)\b/gi
|
|
1357
|
-
)) {
|
|
1358
|
-
found.add(m[1]);
|
|
1359
|
-
}
|
|
1360
|
-
return [...found];
|
|
1361
|
-
}
|
|
1362
|
-
function collectDefinitions(containers) {
|
|
1363
|
-
const services = /* @__PURE__ */ new Map();
|
|
1364
|
-
const redirectMiddlewares = /* @__PURE__ */ new Set();
|
|
1365
|
-
const streamRouters = [];
|
|
1366
|
-
let fileProvider = false;
|
|
1367
|
-
let exposedByDefault = true;
|
|
1368
|
-
for (const c of containers) {
|
|
1369
|
-
const labels = lowerKeys(c.labels);
|
|
1370
|
-
for (const [k, v] of Object.entries(labels)) {
|
|
1371
|
-
let m = k.match(
|
|
1372
|
-
/^traefik\.http\.services\.([^.]+)\.loadbalancer\.server\.(port|scheme)$/
|
|
1373
|
-
);
|
|
1374
|
-
if (m) {
|
|
1375
|
-
const def = services.get(m[1]) ?? {};
|
|
1376
|
-
if (m[2] === "port") def.port = v;
|
|
1377
|
-
else def.scheme = v;
|
|
1378
|
-
services.set(m[1], def);
|
|
1379
|
-
continue;
|
|
1380
|
-
}
|
|
1381
|
-
m = k.match(/^traefik\.http\.middlewares\.([^.]+)\.redirectscheme\./);
|
|
1382
|
-
if (m) {
|
|
1383
|
-
redirectMiddlewares.add(m[1]);
|
|
1384
|
-
continue;
|
|
1385
|
-
}
|
|
1386
|
-
m = k.match(/^traefik\.(tcp|udp)\.routers\.([^.]+)\.rule$/);
|
|
1387
|
-
if (m) streamRouters.push(`${m[1]} router "${m[2]}"`);
|
|
1388
|
-
}
|
|
1389
|
-
const cmd = c.cmd ?? "";
|
|
1390
|
-
if (/--?providers\.file/i.test(cmd)) fileProvider = true;
|
|
1391
|
-
if (/--?providers\.docker\.exposedbydefault[= ]?false/i.test(cmd))
|
|
1392
|
-
exposedByDefault = false;
|
|
1393
|
-
}
|
|
1394
|
-
return {
|
|
1395
|
-
services,
|
|
1396
|
-
redirectMiddlewares,
|
|
1397
|
-
streamRouters,
|
|
1398
|
-
fileProvider,
|
|
1399
|
-
exposedByDefault
|
|
1400
|
-
};
|
|
1401
|
-
}
|
|
1402
|
-
function resolveIp(c, labels) {
|
|
1403
|
-
const wanted = labels["traefik.docker.network"];
|
|
1404
|
-
if (wanted && c.networks?.[wanted]) return c.networks[wanted];
|
|
1405
|
-
if (c.ip) return c.ip;
|
|
1406
|
-
const first = Object.values(c.networks ?? {}).find(Boolean);
|
|
1407
|
-
return first || void 0;
|
|
1408
|
-
}
|
|
1409
|
-
function parseTraefikLabels(containers) {
|
|
1410
|
-
const warnings = [];
|
|
1411
|
-
const defs = collectDefinitions(containers);
|
|
1412
|
-
const candidates = [];
|
|
1413
|
-
for (const c of containers) {
|
|
1414
|
-
const labels = lowerKeys(c.labels);
|
|
1415
|
-
if (labels["traefik.enable"] === "false") continue;
|
|
1416
|
-
if (!defs.exposedByDefault && labels["traefik.enable"] !== "true") continue;
|
|
1417
|
-
const routers = /* @__PURE__ */ new Map();
|
|
1418
|
-
for (const [key, val] of Object.entries(labels)) {
|
|
1419
|
-
const r = key.match(/^traefik\.http\.routers\.([^.]+)\.(.+)$/);
|
|
1420
|
-
if (!r) continue;
|
|
1421
|
-
const bag = routers.get(r[1]) ?? {};
|
|
1422
|
-
bag[r[2]] = val;
|
|
1423
|
-
routers.set(r[1], bag);
|
|
1424
|
-
}
|
|
1425
|
-
for (const [rname, props] of routers) {
|
|
1426
|
-
const rule = props.rule;
|
|
1427
|
-
if (!rule) continue;
|
|
1428
|
-
const hosts = extractHosts(rule);
|
|
1429
|
-
if (hosts.length === 0) {
|
|
1430
|
-
warnings.push(
|
|
1431
|
-
/HostRegexp/i.test(rule) ? `traefik: router "${rname}" uses HostRegexp (${rule}) \u2014 regex hosts aren't migratable` : `traefik: router "${rname}" has no Host() rule (${rule}) \u2014 skipped`
|
|
1432
|
-
);
|
|
1433
|
-
continue;
|
|
1434
|
-
}
|
|
1435
|
-
const ip = resolveIp(c, labels);
|
|
1436
|
-
if (!ip) {
|
|
1437
|
-
warnings.push(
|
|
1438
|
-
`traefik: ${hosts.join(", ")} \u2014 couldn't resolve container ${c.name}'s IP; re-add the upstream manually`
|
|
1439
|
-
);
|
|
1440
|
-
continue;
|
|
1441
|
-
}
|
|
1442
|
-
const svc = props.service?.replace(/@.*$/, "");
|
|
1443
|
-
const def = (svc ? defs.services.get(svc) : void 0) ?? (defs.services.size === 1 ? [...defs.services.values()][0] : void 0);
|
|
1444
|
-
const onlyExposed = c.exposedPorts?.length === 1 ? c.exposedPorts[0].split("/")[0] : void 0;
|
|
1445
|
-
const rawPort = def?.port ?? onlyExposed;
|
|
1446
|
-
const port = /^\d{1,5}$/.test(String(rawPort)) ? String(rawPort) : "80";
|
|
1447
|
-
const scheme = def?.scheme?.toLowerCase() === "https" ? "https" : "http";
|
|
1448
|
-
const middlewares = (props.middlewares ?? "").split(",").map((m) => m.trim().replace(/@.*$/, "")).filter(Boolean);
|
|
1449
|
-
candidates.push({
|
|
1450
|
-
hosts,
|
|
1451
|
-
ssl: Object.keys(props).some(
|
|
1452
|
-
(p) => p === "tls" || p.startsWith("tls.")
|
|
1453
|
-
),
|
|
1454
|
-
url: `${scheme}://${ip}:${port}`,
|
|
1455
|
-
container: c.name,
|
|
1456
|
-
router: rname,
|
|
1457
|
-
rule,
|
|
1458
|
-
middlewares,
|
|
1459
|
-
redirectOnly: middlewares.length > 0 && middlewares.every((m) => defs.redirectMiddlewares.has(m)),
|
|
1460
|
-
portGuessed: rawPort === void 0
|
|
1461
|
-
});
|
|
1462
|
-
}
|
|
1463
|
-
}
|
|
1464
|
-
const { kept: sites, dropped } = collapseByHost(
|
|
1465
|
-
candidates,
|
|
1466
|
-
(c) => c.hosts,
|
|
1467
|
-
(c) => c.redirectOnly ? 0 : c.ssl ? 2 : 1
|
|
1468
|
-
);
|
|
1469
|
-
for (const cand of sites) {
|
|
1470
|
-
const extras = extraMatchers(cand.rule);
|
|
1471
|
-
if (extras.length > 0) {
|
|
1472
|
-
warnings.push(
|
|
1473
|
-
`traefik: ${cand.hosts.join(", ")} also matches ${extras.join(", ")} \u2014 only the Host() part is migrated; re-add path/header rules manually`
|
|
1474
|
-
);
|
|
1475
|
-
}
|
|
1476
|
-
const carried = cand.middlewares.filter(
|
|
1477
|
-
(m) => !defs.redirectMiddlewares.has(m)
|
|
1478
|
-
);
|
|
1479
|
-
if (carried.length > 0) {
|
|
1480
|
-
warnings.push(
|
|
1481
|
-
`traefik: ${cand.hosts.join(", ")} uses middleware(s) "${carried.join(", ")}" \u2014 not migrated`
|
|
1482
|
-
);
|
|
1483
|
-
}
|
|
1484
|
-
if (cand.portGuessed) {
|
|
1485
|
-
warnings.push(
|
|
1486
|
-
`traefik: ${cand.hosts.join(", ")} \u2014 no service port label and no single exposed port on ${cand.container}; assumed :80, check the upstream`
|
|
1487
|
-
);
|
|
1488
|
-
}
|
|
1489
|
-
}
|
|
1490
|
-
for (const d of dropped) {
|
|
1491
|
-
warnings.push(
|
|
1492
|
-
`traefik: ${d.hosts.join(", ")} router "${d.router}" is an http\u2192https redirect \u2014 Kraft's edge does that itself (nothing to migrate)`
|
|
1493
|
-
);
|
|
1494
|
-
}
|
|
1495
|
-
for (const s of defs.streamRouters) {
|
|
1496
|
-
warnings.push(
|
|
1497
|
-
`traefik: ${s} can't migrate \u2014 Kraft's edge routes HTTP(S), not raw TCP/UDP`
|
|
1498
|
-
);
|
|
1499
|
-
}
|
|
1500
|
-
if (defs.fileProvider) {
|
|
1501
|
-
warnings.push(
|
|
1502
|
-
"traefik: a file provider is configured \u2014 routes defined in its YAML/TOML files are NOT read here, only container labels. Re-add those domains manually."
|
|
1503
|
-
);
|
|
1504
|
-
}
|
|
1505
|
-
return {
|
|
1506
|
-
proxy: "traefik",
|
|
1507
|
-
sites: sites.map((cand) => ({
|
|
1508
|
-
serverNames: cand.hosts,
|
|
1509
|
-
ssl: cand.ssl,
|
|
1510
|
-
target: { kind: "proxy", url: cand.url },
|
|
1511
|
-
source: `traefik container ${cand.container}`
|
|
1512
|
-
})),
|
|
1513
|
-
warnings
|
|
1514
|
-
};
|
|
1515
|
-
}
|
|
1516
|
-
async function scanTraefik(executor) {
|
|
1517
|
-
const out = await tryExec(
|
|
1518
|
-
executor,
|
|
1519
|
-
`docker ps -q 2>/dev/null | xargs -r docker inspect --format '{{.Name}} {{json .Config.Labels}} {{range $n, $v := .NetworkSettings.Networks}}{{$n}}={{$v.IPAddress}} {{end}} {{range $p, $v := .Config.ExposedPorts}}{{$p}} {{end}} {{if .Config.Cmd}}{{join .Config.Cmd " "}}{{end}}' 2>/dev/null`
|
|
1520
|
-
);
|
|
1521
|
-
if (!out) {
|
|
1522
|
-
return {
|
|
1523
|
-
proxy: "traefik",
|
|
1524
|
-
sites: [],
|
|
1525
|
-
warnings: ["traefik: couldn't read container labels via docker inspect"]
|
|
1526
|
-
};
|
|
1527
|
-
}
|
|
1528
|
-
const containers = [];
|
|
1529
|
-
for (const line of out.split("\n")) {
|
|
1530
|
-
const [rawName, rawLabels, rawNets, rawPorts, rawCmd] = line.split(" ");
|
|
1531
|
-
if (!rawName || !rawLabels) continue;
|
|
1532
|
-
let labels;
|
|
1533
|
-
try {
|
|
1534
|
-
labels = JSON.parse(rawLabels) ?? {};
|
|
1535
|
-
} catch {
|
|
1536
|
-
continue;
|
|
1537
|
-
}
|
|
1538
|
-
const networks = {};
|
|
1539
|
-
let bareIp;
|
|
1540
|
-
for (const pair of (rawNets ?? "").trim().split(/\s+/)) {
|
|
1541
|
-
if (!pair) continue;
|
|
1542
|
-
const eq = pair.indexOf("=");
|
|
1543
|
-
if (eq > 0) {
|
|
1544
|
-
const ip = pair.slice(eq + 1);
|
|
1545
|
-
if (ip) networks[pair.slice(0, eq)] = ip;
|
|
1546
|
-
} else if (!bareIp) {
|
|
1547
|
-
bareIp = pair;
|
|
1548
|
-
}
|
|
1549
|
-
}
|
|
1550
|
-
const exposedPorts = (rawPorts ?? "").trim().split(/\s+/).filter(Boolean);
|
|
1551
|
-
const hasTraefikLabels = Object.keys(labels).some(
|
|
1552
|
-
(k) => k.toLowerCase().startsWith("traefik.")
|
|
1553
|
-
);
|
|
1554
|
-
const looksLikeTraefik = /traefik/i.test(rawCmd ?? "") || /--?providers\./i.test(rawCmd ?? "");
|
|
1555
|
-
if (!hasTraefikLabels && !looksLikeTraefik) continue;
|
|
1556
|
-
containers.push({
|
|
1557
|
-
name: rawName.replace(/^\//, ""),
|
|
1558
|
-
labels,
|
|
1559
|
-
ip: Object.values(networks)[0] ?? bareIp,
|
|
1560
|
-
networks,
|
|
1561
|
-
exposedPorts,
|
|
1562
|
-
cmd: rawCmd ?? void 0
|
|
1563
|
-
});
|
|
1564
|
-
}
|
|
1565
|
-
return parseTraefikLabels(containers);
|
|
1566
|
-
}
|
|
1567
|
-
|
|
1568
1336
|
// ../../packages/adapters/src/system/proxy/import/index.ts
|
|
1569
1337
|
var INSTALLED_MARKERS = [
|
|
1570
1338
|
{ proxy: "nginx", paths: ["/etc/nginx/nginx.conf"] },
|
|
@@ -1607,8 +1375,6 @@ async function scanImportableSites(executor, proxy) {
|
|
|
1607
1375
|
return scanCaddy(executor);
|
|
1608
1376
|
case "apache":
|
|
1609
1377
|
return scanApache(executor);
|
|
1610
|
-
case "traefik":
|
|
1611
|
-
return scanTraefik(executor);
|
|
1612
1378
|
case "openresty":
|
|
1613
1379
|
return scanForeignOpenResty(executor);
|
|
1614
1380
|
default:
|
|
@@ -1620,7 +1386,7 @@ async function scanImportableSites(executor, proxy) {
|
|
|
1620
1386
|
}
|
|
1621
1387
|
}
|
|
1622
1388
|
function canImportProxy(proxy) {
|
|
1623
|
-
return proxy === "nginx" || proxy === "caddy" || proxy === "apache" || proxy === "
|
|
1389
|
+
return proxy === "nginx" || proxy === "caddy" || proxy === "apache" || proxy === "openresty";
|
|
1624
1390
|
}
|
|
1625
1391
|
function unreachableStaticRoots(sites, opts) {
|
|
1626
1392
|
if (!opts.containerEdge) return [];
|
|
@@ -1693,125 +1459,6 @@ async function caddyStoreCert(exec, host, container) {
|
|
|
1693
1459
|
return null;
|
|
1694
1460
|
}
|
|
1695
1461
|
|
|
1696
|
-
// ../../packages/adapters/src/system/proxy/import/traefik-certs.ts
|
|
1697
|
-
var DEFAULT_ACME_PATHS = [
|
|
1698
|
-
"/acme.json",
|
|
1699
|
-
"/etc/traefik/acme.json",
|
|
1700
|
-
"/data/acme.json",
|
|
1701
|
-
"/letsencrypt/acme.json"
|
|
1702
|
-
];
|
|
1703
|
-
var TRAEFIK_STATIC_CONFIGS = [
|
|
1704
|
-
"/etc/traefik/traefik.yml",
|
|
1705
|
-
"/etc/traefik/traefik.yaml",
|
|
1706
|
-
"/etc/traefik/traefik.toml"
|
|
1707
|
-
];
|
|
1708
|
-
function prop(obj, name) {
|
|
1709
|
-
const hit = Object.keys(obj).find(
|
|
1710
|
-
(k) => k.toLowerCase() === name.toLowerCase()
|
|
1711
|
-
);
|
|
1712
|
-
return hit === void 0 ? void 0 : obj[hit];
|
|
1713
|
-
}
|
|
1714
|
-
async function candidateStoragePaths(exec, container) {
|
|
1715
|
-
const found = [];
|
|
1716
|
-
const collect = (text) => {
|
|
1717
|
-
for (const m of (text ?? "").matchAll(
|
|
1718
|
-
/acme\.storage[=:\s]+["']?(\/[^\s"',}]+)/gi
|
|
1719
|
-
)) {
|
|
1720
|
-
if (isSafeCertPath(m[1])) found.push(m[1]);
|
|
1721
|
-
}
|
|
1722
|
-
for (const m of (text ?? "").matchAll(
|
|
1723
|
-
/(?:^|\s)storage:\s*["']?(\/[^\s"',}]+\.json)/gi
|
|
1724
|
-
)) {
|
|
1725
|
-
if (isSafeCertPath(m[1])) found.push(m[1]);
|
|
1726
|
-
}
|
|
1727
|
-
};
|
|
1728
|
-
if (container) {
|
|
1729
|
-
collect(
|
|
1730
|
-
await tryExec(
|
|
1731
|
-
exec,
|
|
1732
|
-
`docker inspect ${sq2(container)} --format '{{json .Config.Cmd}} {{json .Args}} {{json .Config.Env}}' 2>/dev/null`
|
|
1733
|
-
)
|
|
1734
|
-
);
|
|
1735
|
-
for (const cfg of TRAEFIK_STATIC_CONFIGS) {
|
|
1736
|
-
collect(await readMaybeInContainer(exec, cfg, container));
|
|
1737
|
-
}
|
|
1738
|
-
}
|
|
1739
|
-
return [.../* @__PURE__ */ new Set([...found, ...DEFAULT_ACME_PATHS])];
|
|
1740
|
-
}
|
|
1741
|
-
async function loadAcmeJson(exec, container) {
|
|
1742
|
-
for (const path of await candidateStoragePaths(exec, container)) {
|
|
1743
|
-
const raw = await readMaybeInContainer(exec, path, container);
|
|
1744
|
-
if (raw.trim().startsWith("{")) return { raw, path };
|
|
1745
|
-
}
|
|
1746
|
-
return null;
|
|
1747
|
-
}
|
|
1748
|
-
function certFromAcmeJson(raw, host) {
|
|
1749
|
-
let parsed;
|
|
1750
|
-
try {
|
|
1751
|
-
parsed = JSON.parse(raw);
|
|
1752
|
-
} catch {
|
|
1753
|
-
return null;
|
|
1754
|
-
}
|
|
1755
|
-
const target = host.toLowerCase();
|
|
1756
|
-
const matches = (name) => {
|
|
1757
|
-
const n = (name ?? "").toLowerCase();
|
|
1758
|
-
if (!n) return false;
|
|
1759
|
-
if (n === target) return true;
|
|
1760
|
-
if (!n.startsWith("*.")) return false;
|
|
1761
|
-
const suffix = n.slice(1);
|
|
1762
|
-
return target.endsWith(suffix) && !target.slice(0, -suffix.length).includes(".");
|
|
1763
|
-
};
|
|
1764
|
-
for (const [resolver, value] of Object.entries(parsed)) {
|
|
1765
|
-
if (!value || typeof value !== "object") continue;
|
|
1766
|
-
const certs = prop(value, "certificates");
|
|
1767
|
-
if (!Array.isArray(certs)) continue;
|
|
1768
|
-
for (const entry of certs) {
|
|
1769
|
-
const domain = entry && prop(entry, "domain");
|
|
1770
|
-
const names = [domain?.main, ...domain?.sans ?? []];
|
|
1771
|
-
if (!names.some(matches)) continue;
|
|
1772
|
-
const certB64 = prop(entry, "certificate");
|
|
1773
|
-
const keyB64 = prop(entry, "key");
|
|
1774
|
-
if (typeof certB64 !== "string" || typeof keyB64 !== "string") continue;
|
|
1775
|
-
const certPem = Buffer.from(certB64, "base64").toString("utf-8");
|
|
1776
|
-
const keyPem = Buffer.from(keyB64, "base64").toString("utf-8");
|
|
1777
|
-
if (!certPem.includes("-----BEGIN") || !keyPem.includes("-----BEGIN"))
|
|
1778
|
-
continue;
|
|
1779
|
-
return { certPem, keyPem, resolver };
|
|
1780
|
-
}
|
|
1781
|
-
}
|
|
1782
|
-
return null;
|
|
1783
|
-
}
|
|
1784
|
-
async function traefikAcmeCert(exec, host, container) {
|
|
1785
|
-
const loaded = await loadAcmeJson(exec, container);
|
|
1786
|
-
if (!loaded) return null;
|
|
1787
|
-
const hit = certFromAcmeJson(loaded.raw, host);
|
|
1788
|
-
if (!hit) return null;
|
|
1789
|
-
return {
|
|
1790
|
-
certPem: hit.certPem,
|
|
1791
|
-
keyPem: hit.keyPem,
|
|
1792
|
-
source: `traefik ${loaded.path} (resolver ${hit.resolver})`
|
|
1793
|
-
};
|
|
1794
|
-
}
|
|
1795
|
-
async function traefikDeclaredCertPaths(exec, container) {
|
|
1796
|
-
const pairs = [];
|
|
1797
|
-
for (const cfg of TRAEFIK_STATIC_CONFIGS) {
|
|
1798
|
-
const text = await readMaybeInContainer(exec, cfg, container);
|
|
1799
|
-
if (!text.trim()) continue;
|
|
1800
|
-
const certFiles = [
|
|
1801
|
-
...text.matchAll(/certFile:\s*["']?(\/[^\s"',}]+)/gi)
|
|
1802
|
-
].map((m) => m[1]);
|
|
1803
|
-
const keyFiles = [...text.matchAll(/keyFile:\s*["']?(\/[^\s"',}]+)/gi)].map(
|
|
1804
|
-
(m) => m[1]
|
|
1805
|
-
);
|
|
1806
|
-
for (let i = 0; i < Math.min(certFiles.length, keyFiles.length); i++) {
|
|
1807
|
-
if (isSafeCertPath(certFiles[i]) && isSafeCertPath(keyFiles[i])) {
|
|
1808
|
-
pairs.push({ certPath: certFiles[i], keyPath: keyFiles[i] });
|
|
1809
|
-
}
|
|
1810
|
-
}
|
|
1811
|
-
}
|
|
1812
|
-
return pairs;
|
|
1813
|
-
}
|
|
1814
|
-
|
|
1815
1462
|
// ../../packages/adapters/src/system/proxy/api.ts
|
|
1816
1463
|
function buildProxyRouteIndex(sites) {
|
|
1817
1464
|
const byPort = /* @__PURE__ */ new Map();
|
|
@@ -1878,28 +1525,9 @@ var CERT_SOURCES = {
|
|
|
1878
1525
|
openresty: [declaredCert],
|
|
1879
1526
|
apache: [declaredCert],
|
|
1880
1527
|
caddy: [declaredCert, (c) => caddyStoreCert(c.exec, c.host, c.container)],
|
|
1881
|
-
traefik: [
|
|
1882
|
-
(c) => traefikAcmeCert(c.exec, c.host, c.container),
|
|
1883
|
-
// File provider: paths aren't bound to a hostname (traefik picks by SNI), so
|
|
1884
|
-
// hand every declared pair to the validator and let coverage decide.
|
|
1885
|
-
async (c) => {
|
|
1886
|
-
for (const pair of await traefikDeclaredCertPaths(c.exec, c.container)) {
|
|
1887
|
-
const pems = await readDeclaredPair(
|
|
1888
|
-
c.exec,
|
|
1889
|
-
pair.certPath,
|
|
1890
|
-
pair.keyPath,
|
|
1891
|
-
c.container
|
|
1892
|
-
);
|
|
1893
|
-
if (!pems) continue;
|
|
1894
|
-
if (validateCertFor(c.host, pems, pair.certPath).cert) {
|
|
1895
|
-
return { ...pems, source: pair.certPath };
|
|
1896
|
-
}
|
|
1897
|
-
}
|
|
1898
|
-
return null;
|
|
1899
|
-
}
|
|
1900
|
-
],
|
|
1901
1528
|
// Takeover-only: no importable config, so no cert to find either.
|
|
1902
|
-
haproxy: []
|
|
1529
|
+
haproxy: [],
|
|
1530
|
+
traefik: []
|
|
1903
1531
|
};
|
|
1904
1532
|
async function edgeProxy(exec, opts = {}) {
|
|
1905
1533
|
const status = opts.status ?? await probeEdge(exec).catch(() => null);
|
|
@@ -2867,7 +2495,7 @@ function edgeHostExecutor(executor) {
|
|
|
2867
2495
|
});
|
|
2868
2496
|
}
|
|
2869
2497
|
async function containerEdgeProvider(executor, container, opts) {
|
|
2870
|
-
const { NginxProvider: Provider } = await import("./nginx-
|
|
2498
|
+
const { NginxProvider: Provider } = await import("./nginx-V6DQWKON.js");
|
|
2871
2499
|
return new Provider({
|
|
2872
2500
|
...opts,
|
|
2873
2501
|
// Vhosts go to the BIND-MOUNTED HOST dir (so every host-side reader — the
|
|
@@ -2894,8 +2522,8 @@ async function containerEdgeProvider(executor, container, opts) {
|
|
|
2894
2522
|
});
|
|
2895
2523
|
}
|
|
2896
2524
|
async function localContainerEdgeProvider(container, opts) {
|
|
2897
|
-
const { DockerEdgeExecutor } = await import("./docker-edge-executor-
|
|
2898
|
-
const { NginxProvider: Provider } = await import("./nginx-
|
|
2525
|
+
const { DockerEdgeExecutor } = await import("./docker-edge-executor-JID2Q2HZ.js");
|
|
2526
|
+
const { NginxProvider: Provider } = await import("./nginx-V6DQWKON.js");
|
|
2899
2527
|
return new Provider({
|
|
2900
2528
|
...opts,
|
|
2901
2529
|
paths: OPENRESTY_DEFAULT_PATHS,
|
|
@@ -140,29 +140,29 @@ import {
|
|
|
140
140
|
resolveExecExitCode,
|
|
141
141
|
startAttachStream,
|
|
142
142
|
startExecStream
|
|
143
|
-
} from "./chunk-
|
|
143
|
+
} from "./chunk-Q7FAE2MB.js";
|
|
144
144
|
import {
|
|
145
145
|
BareRuntime
|
|
146
|
-
} from "./chunk-
|
|
146
|
+
} from "./chunk-MK6GYBO4.js";
|
|
147
147
|
import {
|
|
148
148
|
createExecutor
|
|
149
|
-
} from "./chunk-
|
|
149
|
+
} from "./chunk-N7AJ2D4I.js";
|
|
150
150
|
import {
|
|
151
151
|
OPENRESTY_DEFAULT_PATHS
|
|
152
|
-
} from "./chunk-
|
|
152
|
+
} from "./chunk-XAEYWDBX.js";
|
|
153
153
|
import {
|
|
154
154
|
MAIL_HOST_STATE_DIR
|
|
155
|
-
} from "./chunk-
|
|
155
|
+
} from "./chunk-E3J47WO3.js";
|
|
156
156
|
import {
|
|
157
157
|
envOps
|
|
158
|
-
} from "./chunk-
|
|
158
|
+
} from "./chunk-7VMXN646.js";
|
|
159
159
|
import {
|
|
160
160
|
ENVIRONMENT_PROBE_SCRIPT,
|
|
161
161
|
ENVIRONMENT_PROBE_TIMEOUT_MS,
|
|
162
162
|
cacheEnvironment,
|
|
163
163
|
parseEnvironmentProbe,
|
|
164
164
|
profileIsFresh
|
|
165
|
-
} from "./chunk-
|
|
165
|
+
} from "./chunk-BQMBJ32I.js";
|
|
166
166
|
import {
|
|
167
167
|
FAMILY_BY_DISTRO,
|
|
168
168
|
PRICING,
|
|
@@ -175,7 +175,7 @@ import {
|
|
|
175
175
|
validateBackupPath,
|
|
176
176
|
validateClearPath,
|
|
177
177
|
withTimeout
|
|
178
|
-
} from "./chunk-
|
|
178
|
+
} from "./chunk-G4VGNFGV.js";
|
|
179
179
|
|
|
180
180
|
// ../../packages/adapters/src/types.ts
|
|
181
181
|
var DEFAULT_BUILD_RESOURCE_CONFIG = {
|
|
@@ -293,13 +293,16 @@ function registerDestination(kind, factory) {
|
|
|
293
293
|
}
|
|
294
294
|
|
|
295
295
|
// ../../packages/adapters/src/backup/common/credentials.ts
|
|
296
|
-
import { createDecipheriv, createHash as createHash2 } from "crypto";
|
|
297
|
-
var
|
|
296
|
+
import { createDecipheriv, createHash as createHash2, hkdfSync } from "crypto";
|
|
297
|
+
var PREFIX_V1 = "enc1:";
|
|
298
|
+
var PREFIX_V2 = "enc2:";
|
|
298
299
|
var ALGORITHM = "aes-256-gcm";
|
|
299
300
|
var IV_LENGTH = 16;
|
|
300
301
|
var AUTH_TAG_LENGTH = 16;
|
|
302
|
+
var HKDF_SALT_V2 = "kraft-enc-salt-v2";
|
|
303
|
+
var SSH_CREDENTIAL_PURPOSE = "ssh-credential-v1";
|
|
301
304
|
var injectedSecret;
|
|
302
|
-
function
|
|
305
|
+
function deriveKeyV1() {
|
|
303
306
|
const secret = injectedSecret ?? process.env.BETTER_AUTH_SECRET;
|
|
304
307
|
if (!secret) {
|
|
305
308
|
throw new Error(
|
|
@@ -308,23 +311,53 @@ function deriveKey() {
|
|
|
308
311
|
}
|
|
309
312
|
return createHash2("sha256").update(secret).digest();
|
|
310
313
|
}
|
|
311
|
-
function
|
|
312
|
-
|
|
313
|
-
if (!
|
|
314
|
-
|
|
314
|
+
function deriveKeyV2() {
|
|
315
|
+
const secret = injectedSecret ?? process.env.BETTER_AUTH_SECRET;
|
|
316
|
+
if (!secret) {
|
|
317
|
+
throw new Error(
|
|
318
|
+
"BETTER_AUTH_SECRET is not set \u2014 cannot decrypt backup destination credentials."
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
return Buffer.from(
|
|
322
|
+
hkdfSync(
|
|
323
|
+
"sha256",
|
|
324
|
+
Buffer.from(secret, "utf8"),
|
|
325
|
+
HKDF_SALT_V2,
|
|
326
|
+
SSH_CREDENTIAL_PURPOSE,
|
|
327
|
+
32
|
|
328
|
+
)
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
function openEnvelope(packed, key) {
|
|
315
332
|
if (packed.length < IV_LENGTH + AUTH_TAG_LENGTH) {
|
|
316
333
|
throw new Error("Invalid credential ciphertext: too short");
|
|
317
334
|
}
|
|
318
335
|
const iv = packed.subarray(0, IV_LENGTH);
|
|
319
336
|
const authTag = packed.subarray(IV_LENGTH, IV_LENGTH + AUTH_TAG_LENGTH);
|
|
320
337
|
const ciphertext = packed.subarray(IV_LENGTH + AUTH_TAG_LENGTH);
|
|
321
|
-
const decipher = createDecipheriv(ALGORITHM,
|
|
338
|
+
const decipher = createDecipheriv(ALGORITHM, key, iv);
|
|
322
339
|
decipher.setAuthTag(authTag);
|
|
323
340
|
return Buffer.concat([
|
|
324
341
|
decipher.update(ciphertext),
|
|
325
342
|
decipher.final()
|
|
326
343
|
]).toString("utf8");
|
|
327
344
|
}
|
|
345
|
+
function decryptCredential(stored) {
|
|
346
|
+
if (stored == null || stored === "") return void 0;
|
|
347
|
+
if (stored.startsWith(PREFIX_V2)) {
|
|
348
|
+
return openEnvelope(
|
|
349
|
+
Buffer.from(stored.slice(PREFIX_V2.length), "base64"),
|
|
350
|
+
deriveKeyV2()
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
if (stored.startsWith(PREFIX_V1)) {
|
|
354
|
+
return openEnvelope(
|
|
355
|
+
Buffer.from(stored.slice(PREFIX_V1.length), "base64"),
|
|
356
|
+
deriveKeyV1()
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
return stored;
|
|
360
|
+
}
|
|
328
361
|
|
|
329
362
|
// ../../packages/adapters/src/backup/common/sha256-stream.ts
|
|
330
363
|
import { createHash as createHash3 } from "crypto";
|
|
@@ -9,14 +9,14 @@ import {
|
|
|
9
9
|
internalPost,
|
|
10
10
|
mintBareInternalToken,
|
|
11
11
|
waitHealthy
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-KHAT3OZP.js";
|
|
13
13
|
import {
|
|
14
14
|
completeHostEdge,
|
|
15
15
|
markStoppedProxyImported,
|
|
16
16
|
planAndApplyHostEdge,
|
|
17
17
|
previewHostEdge,
|
|
18
18
|
rollbackHostEdge
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-5RWL7EFH.js";
|
|
20
20
|
import {
|
|
21
21
|
DEFAULT_REPO,
|
|
22
22
|
PORTS_FILE,
|
|
@@ -43,11 +43,11 @@ import {
|
|
|
43
43
|
resolvePorts,
|
|
44
44
|
sourceBuildDir,
|
|
45
45
|
verifyHostChannel
|
|
46
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-C3LRTROB.js";
|
|
47
47
|
import {
|
|
48
48
|
startUnitHint,
|
|
49
49
|
thisHost
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-B2CUYCGY.js";
|
|
51
51
|
import {
|
|
52
52
|
AUTH_SECRET_FILE,
|
|
53
53
|
DATA_DIR,
|
|
@@ -59,16 +59,16 @@ import {
|
|
|
59
59
|
import {
|
|
60
60
|
edgeCrashReason,
|
|
61
61
|
edgeIsBroken
|
|
62
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-QLPQ5NFE.js";
|
|
63
63
|
import {
|
|
64
64
|
LocalExecutor
|
|
65
|
-
} from "./chunk-
|
|
65
|
+
} from "./chunk-BIOW6K3V.js";
|
|
66
66
|
import {
|
|
67
67
|
EDGE_CONTAINER_NAME
|
|
68
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-E3J47WO3.js";
|
|
69
69
|
import {
|
|
70
70
|
isValidEmail
|
|
71
|
-
} from "./chunk-
|
|
71
|
+
} from "./chunk-G4VGNFGV.js";
|
|
72
72
|
|
|
73
73
|
// src/commands/up.ts
|
|
74
74
|
import { Command } from "commander";
|
|
@@ -1942,7 +1942,7 @@ async function runForeground(opts, source) {
|
|
|
1942
1942
|
const uiSpinner = ora("Preparing the dashboard\u2026").start();
|
|
1943
1943
|
try {
|
|
1944
1944
|
const bundle = await ensureDashboard({
|
|
1945
|
-
tag: source ? "local" : opts.uiVersion || `v${"0.7.
|
|
1945
|
+
tag: source ? "local" : opts.uiVersion || `v${"0.7.13"}`,
|
|
1946
1946
|
onProgress: (received, total) => {
|
|
1947
1947
|
if (total) {
|
|
1948
1948
|
uiSpinner.text = `Downloading dashboard\u2026 ${Math.round(received / total * 100)}%`;
|