Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ repos:

- id: pyright-check
name: Pyright (nemoclaw-blueprint)
entry: bash -c 'cd nemoclaw-blueprint && uv run --with pyright pyright'
entry: bash -c 'cd nemoclaw-blueprint && uv run --with pyright --with pytest pyright'
language: system
pass_filenames: false
always_run: true
Expand Down
10 changes: 8 additions & 2 deletions bin/lib/onboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -459,14 +459,15 @@ async function startGateway(gpu) {
sleep(2);
}

// CoreDNS fix — always run. k3s-inside-Docker has broken DNS on all platforms.
// CoreDNS fix — k3s-inside-Docker has broken DNS forwarding on all platforms.
const runtime = getContainerRuntime();
if (shouldPatchCoredns(runtime)) {
console.log(" Patching CoreDNS for Colima...");
console.log(" Patching CoreDNS DNS forwarding...");
run(`bash "${path.join(SCRIPTS, "fix-coredns.sh")}" nemoclaw 2>&1 || true`, { ignoreError: true });
}
// Give DNS a moment to propagate
sleep(5);

}

// ── Step 3: Sandbox ──────────────────────────────────────────────
Expand Down Expand Up @@ -613,6 +614,11 @@ async function createSandbox(gpu) {
gpuEnabled: !!gpu,
});

// DNS proxy — run a forwarder in the sandbox pod so the isolated
// sandbox namespace can resolve DNS. Must run after sandbox is Ready.
console.log(" Setting up sandbox DNS proxy...");
run(`bash "${path.join(SCRIPTS, "setup-dns-proxy.sh")}" nemoclaw "${sandboxName}" 2>&1 || true`, { ignoreError: true });
Comment on lines +617 to +620

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Don't complete onboarding before sandbox DNS is verified.

This path keeps the new sandbox even when the DNS proxy install fails, so users can end up with a registered sandbox that still has broken hostname resolution. Please make this step fail the flow, or gate completion on a post-check from inside the sandbox.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bin/lib/onboard.js` around lines 617 - 620, The DNS proxy installation is
currently allowed to fail silently because run(...) is invoked with {
ignoreError: true }, so remove the ignoreError bypass (or detect the run exit
status) and make the onboarding flow exit/throw on failure of run("...
setup-dns-proxy.sh ...", ...); additionally, after the script completes, perform
a verification step (e.g., kubectl exec into the sandbox pod identified by
sandboxName and run a DNS lookup like dig/host against the expected host) and
only mark onboarding complete if that check succeeds—update the logic around
run, SCRIPTS, and sandboxName to fail the onboarding or rollback the sandbox
when either the install or the post-install DNS verification fails.


console.log(` ✓ Sandbox '${sandboxName}' created`);
return sandboxName;
}
Expand Down
5 changes: 4 additions & 1 deletion bin/lib/platform.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ function isUnsupportedMacosRuntime(runtime, opts = {}) {
}

function shouldPatchCoredns(runtime) {
return runtime === "colima";
// k3s-inside-Docker has broken DNS forwarding on all platforms
// (systemd-resolved, Docker Desktop DNS, Colima DNS).
// Always patch CoreDNS to use a non-loopback upstream.
return runtime !== "unknown";
}

function getColimaDockerSocketCandidates(opts = {}) {
Expand Down
36 changes: 20 additions & 16 deletions scripts/fix-coredns.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Fix CoreDNS on local OpenShell gateways running under Colima.
# Fix CoreDNS on local OpenShell gateways.
#
# Problem: k3s CoreDNS forwards to /etc/resolv.conf which inside the
# CoreDNS pod resolves to 127.0.0.11 (Docker's embedded DNS). That
# address is NOT reachable from k3s pods, causing DNS to fail and
# CoreDNS to CrashLoop.
# CoreDNS pod resolves to a loopback address (127.0.0.11 on Docker,
# 127.0.0.53 on systemd-resolved hosts). That address is NOT reachable
# from k3s pods, causing DNS to fail and CoreDNS to CrashLoop.
#
# Fix: forward CoreDNS to the container's default gateway IP, which
# is reachable from pods and routes DNS through Docker to the host.
# Fix: forward CoreDNS to a non-loopback upstream — either the
# container's default gateway IP (routes through Docker to the host)
# or a public DNS server (8.8.8.8) as a last resort.
#
# Run this after `openshell gateway start` on Colima setups.
# Run this after `openshell gateway start`.
#
# Usage: ./scripts/fix-coredns.sh [gateway-name]

Expand All @@ -23,15 +24,11 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# shellcheck source=./lib/runtime.sh
. "$SCRIPT_DIR/lib/runtime.sh"

COLIMA_SOCKET="$(find_colima_docker_socket || true)"

if [ -z "${DOCKER_HOST:-}" ]; then
if [ -n "$COLIMA_SOCKET" ]; then
export DOCKER_HOST="unix://$COLIMA_SOCKET"
else
echo "Skipping CoreDNS patch: Colima socket not found."
exit 0
if docker_host="$(detect_docker_host)"; then
export DOCKER_HOST="$docker_host"
fi
# If still unset, Docker CLI will use the default socket
fi
Comment on lines 27 to 32

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard this path to local Docker daemons.

This generalized flow still derives the fallback resolver from the local machine, but now runs against any detected Docker engine. When DOCKER_HOST points at a remote daemon, the remote CoreDNS config gets patched with the workstation's DNS, which may be unreachable from that cluster. Please either reject non-local Docker hosts here or derive the upstream entirely from the daemon/gateway side.

Also applies to: 49-55

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/fix-coredns.sh` around lines 27 - 32, The current path blindly
accepts any value returned by detect_docker_host into DOCKER_HOST, which can
point at a remote daemon and thus pollute the remote CoreDNS config; change the
logic around the DOCKER_HOST assignment (the docker_host variable and
detect_docker_host call) to validate that the returned host is local before
exporting it — only accept unix socket paths or TCP hosts that resolve to
localhost/127.0.0.1 (or ::1); if docker_host is remote, do not set DOCKER_HOST
and instead fall back to deriving upstream from the daemon/gateway side or bail
with a clear message; apply the same guard/validation to the analogous block
referenced at the later section (lines 49-55).


# Find the cluster container
Expand All @@ -48,10 +45,17 @@ fi

CONTAINER_RESOLV_CONF="$(docker exec "$CLUSTER" cat /etc/resolv.conf 2>/dev/null || true)"
HOST_RESOLV_CONF="$(cat /etc/resolv.conf 2>/dev/null || true)"
UPSTREAM_DNS="$(resolve_coredns_upstream "$CONTAINER_RESOLV_CONF" "$HOST_RESOLV_CONF" "colima" || true)"

# Detect runtime for Colima-specific DNS discovery paths
RUNTIME="unknown"
if [ -n "${DOCKER_HOST:-}" ]; then
RUNTIME="$(docker_host_runtime "$DOCKER_HOST" || echo "unknown")"
fi

UPSTREAM_DNS="$(resolve_coredns_upstream "$CONTAINER_RESOLV_CONF" "$HOST_RESOLV_CONF" "$RUNTIME" || true)"

if [ -z "$UPSTREAM_DNS" ]; then
echo "ERROR: Could not determine a non-loopback DNS upstream for Colima."
echo "ERROR: Could not determine a non-loopback DNS upstream."
exit 1
fi

Expand Down
4 changes: 3 additions & 1 deletion scripts/lib/runtime.sh
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,9 @@ resolve_coredns_upstream() {
return 0
fi

return 1
# Last resort: public DNS. Needed on hosts where all nameservers are
# loopback (e.g. systemd-resolved uses 127.0.0.53).
printf '8.8.8.8\n'
Comment on lines +166 to +168

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Don't fall back to public DNS before exhausting the host resolver.

On the common 127.0.0.53 / ::1 case this branch now pins CoreDNS to 8.8.8.8 instead of the machine's real upstreams, which breaks split-DNS/VPN/internal zones and leaks queries to a public resolver. Please resolve systemd-resolved's actual upstreams first and treat IPv6 loopback as loopback too.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/lib/runtime.sh` around lines 166 - 168, The current last-resort
branch in runtime.sh that prints '8.8.8.8' must be changed to first attempt to
resolve systemd-resolved's real upstreams and to treat IPv6 loopback as loopback
too; update the logic around the printf '8.8.8.8' to (1) try to read upstream
servers from systemd-resolved (e.g. via resolvectl status or
/run/systemd/resolve/resolv.conf) and extract non-loopback IPs, (2) filter out
loopback addresses including 127.0.0.0/8 and ::1 (and equivalent IPv4-mapped
loopback), and (3) only fall back to a public resolver like 8.8.8.8 if no
non-loopback upstreams are found; keep the change localized to the branch that
currently emits '8.8.8.8' so CoreDNS uses the machine's upstreams when
available.

}

select_openshell_cluster_container() {
Expand Down
193 changes: 193 additions & 0 deletions scripts/setup-dns-proxy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
#!/usr/bin/env bash
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Fix sandbox DNS by running a lightweight DNS forwarder in the sandbox pod.
#
# Problem: The sandbox runs in an isolated network namespace (10.200.0.0/24).
# Its /etc/resolv.conf points to the k3s CoreDNS service IP (10.43.0.10), but
# DNS packets from the sandbox route through the pod namespace — where the
# CoreDNS service IP is not locally handled. The result: dns.lookup() fails
# with EAI_AGAIN for every outbound request.
#
# Fix: Run a Python DNS forwarder in the sandbox pod's namespace that:
# 1. Adds 10.43.0.10 as a local address on lo (so packets from the sandbox
# are delivered locally instead of forwarded)
# 2. Listens on 0.0.0.0:53 (UDP) and forwards to public DNS (8.8.8.8)
#
# The sandbox's existing resolv.conf (nameserver 10.43.0.10) works without
# modification — the forwarder intercepts the traffic transparently.
#
# The DNS proxy is launched via `docker exec -d` + `nsenter` from the gateway
# container, which keeps it alive as a persistent background process.
#
# Requires: sandbox must be in Ready state. Run after sandbox creation.
#
# Usage: ./scripts/setup-dns-proxy.sh [gateway-name] <sandbox-name>

set -euo pipefail

GATEWAY_NAME="${1:-}"
SANDBOX_NAME="${2:-}"

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# shellcheck source=./lib/runtime.sh
. "$SCRIPT_DIR/lib/runtime.sh"

if [ -z "$SANDBOX_NAME" ]; then
echo "Usage: $0 [gateway-name] <sandbox-name>"
exit 1
fi

# CoreDNS service IP that the sandbox's /etc/resolv.conf points to
COREDNS_SERVICE_IP="10.43.0.10"
# DNS_UPSTREAM is set below after we discover the CoreDNS pod IP

# ── Find the gateway container ──────────────────────────────────────

if [ -z "${DOCKER_HOST:-}" ]; then
if docker_host="$(detect_docker_host)"; then
export DOCKER_HOST="$docker_host"
fi
fi

CLUSTERS="$(docker ps --filter "name=openshell-cluster" --format '{{.Names}}' 2>/dev/null || true)"
CLUSTER="$(select_openshell_cluster_container "$GATEWAY_NAME" "$CLUSTERS" || true)"

if [ -z "$CLUSTER" ]; then
if [ -n "$GATEWAY_NAME" ]; then
echo "ERROR: Could not find gateway container for '$GATEWAY_NAME'."
else
echo "ERROR: Could not find any openshell cluster container."
fi
exit 1
fi

# ── Helper: kubectl via gateway ─────────────────────────────────────

kctl() {
docker exec "$CLUSTER" kubectl "$@"
}

# ── Discover CoreDNS pod IP ─────────────────────────────────────────
#
# Forward to CoreDNS (not 8.8.8.8) so k8s-internal names like
# openshell-0.openshell.svc.cluster.local still resolve. CoreDNS
# handles both k8s names (kubernetes plugin) and external names
# (forward plugin, patched by fix-coredns.sh).

DNS_UPSTREAM="$(kctl get endpoints kube-dns \
-n kube-system -o jsonpath='{.subsets[0].addresses[0].ip}' 2>/dev/null || true)"

if [ -z "$DNS_UPSTREAM" ]; then
echo "WARNING: Could not discover CoreDNS pod IP. Falling back to 8.8.8.8."
echo "WARNING: k8s-internal names (inference.local routing) will NOT work."
DNS_UPSTREAM="8.8.8.8"
fi

# ── Find the sandbox pod and its PID ────────────────────────────────

POD="$(kctl get pods -n openshell -o name 2>/dev/null \
| grep -- "$SANDBOX_NAME" | head -1 | sed 's|pod/||' || true)"

Comment on lines +90 to +92

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use fixed-string matching for sandbox name.

The grep without -F interprets $SANDBOX_NAME as a regex pattern. If sandbox names contain characters like ., *, or [, this could match unintended pods.

Proposed fix
-POD="$(kctl get pods -n openshell -o name 2>/dev/null \
-  | grep -- "$SANDBOX_NAME" | head -1 | sed 's|pod/||' || true)"
+POD="$(kctl get pods -n openshell -o name 2>/dev/null \
+  | grep -F -- "$SANDBOX_NAME" | head -1 | sed 's|pod/||' || true)"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
POD="$(kctl get pods -n openshell -o name 2>/dev/null \
| grep -- "$SANDBOX_NAME" | head -1 | sed 's|pod/||' || true)"
POD="$(kctl get pods -n openshell -o name 2>/dev/null \
| grep -F -- "$SANDBOX_NAME" | head -1 | sed 's|pod/||' || true)"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/setup-dns-proxy.sh` around lines 90 - 92, The pipeline that sets POD
uses grep -- "$SANDBOX_NAME" which treats the sandbox name as a regex; change
grep to fixed-string mode (e.g., use grep -F -- "$SANDBOX_NAME") so special
characters in $SANDBOX_NAME are matched literally. Update the line that assigns
POD (the command pipeline with kctl get pods | grep -- "$SANDBOX_NAME" | head -1
| sed 's|pod/||') to use grep -F -- "$SANDBOX_NAME" to ensure correct, literal
matching.

if [ -z "$POD" ]; then
echo "ERROR: Could not find pod for sandbox '$SANDBOX_NAME'."
exit 1
fi

# Get the pod's init PID as seen from the gateway container (for nsenter)
POD_PID="$(docker exec "$CLUSTER" sh -c "
# Find PID that has the pod's hostname in its UTS namespace
for pid in /proc/[0-9]*/ns; do
p=\${pid%/ns}; p=\${p##*/}
if [ -f /proc/\$p/root/etc/hostname ] 2>/dev/null; then
hn=\$(cat /proc/\$p/root/etc/hostname 2>/dev/null)
if [ \"\$hn\" = \"$POD\" ]; then
echo \$p
break
fi
fi
done
" 2>/dev/null || true)"

if [ -z "$POD_PID" ]; then
echo "WARNING: Could not find pod PID via hostname. Trying kubectl..."
# Fallback: use kubectl exec to find a PID we can nsenter into
POD_PID="$(kctl exec -n openshell "$POD" -- sh -c 'echo $$' 2>/dev/null || true)"
fi
Comment on lines +113 to +117

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fallback PID may not be valid for nsenter.

The fallback uses kubectl exec ... echo $$ which returns the shell's PID as seen from within the pod's PID namespace. However, nsenter -t "$POD_PID" (line 181) requires the PID as seen from the gateway container's namespace. These are different values.

If the primary hostname-matching method fails and this fallback is used, the subsequent nsenter at line 181 will likely fail or enter the wrong namespace.

Consider either:

  1. Removing the fallback and failing explicitly
  2. Finding the PID through an alternative host-visible method
Option: Remove fallback and fail explicitly
 if [ -z "$POD_PID" ]; then
-  echo "WARNING: Could not find pod PID via hostname. Trying kubectl..."
-  # Fallback: use kubectl exec to find a PID we can nsenter into
-  POD_PID="$(kctl exec -n openshell "$POD" -- sh -c 'echo $$' 2>/dev/null || true)"
-fi
-
-if [ -z "$POD_PID" ]; then
   echo "ERROR: Could not determine pod PID for nsenter."
+  echo "       Hostname matching in /proc failed for pod '$POD'."
   exit 1
 fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/setup-dns-proxy.sh` around lines 113 - 117, The fallback that sets
POD_PID via "kctl exec ... echo $$" is invalid for nsenter because that PID is
in the pod's PID namespace, not the gateway/container host namespace; remove the
fallback block that assigns POD_PID with kctl exec and instead fail explicitly
when POD_PID is empty (print a clear error and exit non-zero), so the later
nsenter invocation (which requires a host-visible PID) is not attempted with a
wrong value; update the script's POD_PID handling to use the original hostname
method only and error out if POD_PID remains unset (references: POD_PID, kctl
exec, nsenter).


if [ -z "$POD_PID" ]; then
echo "ERROR: Could not determine pod PID for nsenter."
exit 1
fi

echo "Setting up DNS proxy in pod '$POD' (pid=$POD_PID, ${COREDNS_SERVICE_IP} → ${DNS_UPSTREAM})..."

# ── Step 1: Add CoreDNS service IP as local address ─────────────────

kctl exec -n openshell "$POD" -- \
ip addr add "${COREDNS_SERVICE_IP}/32" dev lo 2>/dev/null || true

# ── Step 2: Write DNS proxy script to the pod ───────────────────────

kctl exec -n openshell "$POD" -- sh -c "cat > /tmp/dns-proxy.py << DNSPROXY
import socket, threading, os

UPSTREAM = ('${DNS_UPSTREAM}', 53)

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('10.43.0.10', 53))

with open('/tmp/dns-proxy.pid', 'w') as pf:
pf.write(str(os.getpid()))

with open('/tmp/dns-proxy.log', 'w') as log:
log.write('dns-proxy: 10.43.0.10:53 -> {}:{} pid={}\n'.format(
UPSTREAM[0], UPSTREAM[1], os.getpid()))

def forward(data, addr):
try:
f = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
f.settimeout(5)
f.sendto(data, UPSTREAM)
r, _ = f.recvfrom(4096)
sock.sendto(r, addr)
f.close()
except Exception:
pass

while True:
d, a = sock.recvfrom(4096)
threading.Thread(target=forward, args=(d, a), daemon=True).start()
DNSPROXY"

# ── Step 3: Kill any existing DNS proxy ─────────────────────────────

OLD_PID="$(kctl exec -n openshell "$POD" -- cat /tmp/dns-proxy.pid 2>/dev/null || true)"
if [ -n "$OLD_PID" ]; then
kctl exec -n openshell "$POD" -- kill "$OLD_PID" 2>/dev/null || true
sleep 1
fi

# ── Step 4: Launch DNS proxy via docker exec -d (persistent) ────────
#
# Using `docker exec -d` (detached) + `nsenter` to enter the pod's
# network and mount namespaces. This creates a persistent process that
# survives after the script exits — unlike kubectl exec which kills
# child processes on session end.

docker exec -d "$CLUSTER" \
nsenter -t "$POD_PID" -n -m -- \
python3 -u /tmp/dns-proxy.py

sleep 2

# ── Step 5: Verify ──────────────────────────────────────────────────

LOG="$(kctl exec -n openshell "$POD" -- cat /tmp/dns-proxy.log 2>/dev/null || true)"
if echo "$LOG" | grep -q "dns-proxy:"; then
echo "DNS proxy started: $LOG"
else
echo "WARNING: DNS proxy may not have started. Log: $LOG"
fi
10 changes: 7 additions & 3 deletions scripts/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,9 @@ for i in 1 2 3 4 5; do
done
info "Gateway is healthy"

# 2. CoreDNS fix (Colima only)
if [ "$CONTAINER_RUNTIME" = "colima" ]; then
info "Patching CoreDNS for Colima..."
# 2. CoreDNS fix — k3s-inside-Docker has broken DNS forwarding on all platforms.
if [ "$CONTAINER_RUNTIME" != "unknown" ]; then
info "Patching CoreDNS DNS forwarding..."
bash "$SCRIPT_DIR/fix-coredns.sh" nemoclaw 2>&1 || warn "CoreDNS patch failed (may not be needed)"
fi

Expand Down Expand Up @@ -230,6 +230,10 @@ if ! echo "$SANDBOX_LINE" | grep -q "Ready"; then
fail "Sandbox created but not Ready (phase: ${SANDBOX_PHASE:-unknown}). Check 'openshell sandbox get ${SANDBOX_NAME}'."
fi

# 5b. DNS proxy for sandbox — run after sandbox is Ready.
info "Setting up sandbox DNS proxy..."
bash "$SCRIPT_DIR/setup-dns-proxy.sh" nemoclaw "$SANDBOX_NAME" 2>&1 || warn "DNS proxy setup failed (may not be needed)"
Comment on lines +233 to +235

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Make DNS proxy setup part of the success criteria.

setup-dns-proxy.sh is the fix that restores sandbox-side dns.lookup() / getaddrinfo(). Swallowing failures here lets setup.sh finish with “Setup complete!” even though the sandbox still returns EAI_AGAIN. Fail the setup, or at least run an in-sandbox resolution check and only continue when it passes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/setup.sh` around lines 233 - 235, The DNS proxy step currently
swallows errors (bash "$SCRIPT_DIR/setup-dns-proxy.sh" ... || warn ...) so
setup.sh can report success despite unresolved EAI_AGAIN; change this to treat
failures as fatal or block until DNS works: invoke setup-dns-proxy.sh without
the short-circuit warn and if it exits non-zero call error/exit (or retry), then
perform an in-sandbox resolution check (e.g., run a simple node or getent/dig
inside the sandbox using SANDBOX_NAME) and loop/retry with backoff until the
lookup succeeds before printing "Setup complete!" — update the calls around info
"Setting up sandbox DNS proxy...", the bash invocation of setup-dns-proxy.sh,
and the subsequent success path to enforce failure or readiness check.


# 6. Done
echo ""
info "Setup complete!"
Expand Down
Loading
Loading