feat: simplify acquiring access on new-api

This commit is contained in:
Ray Andrew 2026-02-14 13:13:22 -06:00
parent 0d017e24bc
commit 8c872e3c35
Signed by: rayandrew
SSH key fingerprint: SHA256:EUCV+qCSqkap8rR+p+zGjxHfKI06G0GJKgo1DIOniQY
3 changed files with 62 additions and 32 deletions

View file

@ -5,8 +5,8 @@
# ============================================ # ============================================
# --- new-api (LLM proxy) --- # --- new-api (LLM proxy) ---
# Admin access token for new-api management API (also used by init-channels.sh) # Admin password (used by init-channels.sh to login and configure channels)
NEW_API_ACCESS_TOKEN=change-me-to-a-random-string NEW_API_PASSWORD=change-me-after-first-login
OPENROUTER_API_KEY=sk-or-... OPENROUTER_API_KEY=sk-or-...
SILICONFLOW_API_KEY=sk-... SILICONFLOW_API_KEY=sk-...
DEEPINFRA_API_KEY=... DEEPINFRA_API_KEY=...

View file

@ -93,7 +93,6 @@ services:
- TZ=UTC - TZ=UTC
- ENABLE_METRIC=true - ENABLE_METRIC=true
- LANG=en_US.UTF-8 - LANG=en_US.UTF-8
- INITIAL_ROOT_ACCESS_TOKEN=${NEW_API_ACCESS_TOKEN}
restart: unless-stopped restart: unless-stopped
healthcheck: healthcheck:
test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://localhost:3000/"] test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://localhost:3000/"]

View file

@ -3,13 +3,13 @@
# Run once after first boot: ./new-api/init-channels.sh # Run once after first boot: ./new-api/init-channels.sh
# #
# Requires these env vars (or .env file in project root): # Requires these env vars (or .env file in project root):
# NEW_API_ACCESS_TOKEN - admin access token (set via INITIAL_ROOT_ACCESS_TOKEN) # NEW_API_USERNAME - admin username (default: root)
# NEW_API_PASSWORD - admin password
# DEEPINFRA_API_KEY # DEEPINFRA_API_KEY
# SILICONFLOW_API_KEY # SILICONFLOW_API_KEY
# OPENROUTER_API_KEY # OPENROUTER_API_KEY
# GROQ_API_KEY # GROQ_API_KEY
# CEREBRAS_API_KEY # CEREBRAS_API_KEY
# OPENWEBUI_API_KEY - token for Open WebUI to authenticate with new-api
set -euo pipefail set -euo pipefail
@ -25,7 +25,30 @@ if [[ -f "$ENV_FILE" ]]; then
fi fi
API_BASE="${NEW_API_BASE:-http://localhost:4000}" API_BASE="${NEW_API_BASE:-http://localhost:4000}"
TOKEN="${NEW_API_ACCESS_TOKEN:?Set NEW_API_ACCESS_TOKEN (from INITIAL_ROOT_ACCESS_TOKEN)}" USERNAME="${NEW_API_USERNAME:-root}"
PASSWORD="${NEW_API_PASSWORD:?Set NEW_API_PASSWORD to the admin password}"
# ── Login to get session token ──────────────────────────
login() {
echo "Logging in as ${USERNAME}..."
local resp
resp=$(curl -s "${API_BASE}/api/user/login" \
-H "Content-Type: application/json" \
-d "$(python3 -c "
import json, sys
print(json.dumps({'username': sys.argv[1], 'password': sys.argv[2]}))
" "$USERNAME" "$PASSWORD")")
local success token
success=$(echo "$resp" | python3 -c "import sys,json; print(json.load(sys.stdin).get('success', False))")
if [[ "$success" != "True" ]]; then
echo "ERROR: Login failed: ${resp}"
exit 1
fi
TOKEN=$(echo "$resp" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['access_token'])")
echo " Logged in."
}
# ── Helper ────────────────────────────────────────────── # ── Helper ──────────────────────────────────────────────
create_channel() { create_channel() {
@ -51,21 +74,17 @@ print(json.dumps({
})) }))
" "$type" "$name" "$key" "$base_url" "$models" "$model_mapping" "$priority") " "$type" "$name" "$key" "$base_url" "$models" "$model_mapping" "$priority")
local resp http_code body local resp success
resp=$(curl -s -w "\n%{http_code}" \ resp=$(curl -s "${API_BASE}/api/channel/" \
"${API_BASE}/api/channel/" \
-H "Authorization: Bearer ${TOKEN}" \ -H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d "$payload") -d "$payload")
http_code=$(echo "$resp" | tail -1) success=$(echo "$resp" | python3 -c "import sys,json; print(json.load(sys.stdin).get('success', False))")
body=$(echo "$resp" | sed '$d') if [[ "$success" == "True" ]]; then
if [[ "$http_code" == "200" ]]; then
echo " OK" echo " OK"
else else
echo " FAILED (HTTP ${http_code})" echo " FAILED: ${resp}" | head -c 500
echo " ${body}" | head -c 500
echo echo
fi fi
} }
@ -73,7 +92,7 @@ print(json.dumps({
# Wait for new-api to be ready # Wait for new-api to be ready
echo "Waiting for new-api at ${API_BASE}..." echo "Waiting for new-api at ${API_BASE}..."
for i in $(seq 1 30); do for i in $(seq 1 30); do
if curl -sf "${API_BASE}/api/status" > /dev/null 2>&1; then if curl -sf "${API_BASE}/" > /dev/null 2>&1; then
echo "new-api is ready." echo "new-api is ready."
break break
fi fi
@ -84,6 +103,9 @@ for i in $(seq 1 30); do
sleep 2 sleep 2
done done
# Login first
login
# ── Channel: DeepInfra (priority 1) ──────────────────── # ── Channel: DeepInfra (priority 1) ────────────────────
create_channel "DeepInfra" 1 \ create_channel "DeepInfra" 1 \
"${DEEPINFRA_API_KEY:?}" \ "${DEEPINFRA_API_KEY:?}" \
@ -125,13 +147,12 @@ create_channel "Cerebras" 1 \
'{"llama-3.3-70b-cerebras":"llama-3.3-70b"}' '{"llama-3.3-70b-cerebras":"llama-3.3-70b"}'
# ── Create API token for Open WebUI ──────────────────── # ── Create API token for Open WebUI ────────────────────
if [[ -n "${OPENWEBUI_API_KEY:-}" ]]; then echo ""
echo "" echo "Creating API token for Open WebUI..."
echo "Creating API token for Open WebUI..." TOKEN_RESP=$(curl -s "${API_BASE}/api/token/" \
TOKEN_RESP=$(curl -s "${API_BASE}/api/token/" \ -H "Authorization: Bearer ${TOKEN}" \
-H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \
-H "Content-Type: application/json" \ -d "$(python3 -c "
-d "$(python3 -c "
import json import json
print(json.dumps({ print(json.dumps({
'name': 'open-webui', 'name': 'open-webui',
@ -139,23 +160,33 @@ print(json.dumps({
'unlimited_quota': True 'unlimited_quota': True
})) }))
")") ")")
echo "Token response: ${TOKEN_RESP}" | head -c 500
echo "" TOKEN_KEY=$(echo "$TOKEN_RESP" | python3 -c "
echo "" import sys, json
echo "NOTE: Use the token 'key' from the response above as OPENAI_API_KEY in Open WebUI." data = json.load(sys.stdin)
echo " Or create a token manually in the new-api UI." if data.get('success'):
fi print(data['data']['key'])
else:
print('FAILED: ' + data.get('message', 'unknown error'))
" 2>/dev/null || echo "FAILED: could not parse response")
echo " Token: ${TOKEN_KEY}"
echo "" echo ""
echo "══════════════════════════════════════" echo "══════════════════════════════════════"
echo "Channel setup complete!" echo "Channel setup complete!"
echo "" echo ""
if [[ "$TOKEN_KEY" != FAILED* ]]; then
echo "Open WebUI API key: ${TOKEN_KEY}"
echo "Set OPENWEBUI_API_KEY=${TOKEN_KEY} in your .env"
fi
echo ""
echo "Next steps:" echo "Next steps:"
echo " 1. Verify channels at ${API_BASE} (login: root / 123456 — CHANGE THIS)" echo " 1. Verify channels at ${API_BASE}"
echo " 2. Test a model:" echo " 2. Test a model:"
echo " curl ${API_BASE}/v1/chat/completions \\" echo " curl ${API_BASE}/v1/chat/completions \\"
echo " -H 'Authorization: Bearer <token>' \\" echo " -H 'Authorization: Bearer ${TOKEN_KEY}' \\"
echo " -H 'Content-Type: application/json' \\" echo " -H 'Content-Type: application/json' \\"
echo " -d '{\"model\":\"deepseek-v3.2\",\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}]}'" echo " -d '{\"model\":\"deepseek-v3.2\",\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}]}'"
echo " 3. Check Open WebUI can see models" echo " 3. Restart Open WebUI with the new API key"
echo "══════════════════════════════════════" echo "══════════════════════════════════════"