The vector_store_registry block in litellm-config.yaml only seeds the store into litellm's in-memory registry at boot — the Admin UI's Vector Stores page (/ui/vector-stores) reads litellm's own DB (LiteLLM_ManagedVectorStoresTable) instead, via /vector_store/list. A config-only entry there gets silently deleted from memory the first time anyone loads that page, since /vector_store/list treats the DB as the source of truth and removes anything not also present there. update.sh now registers it in the DB too, via POST /vector_store/new (idempotent, same pattern as the existing virtual-key minting) — with the literal resolved key, not the os.environ/... form used in litellm-config.yaml, since the management API doesn't do config.yaml-style substitution on request bodies. Found in the process: /vector_store/update in this litellm version can't touch litellm_params at all (VectorStoreUpdateRequest has no such field, so PGVECTOR_API_KEY sent through it is silently dropped) — worth knowing if this key ever needs rotating; documented in update.sh's comment. Verified live: registered via the API, confirmed the row appears in /vector_store/list (what the Admin UI page reads) with the real key, and re-verified search still works end-to-end afterward.
151 lines
6.5 KiB
Bash
Executable File
151 lines
6.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# The one command to run after any change to this repo (compose file,
|
|
# litellm-config.yaml, .env, or a git pull) to bring the running stack in
|
|
# sync. Ensures secrets/keys exist, pulls, validates, rebuilds/re-pulls
|
|
# images, and recreates only what changed — safe to run any time, including
|
|
# with nothing to do.
|
|
#
|
|
# ponytail: no rollback/backup logic — this is a single-user homelab box,
|
|
# not a fleet. If a bad config lands, `git revert` + re-run is the recovery
|
|
# path, not this script.
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")/.."
|
|
|
|
[ -f .env ] || cp .env.example .env
|
|
|
|
# Handles all three cases: the KEY=value line is missing entirely (.env
|
|
# predates that var being added to .env.example — sed can't fix what isn't
|
|
# there, so this appends it), present but blank, or already set.
|
|
set_if_blank() {
|
|
local key="$1" value="$2"
|
|
if grep -qE "^${key}=.*[^[:space:]]" .env; then
|
|
echo "${key}: already set, skipping."
|
|
elif grep -qE "^${key}=" .env; then
|
|
sed -i "s|^${key}=.*|${key}=${value}|" .env
|
|
echo "${key}: set."
|
|
else
|
|
echo "${key}=${value}" >> .env
|
|
echo "${key}: added (was missing from .env)."
|
|
fi
|
|
}
|
|
|
|
echo "==> filling in missing secrets"
|
|
# Random values — safe to re-run, never overwrites what's already set.
|
|
# LITELLM_SALT_KEY especially: never change it after first run, existing
|
|
# encrypted data becomes unreadable if you do.
|
|
set_if_blank LITELLM_MASTER_KEY "$(openssl rand -hex 32)"
|
|
set_if_blank LITELLM_SALT_KEY "$(openssl rand -hex 32)"
|
|
set_if_blank LITELLM_DB_PASSWORD "$(openssl rand -hex 32)"
|
|
set_if_blank REDIS_PASSWORD "$(openssl rand -hex 32)"
|
|
set_if_blank UI_PASSWORD "$(openssl rand -hex 16)"
|
|
set_if_blank PGVECTOR_DB_PASSWORD "$(openssl rand -hex 32)"
|
|
set_if_blank LITELLM_PGVECTOR_API_KEY "$(openssl rand -hex 32)"
|
|
|
|
echo "==> resolving SEARXNG_LAN_IP"
|
|
# search.home is a LAN mDNS/local-DNS name — resolvable from this host, just
|
|
# not from inside the litellm container (see docs/research/litellm-searxng-search.md).
|
|
searxng_ip="$(getent hosts search.home 2>/dev/null | awk '{print $1}' | head -1)"
|
|
if [ -n "$searxng_ip" ]; then
|
|
set_if_blank SEARXNG_LAN_IP "$searxng_ip"
|
|
else
|
|
echo "SEARXNG_LAN_IP: couldn't resolve search.home from this host, set it manually if still blank."
|
|
fi
|
|
|
|
echo "==> git pull"
|
|
git pull --ff-only
|
|
|
|
echo "==> validating compose config"
|
|
docker compose config -q
|
|
|
|
echo "==> pulling images"
|
|
docker compose pull --ignore-buildable
|
|
|
|
echo "==> rebuilding local-build services"
|
|
docker compose build --pull
|
|
|
|
echo "==> ensuring models are downloaded (skips already-present files)"
|
|
docker compose --profile tools run --rm downloader
|
|
docker compose --profile tools run --rm downloader-embedding
|
|
|
|
echo "==> bringing up litellm (needed to mint virtual keys below)"
|
|
docker compose up -d --wait litellm-db litellm
|
|
|
|
# OPENWEBUI_LITELLM_KEY / LITELLM_PGVECTOR_EMBEDDING_KEY are per-workload
|
|
# virtual keys, not random secrets — minted via LiteLLM's own API
|
|
# (docs/proxy-key-onboarding.md documents the manual Admin UI route; this is
|
|
# the same thing over the REST endpoint LITELLM_MASTER_KEY already
|
|
# authenticates against).
|
|
set -a && . ./.env && set +a
|
|
mint_key_if_blank() {
|
|
local key="$1" alias="$2"
|
|
if grep -qE "^${key}=.*[^[:space:]]" .env; then
|
|
echo "${key}: already set, skipping."
|
|
return
|
|
fi
|
|
local minted
|
|
minted=$(curl -sf -X POST "http://localhost:${LITELLM_PORT:-4000}/key/generate" \
|
|
-H "Authorization: Bearer ${LITELLM_MASTER_KEY}" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{\"key_alias\": \"${alias}\"}" | jq -r '.key')
|
|
if [ -n "$minted" ] && [ "$minted" != "null" ]; then
|
|
# Same missing-line-vs-blank-line handling as set_if_blank above.
|
|
if grep -qE "^${key}=" .env; then
|
|
sed -i "s|^${key}=.*|${key}=${minted}|" .env
|
|
else
|
|
echo "${key}=${minted}" >> .env
|
|
fi
|
|
echo "${key}: minted."
|
|
else
|
|
echo "${key}: mint failed, create it by hand per docs/proxy-key-onboarding.md."
|
|
fi
|
|
}
|
|
mint_key_if_blank OPENWEBUI_LITELLM_KEY openwebui
|
|
mint_key_if_blank LITELLM_PGVECTOR_EMBEDDING_KEY litellm-pgvector
|
|
set -a && . ./.env && set +a
|
|
|
|
echo "==> recreating changed services"
|
|
docker compose up -d --remove-orphans
|
|
|
|
# litellm-pgvector's Dockerfile only runs `prisma generate` (codegen) at
|
|
# build time — nothing ever applied the schema to pgvector-db itself, so the
|
|
# vector_stores/embeddings tables plain didn't exist until this was added
|
|
# (see issue #24). --accept-data-loss is the same "no rollback/backup logic,
|
|
# git revert is the recovery path" tradeoff as the rest of this script — a
|
|
# schema-incompatible change here would need a manual look regardless.
|
|
echo "==> syncing litellm-pgvector's database schema"
|
|
docker compose up -d --wait pgvector-db litellm-pgvector
|
|
docker compose exec -T litellm-pgvector prisma db push --accept-data-loss
|
|
|
|
# Registers memory-and-notes in litellm's own DB (LiteLLM_ManagedVectorStoresTable),
|
|
# not just litellm-config.yaml's vector_store_registry block. Both matter for
|
|
# different reasons: config.yaml seeds it into memory at boot (works even
|
|
# before this script has ever run against a fresh DB); the DB row is what
|
|
# /vector_store/list — and so the Admin UI's Vector Stores page — actually
|
|
# shows, since that endpoint only auto-syncs a config-only entry into the DB
|
|
# view once a DB row with the same id exists (see issue #24 follow-up).
|
|
#
|
|
# Must pass the real key, not the os.environ/... form used in
|
|
# litellm-config.yaml — this hits the live management API, not the
|
|
# config.yaml loader, so there's no env-substitution pass over the request
|
|
# body. Ignores failure if the row already exists (no update-in-place: see
|
|
# below).
|
|
#
|
|
# No update-if-changed path — the DB row is otherwise never touched once
|
|
# created (/vector_store/update in this litellm version can't set
|
|
# litellm_params at all — VectorStoreUpdateRequest has no such field, so an
|
|
# update silently no-ops on it). If LITELLM_PGVECTOR_API_KEY ever rotates,
|
|
# fix this row by hand: /vector_store/delete then re-run this script.
|
|
echo "==> registering memory-and-notes vector store with litellm (for the Admin UI)"
|
|
curl -sf -X POST "http://localhost:${LITELLM_PORT:-4000}/vector_store/new" \
|
|
-H "Authorization: Bearer ${LITELLM_MASTER_KEY}" \
|
|
-H "Content-Type: application/json" \
|
|
-d "$(jq -n --arg key "${LITELLM_PGVECTOR_API_KEY}" '{
|
|
vector_store_id: "memory-and-notes",
|
|
custom_llm_provider: "pg_vector",
|
|
vector_store_name: "memory-and-notes",
|
|
litellm_params: {api_base: "http://litellm-pgvector:8000", api_key: $key}
|
|
}')" > /dev/null 2>&1 || echo "memory-and-notes: already registered (or registration failed — check by hand if this is a fresh deploy)."
|
|
|
|
echo "==> status"
|
|
docker compose ps
|