Spaces:
Running
Running
github-actions[bot] commited on
Commit ·
b17013f
1
Parent(s): 7b6257f
deploy: c7a6362 — 更新 entrypoint.sh
Browse files- huggingface/entrypoint.sh +67 -67
huggingface/entrypoint.sh
CHANGED
|
@@ -1,47 +1,44 @@
|
|
| 1 |
#!/usr/bin/env bash
|
| 2 |
-
#
|
| 3 |
-
#
|
| 4 |
-
#
|
| 5 |
-
# Responsibilities:
|
| 6 |
-
# 1. Apply sensible defaults for any env vars not set via HF Space secrets
|
| 7 |
-
# 2. Ensure required directories exist and are writable (ephemeral /tmp)
|
| 8 |
-
# 3. Sanity-check required files baked into the image
|
| 9 |
-
# 4. Hand off to supervisord (which manages litellm, backend, nginx)
|
| 10 |
-
#
|
| 11 |
-
# Environment variables (set in HF Space → Settings → Repository secrets):
|
| 12 |
-
#
|
| 13 |
-
# LITELLM_MASTER_KEY Required. Admin key for LiteLLM proxy.
|
| 14 |
-
# JWT_SECRET Required. Secret for backend session tokens.
|
| 15 |
-
# GATEWAY_PUBLIC_URL Required. Public URL of this Space, e.g.
|
| 16 |
-
# https://<user>-<space>.hf.space
|
| 17 |
-
# (auto-set by the GitHub Actions workflow)
|
| 18 |
-
# DB_PATH Optional. SQLite path. Default: /app/data/gateway.db
|
| 19 |
-
# LOG_LEVEL Optional. Winston log level. Default: http
|
| 20 |
-
#
|
| 21 |
-
# Provider API keys (optional, set whichever you use):
|
| 22 |
-
# OPENAI_API_KEY, ANTHROPIC_API_KEY, GROQ_API_KEY, GEMINI_API_KEY, …
|
| 23 |
-
# ─────────────────────────────────────────────────────────────────────────────
|
| 24 |
set -euo pipefail
|
| 25 |
|
| 26 |
-
echo "
|
| 27 |
-
echo "
|
| 28 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
|
| 30 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
|
| 32 |
-
#
|
| 33 |
if [ -z "${LITELLM_MASTER_KEY:-}" ]; then
|
| 34 |
export LITELLM_MASTER_KEY="sk-gateway-hf-insecure-change-me"
|
| 35 |
-
echo "
|
| 36 |
-
echo " Set it in: HF Space → Settings → Repository secrets"
|
| 37 |
fi
|
| 38 |
|
| 39 |
if [ -z "${JWT_SECRET:-}" ]; then
|
| 40 |
-
# Generate a random secret at runtime; sessions won't survive restarts
|
| 41 |
-
# but this is acceptable for a demo Space.
|
| 42 |
export JWT_SECRET
|
| 43 |
JWT_SECRET=$(python3 -c "import secrets; print(secrets.token_hex(32))")
|
| 44 |
-
echo "
|
| 45 |
fi
|
| 46 |
|
| 47 |
export GATEWAY_PUBLIC_URL="${GATEWAY_PUBLIC_URL:-http://localhost:7860}"
|
|
@@ -50,51 +47,54 @@ export LOG_LEVEL="${LOG_LEVEL:-http}"
|
|
| 50 |
export NODE_ENV="${NODE_ENV:-production}"
|
| 51 |
|
| 52 |
echo "GATEWAY_PUBLIC_URL : ${GATEWAY_PUBLIC_URL}"
|
| 53 |
-
echo "
|
| 54 |
-
echo "
|
| 55 |
-
|
| 56 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
|
| 58 |
-
#
|
| 59 |
mkdir -p "$(dirname "${DB_PATH}")"
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
mkdir -p \
|
| 63 |
-
/tmp/nginx/client_body \
|
| 64 |
-
/tmp/nginx/proxy \
|
| 65 |
-
/tmp/nginx/fastcgi \
|
| 66 |
-
/tmp/nginx/uwsgi \
|
| 67 |
-
/tmp/nginx/scgi
|
| 68 |
-
|
| 69 |
-
# supervisor socket + pid files live in /tmp (non-root writable)
|
| 70 |
mkdir -p /tmp/supervisor
|
|
|
|
| 71 |
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
if [ ! -f "/app/litellm/config.yaml" ]; then
|
| 77 |
-
echo "❌ /app/litellm/config.yaml not found — aborting."
|
| 78 |
exit 1
|
| 79 |
fi
|
| 80 |
-
echo "✅ LiteLLM config found"
|
| 81 |
-
|
| 82 |
if [ ! -f "/app/frontend/dist/index.html" ]; then
|
| 83 |
-
echo "
|
| 84 |
-
echo " This should have been built in the Docker image Stage 1."
|
| 85 |
exit 1
|
| 86 |
fi
|
| 87 |
-
echo "
|
| 88 |
|
| 89 |
-
# ── 4. Print startup summary ──────────────────────────────────────────────────
|
| 90 |
-
echo ""
|
| 91 |
echo "Starting services:"
|
| 92 |
-
echo "
|
| 93 |
-
echo "
|
| 94 |
-
echo "
|
| 95 |
-
echo ""
|
| 96 |
-
echo "Access your gateway at: ${GATEWAY_PUBLIC_URL}"
|
| 97 |
-
echo "──────────────────────────────────────────"
|
| 98 |
|
| 99 |
-
# ── 5. Exec supervisord (replaces this script as PID 1) ──────────────────────
|
| 100 |
exec /usr/bin/supervisord -c /app/huggingface/supervisord.conf
|
|
|
|
| 1 |
#!/usr/bin/env bash
|
| 2 |
+
# entrypoint.sh - HF Spaces container startup
|
| 3 |
+
# LiteLLM v1.81+ requires PostgreSQL for /model/new API.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
set -euo pipefail
|
| 5 |
|
| 6 |
+
echo "AI Gateway Hub - starting (HF Spaces)"
|
| 7 |
+
echo "======================================"
|
| 8 |
+
|
| 9 |
+
# 1. DATABASE_URL - required for LiteLLM v1.81+ model registration
|
| 10 |
+
if [ -z "${DATABASE_URL:-}" ]; then
|
| 11 |
+
echo "WARNING: DATABASE_URL is not set."
|
| 12 |
+
echo "LiteLLM v1.81+ requires PostgreSQL for /model/new API."
|
| 13 |
+
echo "Without it all model registrations return HTTP 500."
|
| 14 |
+
echo ""
|
| 15 |
+
echo "Get a free PostgreSQL URL from:"
|
| 16 |
+
echo " Neon: https://neon.tech"
|
| 17 |
+
echo " Supabase: https://supabase.com"
|
| 18 |
+
echo " Railway: https://railway.app"
|
| 19 |
+
echo ""
|
| 20 |
+
echo "Add to HF Space Settings -> Repository secrets:"
|
| 21 |
+
echo " DATABASE_URL = postgresql://user:pass@host:5432/dbname"
|
| 22 |
+
fi
|
| 23 |
+
export DATABASE_URL="${DATABASE_URL:-}"
|
| 24 |
|
| 25 |
+
# 2. LITELLM_SALT_KEY - encrypts API keys stored in DB
|
| 26 |
+
if [ -z "${LITELLM_SALT_KEY:-}" ]; then
|
| 27 |
+
echo "WARNING: LITELLM_SALT_KEY not set - stored API keys will not be encrypted."
|
| 28 |
+
echo "IMPORTANT: Never change this after adding models."
|
| 29 |
+
fi
|
| 30 |
+
export LITELLM_SALT_KEY="${LITELLM_SALT_KEY:-}"
|
| 31 |
|
| 32 |
+
# 3. Other secrets
|
| 33 |
if [ -z "${LITELLM_MASTER_KEY:-}" ]; then
|
| 34 |
export LITELLM_MASTER_KEY="sk-gateway-hf-insecure-change-me"
|
| 35 |
+
echo "WARNING: LITELLM_MASTER_KEY not set. Using insecure default."
|
|
|
|
| 36 |
fi
|
| 37 |
|
| 38 |
if [ -z "${JWT_SECRET:-}" ]; then
|
|
|
|
|
|
|
| 39 |
export JWT_SECRET
|
| 40 |
JWT_SECRET=$(python3 -c "import secrets; print(secrets.token_hex(32))")
|
| 41 |
+
echo "INFO: JWT_SECRET not set - generated ephemeral secret."
|
| 42 |
fi
|
| 43 |
|
| 44 |
export GATEWAY_PUBLIC_URL="${GATEWAY_PUBLIC_URL:-http://localhost:7860}"
|
|
|
|
| 47 |
export NODE_ENV="${NODE_ENV:-production}"
|
| 48 |
|
| 49 |
echo "GATEWAY_PUBLIC_URL : ${GATEWAY_PUBLIC_URL}"
|
| 50 |
+
echo "DATABASE_URL set : $([ -n "${DATABASE_URL}" ] && echo YES || echo NO)"
|
| 51 |
+
echo "SALT_KEY set : $([ -n "${LITELLM_SALT_KEY}" ] && echo YES || echo NO)"
|
| 52 |
+
|
| 53 |
+
# 4. Inject database_url into config.yaml at runtime if DATABASE_URL is set
|
| 54 |
+
# entrypoint runs as user:user who owns /app/litellm/config.yaml (set in Dockerfile)
|
| 55 |
+
CONFIG="/app/litellm/config.yaml"
|
| 56 |
+
if [ -n "${DATABASE_URL}" ]; then
|
| 57 |
+
if ! grep -q "database_url" "${CONFIG}"; then
|
| 58 |
+
python3 << PYEOF
|
| 59 |
+
import re
|
| 60 |
+
with open("${CONFIG}", "r") as f:
|
| 61 |
+
content = f.read()
|
| 62 |
+
content = re.sub(
|
| 63 |
+
r"(master_key:\s*os\.environ/LITELLM_MASTER_KEY)",
|
| 64 |
+
r"\1\n database_url: os.environ/DATABASE_URL",
|
| 65 |
+
content
|
| 66 |
+
)
|
| 67 |
+
with open("${CONFIG}", "w") as f:
|
| 68 |
+
f.write(content)
|
| 69 |
+
print("INFO: database_url injected into config.yaml")
|
| 70 |
+
PYEOF
|
| 71 |
+
else
|
| 72 |
+
echo "INFO: database_url already present in config.yaml"
|
| 73 |
+
fi
|
| 74 |
+
fi
|
| 75 |
|
| 76 |
+
# 5. Directories
|
| 77 |
mkdir -p "$(dirname "${DB_PATH}")"
|
| 78 |
+
mkdir -p /tmp/nginx/client_body /tmp/nginx/proxy \
|
| 79 |
+
/tmp/nginx/fastcgi /tmp/nginx/uwsgi /tmp/nginx/scgi
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
mkdir -p /tmp/supervisor
|
| 81 |
+
echo "Directories ready"
|
| 82 |
|
| 83 |
+
# 6. Sanity checks
|
| 84 |
+
if [ ! -f "${CONFIG}" ]; then
|
| 85 |
+
echo "ERROR: ${CONFIG} not found - aborting."
|
|
|
|
|
|
|
|
|
|
| 86 |
exit 1
|
| 87 |
fi
|
|
|
|
|
|
|
| 88 |
if [ ! -f "/app/frontend/dist/index.html" ]; then
|
| 89 |
+
echo "ERROR: frontend build missing - aborting."
|
|
|
|
| 90 |
exit 1
|
| 91 |
fi
|
| 92 |
+
echo "Config and frontend OK"
|
| 93 |
|
|
|
|
|
|
|
| 94 |
echo "Starting services:"
|
| 95 |
+
echo " LiteLLM -> localhost:4000 (priority 10)"
|
| 96 |
+
echo " Backend -> localhost:3001 (priority 20)"
|
| 97 |
+
echo " nginx -> 0.0.0.0:7860 (priority 30)"
|
| 98 |
+
echo "Gateway URL: ${GATEWAY_PUBLIC_URL}"
|
|
|
|
|
|
|
| 99 |
|
|
|
|
| 100 |
exec /usr/bin/supervisord -c /app/huggingface/supervisord.conf
|