#!/bin/bash # # Deploy the AIUI (Chat mode iframe) build to an Archipelago server. # # Usage: # ./scripts/setup-aiui-server.sh # ./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 " 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 /secrets/claude-api-key." echo " Access: http://$(echo $TARGET_HOST | cut -d@ -f2)"