igneum/infra/cloud-devnet/experiments/observer.sh
igneum-labs d6c69bcb0c infra: cloud devnet (20 nodes), rented GPU bench and seed node scripts; plans for both
infra/cloud-devnet: hcloud (doctl variant) create, builder-VM provision from a git-archive source tarball,
systemd units for igneumd --devnet-suffix with a sparse --addpeer mesh and a CPU trickle miner per node,
stdlib wRPC client, experiments (latency, partition, hop, collect, observer hookup), README with the command
sequence and the Hetzner API prices of 3 Oct 2026.
infra/gpu-bench: RunPod image recipes (CUDA 12.8, ROCm), bundle, run.sh (vectors gate, 10-min raw, sweep,
inline shortcut ratio, nvcc/NVRTC/OpenCL recompile timings, results row, intake upload), bench-log template.
infra/seed-nodes: create-seed (persistent IPv4, firewall), provision on the VM, health check, addPeer from the
Mac over grpcurl, seeds.txt; igneum-seed-1 created at 188.245.5.161 (Hetzner cx23, fsn1).
docs/plans/cloud-devnet.md and docs/plans/seed-nodes.md.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-03 22:01:50 +00:00

55 lines
3.6 KiB
Bash
Executable file

#!/usr/bin/env bash
# Observer hookup: let tools/observer/observer.mjs watch one cloud node so /live on the site shows the 20-node network.
# The RPC never leaves the node's loopback, so the observer reaches it through an ssh tunnel (from the Mac) or runs
# on the node itself (remote mode, keeps the overloaded Mac out of it).
#
# ./experiments/observer.sh tunnel [node] ssh -L 28610 -> the node's wRPC JSON; prints the observer command
# ./experiments/observer.sh remote on [node] install Node 22 on the node, copy observer.mjs and DATABASE_URL, start a unit
# ./experiments/observer.sh remote off [node] stop and remove that unit (the DATABASE_URL file is deleted too)
#
# Tables: with LIVE_TABLE_PREFIX=cloud_ the observer writes cloud_live_* and the public page keeps showing the Mac's
# devnet (site/api/live.mjs reads the unprefixed tables; it has no prefix switch, so a side-by-side page needs that
# one-line change in site/). Without the prefix the cloud network REPLACES the Mac's devnet on /live: stop the
# Mac's observer first, or two writers fight over live_state.
. "$(dirname "$0")/../lib/common.sh"
require_nodes
mode="${1:-}"; node="${3:-${2:-}}"
case "$mode" in
tunnel)
node="${2:-$(node_name 1)}"; ip=$(node_ip "$node")
log "tunnel to $node ($ip): local ws://127.0.0.1:${LOCAL_PORT:-28620} -> node 127.0.0.1:$RPC_JSON_PORT (Ctrl+C ends it)"
log "in another shell, from the repo root:"
log " IGNEUM_RPC=ws://127.0.0.1:${LOCAL_PORT:-28620} LIVE_TABLE_PREFIX=cloud_ node tools/observer/observer.mjs # parallel record"
log " IGNEUM_RPC=ws://127.0.0.1:${LOCAL_PORT:-28620} node tools/observer/observer.mjs # takes over /live (stop the Mac's observer first)"
exec ssh "${SSH_OPTS[@]}" -N -L "${LOCAL_PORT:-28620}:127.0.0.1:$RPC_JSON_PORT" "$SSH_USER@$ip"
;;
remote)
sub="${2:-}"; node="${3:-$(node_name 1)}"; ip=$(node_ip "$node")
if [ "$sub" = on ]; then
envf="$HOME/.config/igneum/env"; [ -f "$envf" ] || die "no $envf (DATABASE_URL)"
dburl=$(grep -E '^DATABASE_URL=' "$envf" | head -1)
[ -n "$dburl" ] || die "DATABASE_URL not in $envf"
log "installing Node 22 (NodeSource apt repository) and the observer on $node"
nssh "$ip" 'command -v node >/dev/null && node -v | grep -q "^v2[2-9]" || { curl -fsSL https://deb.nodesource.com/setup_22.x | bash - >/dev/null && apt-get install -y -qq nodejs >/dev/null; }; node -v'
nscp "$REPO/tools/observer/observer.mjs" "$SSH_USER@$ip:/opt/igneum/observer.mjs"
printf '%s\nIGNEUM_RPC=ws://127.0.0.1:%s\nLIVE_TABLE_PREFIX=%s\n' "$dburl" "$RPC_JSON_PORT" "${LIVE_TABLE_PREFIX:-cloud_}" | nssh "$ip" 'umask 077; cat > /etc/igneum/observer.env'
nssh "$ip" 'cat > /etc/systemd/system/igneum-observer.service <<EOF
[Unit]
Description=Igneum devnet observer (writes the live tables in Neon)
After=igneumd.service
[Service]
EnvironmentFile=/etc/igneum/observer.env
ExecStart=/usr/bin/node /opt/igneum/observer.mjs
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload && systemctl enable --now igneum-observer && sleep 3 && journalctl -u igneum-observer --no-pager -n 5'
log "observer running on $node with LIVE_TABLE_PREFIX=${LIVE_TABLE_PREFIX:-cloud_} (empty prefix = it takes over /live)"
elif [ "$sub" = off ]; then
nssh "$ip" 'systemctl disable --now igneum-observer 2>/dev/null; rm -f /etc/systemd/system/igneum-observer.service /etc/igneum/observer.env; systemctl daemon-reload; echo removed'
else die "usage: observer.sh remote on|off [node]"; fi
;;
*) die "usage: observer.sh tunnel [node] | observer.sh remote on|off [node]" ;;
esac