openship 0.6.1 → 0.6.5

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.
Files changed (59) hide show
  1. package/README.md +7 -2
  2. package/dist/{bare-IWS2QHJ3.js → bare-XQIPDO4R.js} +10 -9
  3. package/dist/{chunk-RRJJGVKE.js → chunk-3ZAGC5NT.js} +64 -17
  4. package/dist/{chunk-6ODUBKUB.js → chunk-5OUWIPOB.js} +69 -7
  5. package/dist/chunk-6HOA5JT7.js +124 -0
  6. package/dist/{chunk-TWJCLD4W.js → chunk-6JELW75A.js} +4 -4
  7. package/dist/{chunk-IOT5ZX23.js → chunk-7334NSJL.js} +399 -369
  8. package/dist/chunk-7S4USQYF.js +1753 -0
  9. package/dist/{chunk-3LDWWY7U.js → chunk-A7EWM2KA.js} +41 -7
  10. package/dist/chunk-ELGRMZOW.js +25 -0
  11. package/dist/chunk-EZPPTWJQ.js +292 -0
  12. package/dist/{chunk-IXM5245F.js → chunk-GRTXMUHA.js} +553 -538
  13. package/dist/chunk-HPXP6LXZ.js +428 -0
  14. package/dist/{chunk-OTLSJYAC.js → chunk-LEYSL46B.js} +2135 -85
  15. package/dist/{chunk-EMXI4UCU.js → chunk-LFCSC4IU.js} +29 -10
  16. package/dist/{chunk-JIMUYEKN.js → chunk-MSZUCNPV.js} +1 -1
  17. package/dist/{chunk-YIPMDGG6.js → chunk-PZRRL5PC.js} +68 -23
  18. package/dist/{chunk-2NZSUXOB.js → chunk-QLX7NBEA.js} +1208 -599
  19. package/dist/chunk-RFWJE7ZN.js +68 -0
  20. package/dist/{chunk-VDDMADOF.js → chunk-TM2IQPYU.js} +16 -2
  21. package/dist/{chunk-3FYIXVX5.js → chunk-VDESJSG6.js} +451 -106
  22. package/dist/{chunk-UC7YIEHT.js → chunk-VHMOQL5Y.js} +254 -45
  23. package/dist/{chunk-EW6KB2J7.js → chunk-VLQ3UIVO.js} +393 -53
  24. package/dist/{chunk-VZ2ZHPS2.js → chunk-WE7BXW6L.js} +3 -9
  25. package/dist/chunk-WFRXYWK2.js +444 -0
  26. package/dist/chunk-XRNRT37W.js +316 -0
  27. package/dist/{chunk-3NZICQHF.js → chunk-XVOBL7BC.js} +31 -8
  28. package/dist/cloud-3DODOWTR.js +36 -0
  29. package/dist/{detect-ALF4GXRX.js → detect-P4CIQBRH.js} +3 -3
  30. package/dist/{docker-QECQJ5P4.js → docker-3K2NEBD6.js} +15 -8
  31. package/dist/{docker-edge-executor-62N64MGS.js → docker-edge-executor-YZZ6P7IC.js} +5 -5
  32. package/dist/{edge-import-SAYTRJLO.js → edge-import-MCJNVTZ2.js} +26 -23
  33. package/dist/edge-preflight-ES6FH4JK.js +42 -0
  34. package/dist/{ensure-container-edge-CFSCPGZK.js → ensure-container-edge-YPITNH45.js} +9 -8
  35. package/dist/{executor-PT6UEJ5M.js → executor-DZGX55K2.js} +12 -5
  36. package/dist/host-channel-preflight-MUXE3KZU.js +49 -0
  37. package/dist/index.js +4089 -4538
  38. package/dist/{nginx-YOEEFBTE.js → nginx-NSAHWGJV.js} +11 -5
  39. package/dist/node-bootstrap.js +241 -0
  40. package/dist/node-entry.js +52 -1
  41. package/dist/{openresty-lua-WGBO2M3Z.js → openresty-lua-DR4D3EZ6.js} +6 -2
  42. package/dist/privilege-YTVI4SKF.js +19 -0
  43. package/dist/server/engine/samples/fail2ban/jail.d/sshd.local +4 -1
  44. package/dist/server/index.js +21391 -13110
  45. package/dist/server/migrations/0098_instance_product_mode.sql +12 -0
  46. package/dist/server/migrations/0099_mail_webmail_project.sql +24 -0
  47. package/dist/server/migrations/0100_server_ssh_private_key.sql +11 -0
  48. package/dist/server/migrations/0101_mail_resume_step.sql +12 -0
  49. package/dist/server/migrations/0102_project_workload_axes.sql +19 -0
  50. package/dist/server/migrations/0103_dns_credential.sql +41 -0
  51. package/dist/server/migrations/0104_instance_host_control.sql +15 -0
  52. package/dist/server/migrations/meta/_journal.json +49 -0
  53. package/dist/{setup-M2ZDGH3O.js → setup-WUUZURHS.js} +10 -9
  54. package/dist/up-XEO3SR6Z.js +58 -0
  55. package/package.json +4 -2
  56. package/dist/chunk-IW2UKBVF.js +0 -144
  57. package/dist/chunk-ZCFVHA25.js +0 -89
  58. package/dist/cloud-M2YLWEXO.js +0 -31
  59. /package/dist/{dist-es-JGBPABJI.js → dist-es-ZP5QDSJ3.js} +0 -0
@@ -7,14 +7,14 @@ import {
7
7
  localGitSshWriter,
8
8
  materializeGitSsh,
9
9
  sq
10
- } from "./chunk-VDDMADOF.js";
10
+ } from "./chunk-TM2IQPYU.js";
11
11
  import {
12
12
  getTarCreateEnv,
13
13
  prepareSourceTarArgs
14
- } from "./chunk-6ODUBKUB.js";
14
+ } from "./chunk-5OUWIPOB.js";
15
15
  import {
16
16
  packageManagerEnsureCommand
17
- } from "./chunk-OTLSJYAC.js";
17
+ } from "./chunk-LEYSL46B.js";
18
18
  import {
19
19
  __commonJS,
20
20
  __toESM
@@ -480,16 +480,34 @@ var require_ignore = __commonJS({
480
480
 
481
481
  // ../../packages/adapters/src/runtime/docker-paths.ts
482
482
  import { access, readdir } from "fs/promises";
483
- import { isAbsolute, join, relative, sep } from "path";
483
+ import { isAbsolute, join, relative, resolve, sep } from "path";
484
484
  function toPosixPath(value) {
485
485
  return value.split(sep).filter(Boolean).join("/");
486
486
  }
487
+ function toSafeSegments(value, label) {
488
+ const segments = value.split(/[\\/]/).filter((segment) => segment && segment !== ".");
489
+ if (segments.includes("..")) {
490
+ throw new Error(
491
+ `Invalid ${label} ${JSON.stringify(value)}: path segments must not contain "..".`
492
+ );
493
+ }
494
+ return segments;
495
+ }
487
496
  function normalizeDockerRelativePath(value) {
488
497
  const normalized = value?.trim().replace(/^\.\//, "").replace(/^\/+|\/+$/g, "");
489
498
  if (!normalized || normalized === ".") {
490
499
  return "";
491
500
  }
492
- return normalized.split(/[\\/]/).filter(Boolean).join("/");
501
+ return toSafeSegments(normalized, "path").join("/");
502
+ }
503
+ function resolveWithinDirectory(baseDir, relativePath) {
504
+ const base = resolve(baseDir);
505
+ const target = resolve(base, ...toSafeSegments(relativePath?.trim() ?? "", "path"));
506
+ const escape = relative(base, target);
507
+ if (escape === ".." || escape.startsWith(`..${sep}`) || isAbsolute(escape)) {
508
+ throw new Error(`Resolved path ${JSON.stringify(target)} escapes ${JSON.stringify(base)}.`);
509
+ }
510
+ return target;
493
511
  }
494
512
  function normalizeDockerRootDirectory(rootDirectory, localPath) {
495
513
  let normalized = rootDirectory?.trim() ?? "";
@@ -509,7 +527,7 @@ function normalizeDockerRootDirectory(rootDirectory, localPath) {
509
527
  if (!normalized || normalized === ".") {
510
528
  return "";
511
529
  }
512
- return toPosixPath(normalized);
530
+ return toSafeSegments(normalized, "rootDirectory").join("/");
513
531
  }
514
532
  function resolveExplicitDockerfileCandidate(rootDirectory, dockerfilePath) {
515
533
  const normalizedRootDirectory = normalizeDockerRelativePath(rootDirectory);
@@ -904,7 +922,7 @@ import { join as join2, relative as relative2, sep as sep2 } from "path";
904
922
  var GIT_CLONE_IDLE_TIMEOUT_MS = 5 * 6e4;
905
923
  var GIT_CHECKOUT_IDLE_TIMEOUT_MS = 6e4;
906
924
  function spawnGit(args, opts) {
907
- return new Promise((resolve, reject) => {
925
+ return new Promise((resolve2, reject) => {
908
926
  const child = spawn("git", args, {
909
927
  stdio: ["ignore", "pipe", "pipe"],
910
928
  env: {
@@ -954,7 +972,7 @@ function spawnGit(args, opts) {
954
972
  });
955
973
  child.on("close", (code) => {
956
974
  clearTimeout(idleTimer);
957
- if (code === 0) resolve();
975
+ if (code === 0) resolve2();
958
976
  else reject(new Error(`git exited with code ${code}: ${stderr.trim().slice(-500) || "no stderr"}`));
959
977
  });
960
978
  });
@@ -1014,7 +1032,7 @@ async function applyDockerignore(contextDir, config) {
1014
1032
  async function materializeLocalSource(sourcePath, targetPath) {
1015
1033
  const { args, cleanup } = await prepareSourceTarArgs(sourcePath);
1016
1034
  try {
1017
- await new Promise((resolve, reject) => {
1035
+ await new Promise((resolve2, reject) => {
1018
1036
  const create = spawn("tar", args, { env: getTarCreateEnv() });
1019
1037
  const extract = spawn("tar", ["-xzf", "-", "-C", targetPath]);
1020
1038
  let err = "";
@@ -1027,7 +1045,7 @@ async function materializeLocalSource(sourcePath, targetPath) {
1027
1045
  create.on("close", (code) => createCode = code);
1028
1046
  create.stdout.pipe(extract.stdin);
1029
1047
  extract.on("close", (code) => {
1030
- if (code === 0 && (createCode ?? 0) === 0) return resolve();
1048
+ if (code === 0 && (createCode ?? 0) === 0) return resolve2();
1031
1049
  const parts = [
1032
1050
  createCode ? `pack exited ${createCode}: ${createErr.trim().slice(-500)}` : "",
1033
1051
  code ? `extract exited ${code}: ${err.trim().slice(-500)}` : ""
@@ -1173,6 +1191,7 @@ async function createDockerBuildContext(config, opts) {
1173
1191
 
1174
1192
  export {
1175
1193
  normalizeDockerRelativePath,
1194
+ resolveWithinDirectory,
1176
1195
  resolveDockerfileCandidates,
1177
1196
  staticBuilderOutputPath,
1178
1197
  generateDockerfile,
@@ -6,7 +6,7 @@ import {
6
6
  detectBuildKillHint,
7
7
  runBuildPipeline,
8
8
  transferLocalDirectory
9
- } from "./chunk-VDDMADOF.js";
9
+ } from "./chunk-TM2IQPYU.js";
10
10
  import {
11
11
  LocalExecutor
12
12
  } from "./chunk-6FH4AXVY.js";
@@ -2,12 +2,22 @@
2
2
  ":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
3
3
  import { createRequire as __ospCreateRequire } from "node:module";
4
4
  const require = __ospCreateRequire(import.meta.url);
5
+ import {
6
+ envOps,
7
+ opScript
8
+ } from "./chunk-EZPPTWJQ.js";
9
+ import {
10
+ resolveEnvironment
11
+ } from "./chunk-WFRXYWK2.js";
5
12
  import {
6
13
  sq
7
14
  } from "./chunk-ZFJXPCQP.js";
8
15
  import {
16
+ SYSTEM,
17
+ answered,
18
+ refused,
9
19
  safeErrorMessage
10
- } from "./chunk-OTLSJYAC.js";
20
+ } from "./chunk-LEYSL46B.js";
11
21
 
12
22
  // ../../packages/adapters/src/infra/openresty-lua.ts
13
23
  import { createHash, randomBytes } from "crypto";
@@ -126,6 +136,40 @@ function edgeRealIpConf() {
126
136
  }
127
137
  return lines.join("\n") + "\n";
128
138
  }
139
+ var CLOUD_EDGE_REAL_IP_HEADER = "X-Real-IP";
140
+ function isCloudFrontedHost(hostname) {
141
+ const host = hostname.trim().toLowerCase().replace(/\.+$/, "");
142
+ const suffix = `.${SYSTEM.DOMAINS.CLOUD_DOMAIN.toLowerCase()}`;
143
+ return host.length > suffix.length && host.endsWith(suffix);
144
+ }
145
+ function cloudEdgeRealIpConf(indent = " ") {
146
+ const lines = [
147
+ "# Openship Cloud's edge fronts this free host, so the peer is the edge and the",
148
+ "# visitor is named in X-Real-IP (which that front OVERWRITES). The http-scope block",
149
+ "# reads CF-Connecting-IP for Cloudflare-fronted custom domains, and there is one",
150
+ "# real_ip_header per scope \u2014 hence this override.",
151
+ "#",
152
+ "# Trust is scoped to this VHOST instead of to a peer list, deliberately. The Cloud",
153
+ "# edge reaches origins from its own address, which this box has no way to know and",
154
+ "# which Cloudflare's ranges (the visitor\u2192edge leg) do not contain \u2014 so a peer list",
155
+ "# here silently ignores the header and every free-domain visitor stays the edge.",
156
+ "#",
157
+ "# What bounds it is the server_name: this block exists only inside a <slug>.opsh.io",
158
+ "# vhost, a hostname whose only legitimate path is that edge. Someone who reaches this",
159
+ "# box directly on :80 with a forged Host AND a forged X-Real-IP can choose their own",
160
+ "# apparent address for THIS vhost \u2014 accepted, because the alternative is the address",
161
+ "# being wrong for every visitor all the time. Custom domains keep the peer-anchored",
162
+ "# http-scope block; do not widen this to them.",
163
+ `real_ip_header ${CLOUD_EDGE_REAL_IP_HEADER};`,
164
+ // OFF, unlike the http-scope block: the Cloud edge OVERWRITES X-Real-IP with a single
165
+ // address, so there is no list to walk, and "skip trusted addresses from the right"
166
+ // has no meaning once every address is trusted.
167
+ "real_ip_recursive off;",
168
+ "set_real_ip_from 0.0.0.0/0;",
169
+ "set_real_ip_from ::/0;"
170
+ ];
171
+ return lines.map((l) => `${indent}${l}`).join("\n") + "\n";
172
+ }
129
173
 
130
174
  // ../../packages/adapters/src/infra/edge-not-found.ts
131
175
  var EDGE_UNROUTED_SENTINEL = "openship-edge-unrouted";
@@ -266,6 +310,9 @@ var EDGE_CONTAINER_MOUNTS = [
266
310
  { host: `${EDGE_HOST_STATE_DIR}/acme`, container: "/var/www/acme" },
267
311
  { host: "/opt/openship/static", container: "/opt/openship/static" }
268
312
  ];
313
+ var EDGE_SAME_PATH_MOUNTS = EDGE_CONTAINER_MOUNTS.filter(
314
+ (m) => m.host === m.container
315
+ ).map((m) => m.host.replace(/\/+$/, ""));
269
316
  var EDGE_HOST_PATHS = {
270
317
  bin: OPENRESTY_DEFAULT_PATHS.bin,
271
318
  confPath: OPENRESTY_DEFAULT_PATHS.confPath,
@@ -455,7 +502,7 @@ var MANAGEMENT_BLOCK = `# Openship internal management - analytics & live-log st
455
502
  ${EDGE_MGMT_SERVER_BLOCK}
456
503
  `;
457
504
  var ACME_HTTP01_PORT = 49180;
458
- var ACME_CHALLENGE_LOCATION = ` location /.well-known/acme-challenge/ {
505
+ var ACME_CHALLENGE_LOCATION = ` location ^~ /.well-known/acme-challenge/ {
459
506
  proxy_pass http://127.0.0.1:${ACME_HTTP01_PORT};
460
507
  proxy_set_header Host $host;
461
508
  }`;
@@ -466,7 +513,7 @@ var EDGE_CHALLENGE_HOST_DIR = `${EDGE_HOST_STATE_DIR}/acme/oblien${EDGE_CHALLENG
466
513
  /\/$/,
467
514
  ""
468
515
  );
469
- var EDGE_CHALLENGE_LOCATION = ` location ${EDGE_CHALLENGE_URL_PREFIX} {
516
+ var EDGE_CHALLENGE_LOCATION = ` location ^~ ${EDGE_CHALLENGE_URL_PREFIX} {
470
517
  root ${EDGE_CHALLENGE_ROOT};
471
518
  default_type text/plain;
472
519
  try_files $uri =404;
@@ -600,27 +647,22 @@ async function ensureLuaScripts(executor, paths) {
600
647
  }
601
648
  }
602
649
  async function installGeoDeps(executor) {
603
- try {
604
- const hasPkg = async (cmd) => {
605
- try {
606
- await executor.exec(`command -v ${cmd}`);
607
- return true;
608
- } catch {
609
- return false;
610
- }
611
- };
612
- if (await hasPkg("apt-get")) {
613
- await executor.exec(
614
- "apt-get update -qq && apt-get install -y -qq libmaxminddb0 libmaxminddb-dev"
650
+ const profile = await resolveEnvironment(executor).catch((err) => safeErrorMessage(err));
651
+ const install = typeof profile === "string" ? refused(`the host profile could not be read: ${profile}`) : envOps(profile).pkgInstallVariants({
652
+ apt: answered(["libmaxminddb0", "libmaxminddb-dev"]),
653
+ dnf: answered(["libmaxminddb", "libmaxminddb-devel"]),
654
+ yum: answered(["libmaxminddb", "libmaxminddb-devel"]),
655
+ apk: answered(["libmaxminddb"]),
656
+ brew: refused("the bare edge is Linux-only, so Openship has no macOS package for it.")
657
+ });
658
+ if (install.supported) {
659
+ await executor.exec(opScript(install.value)).catch((err) => {
660
+ console.warn(
661
+ `[openresty] libmaxminddb install failed \u2014 geo lookups return nil: ${safeErrorMessage(err)}`
615
662
  );
616
- } else if (await hasPkg("dnf")) {
617
- await executor.exec("dnf install -y libmaxminddb libmaxminddb-devel");
618
- } else if (await hasPkg("yum")) {
619
- await executor.exec("yum install -y libmaxminddb libmaxminddb-devel");
620
- } else if (await hasPkg("apk")) {
621
- await executor.exec("apk add --no-cache libmaxminddb");
622
- }
623
- } catch {
663
+ });
664
+ } else {
665
+ console.warn(`[openresty] libmaxminddb not installed \u2014 geo lookups return nil: ${install.reason}`);
624
666
  }
625
667
  try {
626
668
  const exists = await executor.exists(GEOIP_DB_PATH);
@@ -665,6 +707,8 @@ async function deployLuaScripts(executor, paths) {
665
707
  }
666
708
 
667
709
  export {
710
+ isCloudFrontedHost,
711
+ cloudEdgeRealIpConf,
668
712
  OPENRESTY_LUA_DIR,
669
713
  LUA_LOGGER_PATH,
670
714
  RULES_GUARD_PATH,
@@ -679,6 +723,7 @@ export {
679
723
  EDGE_DEFAULT_CERT_CN,
680
724
  EDGE_HOST_STATE_DIR,
681
725
  EDGE_CONTAINER_MOUNTS,
726
+ EDGE_SAME_PATH_MOUNTS,
682
727
  EDGE_HOST_PATHS,
683
728
  detectOpenRestyPaths,
684
729
  buildReloadCommand,