Initial commit: ein-ai-proxy
Anthropic-compatible API proxy that routes requests to multiple providers (Anthropic, Z.ai/GLM-4.7, DeepSeek V3.2) based on model name. Zero dependencies, SSE streaming, bearer token auth. Designed to run behind Caddy/nginx on a home server, enabling Claude Code and Roo Code clients to connect from anywhere.
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
#!/bin/bash
|
||||
# =============================================================
|
||||
# Ein AI Proxy - Deployment Script
|
||||
# Run on: mini-server (ssh.maybe.zone) as user harrison
|
||||
# =============================================================
|
||||
set -e
|
||||
|
||||
PROXY_DIR="$HOME/ai-proxy"
|
||||
SERVICE_NAME="ein-ai-proxy"
|
||||
|
||||
echo "============================================"
|
||||
echo " Ein AI Proxy - Deployment"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
|
||||
# --- Step 1: Check config exists ---
|
||||
if [ ! -f "$PROXY_DIR/config.json" ]; then
|
||||
echo "[!] config.json not found."
|
||||
echo " Copy the example and fill in your keys:"
|
||||
echo ""
|
||||
echo " cp $PROXY_DIR/config.example.json $PROXY_DIR/config.json"
|
||||
echo " nano $PROXY_DIR/config.json"
|
||||
echo ""
|
||||
echo " Then re-run this script."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[1/5] Config found."
|
||||
|
||||
# --- Step 2: Generate auth token if still default ---
|
||||
AUTH_TOKEN=$(node -e "console.log(JSON.parse(require('fs').readFileSync('$PROXY_DIR/config.json','utf-8')).authToken)")
|
||||
if [ "$AUTH_TOKEN" = "CHANGE_ME_TO_A_LONG_RANDOM_STRING" ]; then
|
||||
echo "[!] You haven't set a real authToken in config.json."
|
||||
NEW_TOKEN=$(openssl rand -hex 32)
|
||||
echo " Here's a generated one you can use:"
|
||||
echo ""
|
||||
echo " $NEW_TOKEN"
|
||||
echo ""
|
||||
echo " Edit config.json and replace the authToken value, then re-run."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[2/5] Auth token is set."
|
||||
|
||||
# --- Step 3: Test the proxy locally ---
|
||||
echo "[3/5] Testing proxy startup..."
|
||||
source "$HOME/.nvm/nvm.sh"
|
||||
timeout 5 node "$PROXY_DIR/proxy.mjs" &
|
||||
PROXY_PID=$!
|
||||
sleep 2
|
||||
|
||||
HEALTH=$(curl -s http://127.0.0.1:3100/health 2>/dev/null || echo "FAIL")
|
||||
kill $PROXY_PID 2>/dev/null || true
|
||||
wait $PROXY_PID 2>/dev/null || true
|
||||
|
||||
if echo "$HEALTH" | grep -q '"status":"ok"'; then
|
||||
echo " Proxy starts and responds. Routes:"
|
||||
echo "$HEALTH" | node -e "
|
||||
const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf-8'));
|
||||
Object.entries(d.routes).forEach(([m,r])=>console.log(' '+m+' -> '+r));
|
||||
" 2>/dev/null || echo " (could not parse routes)"
|
||||
else
|
||||
echo " [!] Proxy failed to start. Check config.json."
|
||||
echo " Response: $HEALTH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Step 4: Install systemd service ---
|
||||
echo "[4/5] Installing systemd service..."
|
||||
sudo cp "$PROXY_DIR/$SERVICE_NAME.service" "/etc/systemd/system/$SERVICE_NAME.service"
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable "$SERVICE_NAME"
|
||||
sudo systemctl restart "$SERVICE_NAME"
|
||||
sleep 2
|
||||
|
||||
if sudo systemctl is-active --quiet "$SERVICE_NAME"; then
|
||||
echo " Service is running."
|
||||
else
|
||||
echo " [!] Service failed to start. Check logs:"
|
||||
echo " sudo journalctl -u $SERVICE_NAME -n 20"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Step 5: Nginx setup reminder ---
|
||||
echo "[5/5] Nginx setup:"
|
||||
echo ""
|
||||
echo " 1. Create DNS A record: ai.maybe.zone -> $(curl -s ifconfig.me 2>/dev/null || echo 'YOUR_IP')"
|
||||
echo ""
|
||||
echo " 2. Install the nginx config:"
|
||||
echo " sudo cp $PROXY_DIR/nginx-ai-proxy.conf /etc/nginx/sites-available/ai-proxy"
|
||||
echo " sudo ln -sf /etc/nginx/sites-available/ai-proxy /etc/nginx/sites-enabled/"
|
||||
echo " sudo nginx -t && sudo systemctl reload nginx"
|
||||
echo ""
|
||||
echo " 3. Get SSL cert:"
|
||||
echo " sudo certbot --nginx -d ai.maybe.zone"
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo " Deployment complete!"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
echo " Proxy running at: http://127.0.0.1:3100"
|
||||
echo " After nginx+SSL: https://ai.maybe.zone"
|
||||
echo ""
|
||||
echo " --- Client Setup ---"
|
||||
echo ""
|
||||
echo " Claude Code CLI (~/.claude/settings.json):"
|
||||
echo ' {'
|
||||
echo ' "env": {'
|
||||
echo " \"ANTHROPIC_BASE_URL\": \"https://ai.maybe.zone\","
|
||||
echo " \"ANTHROPIC_AUTH_TOKEN\": \"$AUTH_TOKEN\","
|
||||
echo ' "API_TIMEOUT_MS": "3000000"'
|
||||
echo ' }'
|
||||
echo ' }'
|
||||
echo ""
|
||||
echo " Roo Code (VS Code):"
|
||||
echo " Provider: Anthropic"
|
||||
echo " API Key: $AUTH_TOKEN"
|
||||
echo " Custom Base URL: https://ai.maybe.zone"
|
||||
echo ""
|
||||
echo " Model routing:"
|
||||
echo " Sonnet requests -> GLM-4.7 (Z.ai)"
|
||||
echo " Opus requests -> Claude Opus (Anthropic API)"
|
||||
echo " Haiku requests -> DeepSeek V3.2"
|
||||
echo ""
|
||||
Reference in New Issue
Block a user