Kubernetes
Libre WebUI furnizează un chart Helm în helm/libre-webui.
Work pe Kubernetes
Work rulează nativ pe Kubernetes — fără daemon, CLI sau socket Docker. Activați-l la instalare:
helm install libre-webui ./helm/libre-webui --set work.enabled=true
Aceasta setează WORK_RUNTIME_BACKEND=kubernetes și creează:
- un namespace sandbox dedicat (
work.namespace, implicitlibre-webui-work) cu câte un Pod per sandbox activ și un PersistentVolumeClaim per workspace (work.workspaceSize, implicit5Gi— cotă reală pe task; o policy numită poate seta alta); - Role și RoleBinding limitate la namespace, care acordă ServiceAccount exact
pods(get/list/create/delete),pods/exec(get/create) șipersistentvolumeclaims(get/list/create/delete) — fără secrets sau cluster scope. Înlocuiesc complet socketul Docker: API server impune ca sandboxul să nu monteze căi host; - NetworkPolicies default-deny, ingress numai din backend pe preview port și internet
egress pentru sandboxuri cu rețea, minus
work.networkPolicy.blockedEgressCidrs(range-uri private, CGNAT folosit de unele clustere și cloud metadata link-local). Verificați CIDR-urile Pod/service. DNS sandbox doar cătrekube-system; node-local DNS cere excepție.
Sandboxurile rulează non-root, rootfs read-only, fără capabilities, seccomp
RuntimeDefault și fără token ServiceAccount. Fișierele, comenzile, git și terminalele
folosesc exec prin API server; preview este servit din Pod IP prin proxy semnat same-origin,
ceea ce cere backend in-cluster. Workspace-urile host-folder nu sunt suportate.
Două note: NetworkPolicy cere un CNI care o impune (Calico, Cilium, kind recent și majoritatea clusterelor administrate). Verificați înainte de a considera izolarea activă; suita CI raportează enforcement. Nu montați niciodată socketul runtime al nodului în Podul WebUI.
Instalare
helm install libre-webui oci://ghcr.io/libre-webui/charts/libre-webui
Chartul implicit deployează Libre cu storage persistent și Ollama inclus. Tranziția
0.14.1 este fixată la digest multi-architecture verificat; charturile ulterioare folosesc
image-ul semantic appVersion. Setați image.tag sau image.digest numai deliberat.
Un image.tag non-empty are prioritate față de digestul tranziției.
Profilul solo acceptă replicaCount: 0 pentru suspendare sau replicaCount: 1 pentru
funcționare. Refuză valori mai mari și HorizontalPodAutoscaler deoarece SQLite,
fișierele locale și coordonarea proces-local nu sunt sigure cu mai multe pods. La zero
se creează control-plane resources, dar nu se servește trafic.
Pentru mai multe replici folosiți profilul complet team: PostgreSQL/PGVector, blob S3,
Redis și worker persistent separat. Chartul refuză amestec parțial shared/local. Porniți
de la un fișier values protejat:
replicaCount: 3
env:
LIBRE_PLATFORM_MODE: team
DATABASE_BACKEND: postgres
DATABASE_SSL_MODE: verify-full
POSTGRES_MIGRATION_MODE: apply
POSTGRES_POOL_MAX: 10
POSTGRES_CONNECT_TIMEOUT_MS: 5000
POSTGRES_IDLE_TIMEOUT_MS: 30000
POSTGRES_STATEMENT_TIMEOUT_MS: 30000
POSTGRES_MIGRATION_LOCK_TIMEOUT_MS: 60000
OLLAMA_TIMEOUT: 300000
OLLAMA_LONG_OPERATION_TIMEOUT: 900000
OLLAMA_MAX_CONTEXT: 32768
BLOB_STORE_BACKEND: s3
VECTOR_STORE_BACKEND: pgvector
COORDINATION_BACKEND: redis
JOB_WORKER_MODE: external
STORAGE_ENCRYPTION_ACTIVE_KEY_ID: active
S3_BUCKET: libre-blobs
S3_REGION: us-east-1
S3_BLOB_PREFIX: libre/blobs
worker:
replicaCount: 1
secrets:
databaseUrl: postgresql://libre:replace-me@postgres.example/libre
redisUrl: rediss://redis.example:6379/0
jwtSecret: '<one-stable-high-entropy-secret-for-every-replica>'
encryptionKey: '<legacy-64-character-lowercase-hex-key>'
storageEncryptionKeys: '{"legacy":"<legacy-64-character-lowercase-hex-key>","active":"<active-64-character-lowercase-hex-key>"}'
s3AccessKeyId: replace-me
s3SecretAccessKey: replace-me
secrets.encryptionKey trebuie să corespundă exact intrării legacy, iar map-ul să
conțină STORAGE_ENCRYPTION_ACTIVE_KEY_ID. secrets.jwtSecret trebuie să fie o valoare
stabilă high-entropy comună tuturor app/worker pods; fără ea chartul refuză team pentru
ca sesiunile să nu depindă de material pod-local. Păstrați TLS verificat pentru
PostgreSQL administrat și nu adăugați parametri TLS driver în databaseUrl. Limitele
pool sunt per pod, deci rezervați cel puțin
(replicaCount + worker.replicaCount) * POSTGRES_POOL_MAX conexiuni plus rezervă.
helm upgrade --install libre-webui \
oci://ghcr.io/libre-webui/charts/libre-webui \
--values /absolute/path/to/libre-team-values.yaml
Nu commitați fișierul și nu treceți secrets prin --set. Folosiți workflow encrypted.
Scalați furnizorii și Pods Work independent. Cu work.enabled=true, workerul extern
primește același image, StorageClass, work.env, endpoint Ollama, timeouts și context ca
app, fiindcă embeddings, chat-uri și Work calls rulează acolo.
O app team activă (replicaCount pozitiv sau autoscaling) cere cel puțin un worker;
chartul refuză zero. Pentru suspendare totală setați replicaCount și
worker.replicaCount zero. Numai app zero este drain/recovery worker-only: fără web,
dar coada continuă.
Upgrade team și compatibilitate schema
Libre cere exact schema version, nu mixed sau zero-downtime DB upgrade. App și worker
folosesc Recreate, fără overlap în fiecare Deployment, dar Kubernetes nu le coordonează
ca o singură limită. Înainte: opriți ingress, terminați/anulați jobs, scalați ambele la
zero, backup verificat și confirmați terminarea pods. Apoi upgrade cu
POSTGRES_MIGRATION_MODE=apply; un proces ține advisory leader lock, celelalte așteaptă
și validează ledger-ul. Pentru rollback restaurați backupul într-o țintă PostgreSQL/S3
curată; niciodată binary vechi pe schema incompatibilă. Va exista întrerupere deliberată.
Acces local
kubectl port-forward svc/libre-webui 8080:8080
Deschideți http://localhost:8080.
Ollama extern
Folosiți un endpoint Ollama existent:
helm install libre-webui oci://ghcr.io/libre-webui/charts/libre-webui \
--set ollama.bundled.enabled=false \
--set ollama.external.enabled=true \
--set ollama.external.url=http://my-ollama:11434
Secrete
Setați un JWT secret stabil și o cheie de criptare. Implicit chartul creează
<release>-libre-webui-secrets din valori non-empty secrets.*:
helm upgrade --install libre-webui \
oci://ghcr.io/libre-webui/charts/libre-webui \
--set-string secrets.jwtSecret="$(openssl rand -hex 64)" \
--set-string secrets.encryptionKey="$(openssl rand -hex 32)"
Pentru Secret administrat de operator setați secrets.existingSecret; chartul nu mai
creează și app/worker referă obiectul numit:
secrets:
existingSecret: libre-webui-runtime
Creați înainte de release. Trebuie jwt-secret, encryption-key, iar team și
database-url, redis-url, storage-encryption-keys. Opțional session-secret,
s3-access-key-id, s3-secret-access-key, s3-session-token. OAuth GitHub/Hugging
Face citește *-client-id/*-client-secret când secrets.githubClientId sau
secrets.huggingfaceClientId non-empty activează integrarea. Chartul nu validează/copiază
valorile; cheia lipsă împiedică Podul să pornească.
Pentru automatizare preferați secrets.existingSecret cu external-secrets sau values
criptate. --set poate fi vizibil în procese și metadata Helm. Credentialele provider
prin extensie deliberată sau per utilizator în WebUI.
NetworkPolicies pentru aplicație și worker
Setați networkPolicy.enabled=true pentru ingress policies app și worker team:
networkPolicy:
enabled: true
App acceptă ingress numai pe portul HTTP, workerul niciunul. Policies nu limitează egress: procesele trebuie să atingă PostgreSQL, Redis, S3, Ollama, tools și furnizori, iar operatorul decide locația.
Este separat de work.networkPolicy.enabled, default-deny în namespace Work, activat
implicit cu Work. Ambele cer CNI enforcement; randarea obiectelor nu dovedește izolarea.
Persistență
Păstrați PVC data și Ollama pe storage persistent. Salvați volumul și cheia împreună.
Workspace-urile Work au PVC proprii în sandbox, nu data PVC. Recovery complet cere baza (ownership, nume, runs) și PVC; salvați împreună.
Ingress
Pentru acces public configurați HTTPS și origin exact:
helm upgrade libre-webui \
oci://ghcr.io/libre-webui/charts/libre-webui \
--reuse-values \
--set env.TRUST_PROXY=1 \
--set-string env.CORS_ORIGIN=https://your-domain.example
TRUST_PROXY este count exact de hops, nu boolean. Default sigur 0 ignoră forwarded
addresses. 1 numai cu un ingress direct; numărați fiecare load balancer în lanț fix și
păstrați Service inaccesibil în afara lui. Prea mic grupează clienți și epuizează login
limits; prea mare crede adresă client. Chartul acceptă 0–16, niciodată true, și îl
trimite numai pods HTTP.
Chartul nu expune BASE_URL sau callbacks OAuth. Instalațiile OAuth trebuie să extindă
chartul/patch Deployment, iar URL-urile să corespundă domeniului public.
Planificarea resurselor
Pentru Ollama local, programați Podul pe nodes cu memorie/GPU suficient. Dacă există un serviciu dedicat Ollama/inference, varianta externă este mai simplă.