Closes the live production exposure this plan targets: /aiui/api/claude/
and /aiui/api/ollama/ proxied straight through with "no session gate
needed", and /aiui/api/openrouter/ was a plain unauthenticated relay to a
paid third-party API the node holds no key for (T-13-08/T-13-09/T-13-10).
image-recipe/configs/nginx-archipelago.conf (BOTH server blocks, ~line 49
and ~line 961 — a fix applied to only one leaves the exposure live on
whichever block serves the request, T-13-15):
- /aiui/api/claude/ and /aiui/api/ollama/ proxy_pass re-pointed from
127.0.0.1:3142 / 127.0.0.1:11434 to the Rust daemon at 127.0.0.1:5678
(no trailing path component, so the daemon's own prefix match sees the
full request URI)
- Forward the session Cookie header to the daemon so it can re-derive auth
- location /aiui/api/openrouter/ deleted outright in both blocks
- Old comment "API key managed by proxy, no session gate needed" (the
reasoning error that produced the exposure) replaced with rationale
scripts/deploy-to-target.sh: deleted the embedded claude-api-proxy.py
heredoc, its systemd unit creation/enable/restart, the ANTHROPIC_API_KEY
extraction, and the 3141->3142 sed fixups. Added an unconditional step that
stops/disables/removes any pre-existing claude-api-proxy unit and deletes
/opt/archipelago/claude-api-proxy.py and
<data_dir>/secrets/claude-api-proxy.env on every deploy — so
already-provisioned nodes actually lose the old unauthenticated listener,
not just newly-deployed ones.
scripts/setup-aiui-server.sh: dropped the hard ANTHROPIC_API_KEY
requirement and the patch-nginx-claude.py step; the script's remaining job
is the AIUI dist rsync. (Also drops the FileBrowser-fix step that lived
here — that logic already exists, and is kept, in deploy-to-target.sh; this
script narrows to exactly what its rewritten header now says it does.)
core/archipelago/src/api/rpc/system/handlers.rs: `claude_api_key` setting
branch no longer writes a second key copy to secrets/claude-api-proxy.env
or restarts claude-api-proxy. secrets/claude-api-key (0600) remains the
single ledger, with a comment naming it as such.
`cargo build --package archipelago` succeeds. Verified via grep against
every acceptance criterion in 13-02-PLAN.md's Task 2 (openrouter count 0,
3142 gone from nginx, both location blocks present, PORT=3142 gone,
claude-api-proxy gone from handlers.rs, secrets/claude-api-key present).
Task 3 (real-node curl/systemd verification, S-15) is NOT done in this
commit — see 13-02-SUMMARY.md.
Continues WIP checkpoint 13b576da (reset --soft, recommitted atomically
per task per plan protocol).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
88 lines
3.7 KiB
Bash
Executable File
88 lines
3.7 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Deploy the AIUI (Chat mode iframe) build to an Archipelago server.
|
|
#
|
|
# Usage:
|
|
# ./scripts/setup-aiui-server.sh <host>
|
|
# ./scripts/setup-aiui-server.sh archipelago@192.168.1.198
|
|
# ./scripts/setup-aiui-server.sh archipelago@192.168.1.228
|
|
#
|
|
# What it does:
|
|
# Rsyncs (or tar+scp, if rsync is unavailable on the target) a locally
|
|
# built AIUI dist/ into /opt/archipelago/web-ui/aiui/ on the target node.
|
|
#
|
|
# What it no longer does (13-02-PLAN.md — closing a live production
|
|
# exposure): it used to also patch nginx to route /aiui/api/claude/ to a
|
|
# standalone Python proxy holding its own ANTHROPIC_API_KEY, with no session
|
|
# gate — anyone who could reach the node's web port could spend the owner's
|
|
# API budget. That proxy, its systemd unit, and this script's nginx-patch
|
|
# step are all deleted (see scripts/deploy-to-target.sh's "Removing legacy
|
|
# Claude API proxy sidecar" step). AIUI's Claude/Ollama calls now route
|
|
# through the Rust daemon (127.0.0.1:5678), which enforces the session
|
|
# cookie itself and reads the node's single key ledger. Set the key via
|
|
# `system.settings.set claude_api_key` (Settings > AIUI in neode-ui) — this
|
|
# script has nothing to do with the key anymore.
|
|
#
|
|
# Prerequisites:
|
|
# - AIUI must be built locally first: cd AIUI/packages/app && VITE_BASE_PATH=/aiui/ npx vite build
|
|
# - SSH key access to target server
|
|
|
|
set -e
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
|
SSH_KEY="${ARCHIPELAGO_SSH_KEY:-$HOME/.ssh/archipelago-deploy}"
|
|
SSH_OPTS="-o StrictHostKeyChecking=no -i $SSH_KEY"
|
|
|
|
TARGET_HOST="$1"
|
|
if [ -z "$TARGET_HOST" ]; then
|
|
echo "Usage: $0 <user@host>"
|
|
echo " e.g. $0 archipelago@192.168.1.198"
|
|
exit 1
|
|
fi
|
|
|
|
AIUI_DIST="$PROJECT_DIR/../AIUI/packages/app/dist"
|
|
if [ ! -f "$AIUI_DIST/index.html" ]; then
|
|
echo "ERROR: AIUI build not found at $AIUI_DIST"
|
|
echo "Build it first: cd ../AIUI/packages/app && VITE_BASE_PATH=/aiui/ npx vite build"
|
|
exit 1
|
|
fi
|
|
|
|
timestamp() { echo "[$(date +%H:%M:%S)]"; }
|
|
|
|
echo "╔════════════════════════════════════════════════════════════╗"
|
|
echo "║ Archipelago AIUI deploy ║"
|
|
echo "║ Target: $TARGET_HOST"
|
|
echo "╚════════════════════════════════════════════════════════════╝"
|
|
|
|
# --- Deploy AIUI files ---
|
|
echo ""
|
|
echo "$(timestamp) 📦 Deploying AIUI files..."
|
|
|
|
if ssh $SSH_OPTS "$TARGET_HOST" "which rsync" &>/dev/null; then
|
|
rsync -avz --delete -e "ssh $SSH_OPTS" "$AIUI_DIST/" "$TARGET_HOST:/opt/archipelago/web-ui/aiui/" 2>&1 | tail -3
|
|
else
|
|
echo " rsync not available, using tar+scp..."
|
|
TMPTAR=$(mktemp /tmp/aiui-dist-XXXXX.tar.gz)
|
|
(cd "$AIUI_DIST" && tar czf "$TMPTAR" .)
|
|
scp $SSH_OPTS "$TMPTAR" "$TARGET_HOST:/tmp/aiui-dist.tar.gz"
|
|
ssh $SSH_OPTS "$TARGET_HOST" "sudo mkdir -p /opt/archipelago/web-ui/aiui && cd /opt/archipelago/web-ui/aiui && sudo tar xzf /tmp/aiui-dist.tar.gz --overwrite"
|
|
rm -f "$TMPTAR"
|
|
fi
|
|
echo " AIUI deployed."
|
|
|
|
# --- Verify ---
|
|
echo ""
|
|
echo "$(timestamp) ✅ Verification..."
|
|
ssh $SSH_OPTS "$TARGET_HOST" "
|
|
echo \" AIUI index: \$(ls -la /opt/archipelago/web-ui/aiui/index.html 2>/dev/null | awk '{print \$6,\$7,\$8}')\"
|
|
echo \" Nginx: \$(systemctl is-active nginx)\"
|
|
echo \" Backend: \$(systemctl is-active archipelago)\"
|
|
"
|
|
|
|
echo ""
|
|
echo "$(timestamp) Done! AIUI deployed."
|
|
echo " Set the Claude API key (if not already set) via Settings > AIUI in"
|
|
echo " neode-ui — it now lives only at <data_dir>/secrets/claude-api-key."
|
|
echo " Access: http://$(echo $TARGET_HOST | cut -d@ -f2)"
|