Build server: wait-<pid> file while a build queues for a slot; Caddy serves the dashboard's two JSON files at build.igneum.network

remote-run.sh writes /srv/builds/_locks/wait-<pid> in the slot-file line format while it waits and removes it when the
slot is taken or the wait is given up (shown: present during a held slot, gone after). provision.sh installs Caddy with a
Caddyfile that serves only /srv/workers/workers.json and headline.json (every other path 404, CORS for dl.igneum.network,
no-store, Let's Encrypt only) and opens 80 and 443. Both asked for by the worker-dashboard agent, approved by main.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
igneum-labs 2026-10-06 17:59:02 +00:00
parent aed5ca9bd7
commit d9e580d3bd
2 changed files with 46 additions and 3 deletions

View file

@ -32,6 +32,7 @@
# chain) listens on the same 26611 (infra/cloud-devnet/config.sh P2P_PORT=26611). RPC ports
# (26610, 28610, 26790 and the 268xx set) stay on loopback as on every seed, so they are not opened.
# BOX_HOSTNAME igneum-build-1
# WORKERS_HOST build.igneum.network Caddy serves /srv/workers/{workers,headline}.json there (read-only, all else 404)
# SSH_PUBKEY (unset) a public key line for the build user when root has no authorized_keys (installimage installs it)
#
# Mirrors: the Mac pushes to them (never a clone from GitHub; the fork vendor/igneum-node exists only on the Mac):
@ -54,6 +55,7 @@ WORKTREES="${WORKTREES:-}"
SLOTS="${SLOTS:-1}"
P2P_PORTS="${P2P_PORTS:-26611 26811}"
BOX_HOSTNAME="${BOX_HOSTNAME:-igneum-build-1}"
WORKERS_HOST="${WORKERS_HOST:-build.igneum.network}" # the dashboard feed's HTTPS name (A record in deSEC, 6 Oct 2026)
SSH_PUBKEY="${SSH_PUBKEY:-}"
BUILD_USER=build
BUILD_HOME=/home/$BUILD_USER
@ -122,7 +124,7 @@ step_os_check() {
APT_PACKAGES=(
build-essential clang lld llvm libclang-dev pkg-config libssl-dev cmake protobuf-compiler
gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 binutils-mingw-w64-x86-64 mingw-w64-x86-64-dev mingw-w64-tools
git tmux curl ca-certificates xz-utils zstd unzip rsync jq python3 ufw htop file
git tmux curl ca-certificates xz-utils zstd unzip rsync jq python3 ufw htop file caddy
)
step_apt() {
local need=() p
@ -337,17 +339,49 @@ EOF
changed sshd "key-only, root prohibit-password"
}
# the worker dashboard's feed (asked for on 6 October 2026, approved by main): Caddy serves exactly two files of /srv/workers
# over HTTPS at build.igneum.network (A record in deSEC, set by main), read-only, no directory listing, every other path 404,
# CORS for dl.igneum.network, no caching. Nothing under /srv/workers is a secret (workers.json and headline.json are written
# by the dashboard collector and remote-run.sh); the Caddyfile refuses every other file name anyway. Issuer pinned to Let's
# Encrypt: Ubuntu's Caddy 2.6.2 fails the ZeroSSL fallback (HTTP 422 caddy_legacy_user_removed, 6 Oct 2026) and would retry it for ever.
step_caddy() {
local f=/etc/caddy/Caddyfile tmp
command -v caddy >/dev/null 2>&1 || die "caddy is not installed (apt)"
install -d -m 755 -o "$BUILD_USER" -g "$BUILD_USER" /srv/workers
tmp=$(mktemp)
cat > "$tmp" <<EOF
# igneum-build-1 (infra/build-server/provision.sh): the worker dashboard's two JSON files, nothing else
$WORKERS_HOST {
tls {
issuer acme
}
root * /srv/workers
header Access-Control-Allow-Origin https://dl.igneum.network
header Cache-Control "no-store"
@notjson not path /workers.json /headline.json
respond @notjson 404
file_server
}
EOF
if [ -f "$f" ] && cmp -s "$tmp" "$f"; then rm -f "$tmp"; systemctl is-active --quiet caddy || systemctl start caddy; ok caddy "$WORKERS_HOST"; return; fi
caddy validate --config "$tmp" --adapter caddyfile >/dev/null 2>&1 || { rm -f "$tmp"; die "caddy validate rejected the Caddyfile"; }
install -m 644 "$tmp" "$f"; rm -f "$tmp"
systemctl enable --quiet caddy 2>/dev/null || true
systemctl reload caddy 2>/dev/null || systemctl restart caddy
changed caddy "$WORKERS_HOST serving /srv/workers/{workers,headline}.json"
}
step_ufw() {
local p want=() any=0 status
status=$(ufw status verbose 2>/dev/null || true)
grep -q 'Default: deny (incoming), allow (outgoing)' <<<"$status" || { ufw --force default deny incoming >/dev/null; ufw --force default allow outgoing >/dev/null; any=1; }
want=(22)
want=(22 80 443)
for p in $P2P_PORTS; do want+=("$p"); done
for p in "${want[@]}"; do
grep -qE "^$p/tcp +ALLOW IN +Anywhere *$" <<<"$status" || { ufw allow "$p/tcp" >/dev/null; any=1; }
done
grep -q '^Status: active' <<<"$status" || { ufw --force enable >/dev/null; any=1; }
[ "$any" = 1 ] && changed ufw "22 and ${P2P_PORTS} open, everything else denied" || ok ufw "22 and ${P2P_PORTS}"
[ "$any" = 1 ] && changed ufw "22, 80, 443 and ${P2P_PORTS} open, everything else denied" || ok ufw "22, 80, 443 and ${P2P_PORTS}"
}
step_summary() {
@ -364,6 +398,7 @@ step_summary() {
printf 'mirrors: /srv/igneum.git (%s) /srv/igneum-node.git (%s)\n' "$(as_build 'git -C /srv/igneum.git branch --list | wc -l') branches" "$(as_build 'git -C /srv/igneum-node.git branch --list | wc -l') branches"
printf 'builds: %s worktree dirs under /srv/builds, %s slot(s)\n' "$(worktree_count)" "$(cat /srv/builds/_locks/slots)"
printf 'ufw: %s\n' "$(ufw status | grep -E 'ALLOW' | awk '{ print $1 }' | tr '\n' ' ')"
printf 'caddy: %s, %s\n' "$(caddy version 2>/dev/null | cut -d' ' -f1)" "$(systemctl is-active caddy 2>/dev/null) at https://$WORKERS_HOST/headline.json"
printf 'ssh line: ssh -i ~/.ssh/igneum_ed25519 build@%s\n' "$(hostname -I 2>/dev/null | awk '{ print $1 }')"
} | sed 's/^/ /'
}
@ -385,6 +420,7 @@ do_provision() {
step_profile
step_node
step_sshd
step_caddy
step_ufw
step_summary
log "done"

View file

@ -81,12 +81,19 @@ for k in $(seq 0 $((slots - 1))); do
done
if [ -z "$got" ]; then
echo "build-remote: all $slots slot(s) busy, waiting (up to 2 h) for build-0: $(head -c 160 "$IGNEUM_BUILD_SLOTS_DIR/build-0" 2>/dev/null)" >&2
# the queue is visible while it waits (the worker dashboard reads wait-* files; asked for on 6 October 2026): the same line
# format as a slot file, removed the moment the slot is taken or the wait is given up
waitfile="$IGNEUM_BUILD_SLOTS_DIR/wait-$BR_PID"
printf 'pid %s since %sZ waited 0 s: %s\n' "$BR_PID" "$(date -u +%H:%M:%S)" "$BR_LABEL" > "$waitfile"
trap 'rm -f "$waitfile"' EXIT
exec {fd}>"$IGNEUM_BUILD_SLOTS_DIR/build-0"
if ! flock -w 7200 "$fd"; then
echo "build-remote: gave up waiting for a slot after 2 h" >&2
jsonlog 75 0 $(( $(date +%s) - BR_T0 )) "" "$(date +%s)" "" "" "" "" "" ""
rm -f "$waitfile"
exit 75
fi
rm -f "$waitfile"; trap - EXIT
got=0
fi
waited=$(( $(date +%s) - BR_T0 ))