Open WebUI — web interfejs za tvoje lokalne modele
Model koji radi u terminalu je dokaz da postavka valja. Model koji koriste ljudi u firmi mora da izgleda kao nešto što svi već znaju da koriste — sa nalozima, istorijom razgovora i mogućnošću da se priloži fajl.
Open WebUI je upravo to: veb sloj iznad tvoje Ollame ili vLLM-a. Ovim tekstom se zatvara Faza 3, jer je postavka od ovog trenutka upotrebljiva i za nekog ko nikad neće otvoriti terminal.
Šta dobijaš
- Razgovor u pregledaču, sa istorijom koja se čuva
- Korisničke naloge i prava pristupa po modelu
- Prilaganje dokumenata i pitanja nad njihovim sadržajem
- Sopstvene sistemske promptove sačuvane kao modeli
- Rad sa više servisa odjednom — lokalni model i spoljni API na istom mestu
Ono što ne dobijaš je bilo kakvo ubrzanje. Interfejs samo prosleđuje zahteve; brzina i dalje zavisi od toga šta je ispod, kako je opisano u tekstu o proceni VRAM-a.
Ovo je dodatni servis sa sopstvenom bazom i nalozima. Znači i sopstvenu površinu za napad, i sopstvene rezervne kopije. Ako si jedini korisnik, terminal je i dalje sasvim u redu.
Instalacija
Uz Ollamu koja već radi na domaćinu:
$ docker run -d \
--name open-webui \
-p 127.0.0.1:3000:8080 \
-v /data/open-webui:/app/backend/data \
-e OLLAMA_BASE_URL=http://host.docker.internal:11434 \
--add-host=host.docker.internal:host-gateway \
--restart unless-stopped \
ghcr.io/open-webui/open-webui:main
Zapis host.docker.internal uz --add-host je način da kontejner dođe do servisa na domaćinu. Bez toga localhost unutar kontejnera pokazuje na sam kontejner.
Ako je Ollama takođe u kontejneru, čistije je kroz compose iz prethodnog teksta:
services:
ollama:
image: ollama/ollama
container_name: ollama
restart: unless-stopped
volumes:
- /data/ollama:/root/.ollama
environment:
- OLLAMA_KEEP_ALIVE=-1
- OLLAMA_CONTEXT_LENGTH=16384
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
webui:
image: ghcr.io/open-webui/open-webui:main
container_name: open-webui
restart: unless-stopped
depends_on:
- ollama
ports:
- "127.0.0.1:3000:8080"
volumes:
- /data/open-webui:/app/backend/data
environment:
- OLLAMA_BASE_URL=http://ollama:11434
- WEBUI_AUTH=true
$ docker compose up -d $ docker compose logs -f webui
Prvo podizanje traje duže jer se preuzima i model za embeddinge. Otvori zatim http://localhost:3000.
Prvi napravljeni nalog dobija administratorska prava. Napravi ga odmah, pre nego što servis izložiš bilo kome — inače to uradi neko drugi.
Bez Dockera
$ pipx install open-webui $ open-webui serve --port 3000
Radi, ali povlači podosta Python zavisnosti i ažurira se teže. Kontejner je ovde jasno bolji izbor.
Povezivanje sa vLLM-om
Open WebUI govori i OpenAI protokolom, pa vLLM ide bez ikakvog posrednika:
environment: - OPENAI_API_BASE_URL=http://vllm:8000/v1 - OPENAI_API_KEY=tajni-kljuc-ovde
Oba se mogu postaviti istovremeno — Ollama i vLLM tada stoje u istom padajućem meniju za izbor modela. Isto važi i za spoljne komercijalne servise, ako ih koristiš uporedo.
Podešavanje se može i kroz sam interfejs, pod Settings → Connections, što je zgodnije za probanje nego menjanje compose fajla.
Korisnici i prava
Ovo je razlog zbog koga se interfejs uopšte uvodi u firmu.
Podrazumevano novi korisnici čekaju odobrenje administratora, i tako treba da ostane. Pod Admin Panel → Settings:
| Podešavanje | Preporuka |
|---|---|
| Enable New Sign Ups | Isključi kad svi imaju nalog |
| Default User Role | pending, nikako user |
| Model Whitelist | Ograniči ko koji model vidi |
| Allow Chat Deletion | Zavisi od toga da li ti treba trag |
Isto kroz okruženje, ako voliš da postavka stoji u fajlu:
environment: - WEBUI_AUTH=true - ENABLE_SIGNUP=false - DEFAULT_USER_ROLE=pending
Vrednost WEBUI_AUTH=false isključuje prijavu u potpunosti. Naići ćeš na nju u uputstvima za lokalno probanje. Na serveru koji je dostupan bilo kome van tvoje mašine to ne dolazi u obzir.
Sopstveni modeli
Isto što i Modelfile u Ollami, samo kroz interfejs. Pod Workspace → Models praviš varijantu sa svojim sistemskim promptom:
Naziv: Linux pomoćnik Osnova: qwen3:8b Temperatura: 0.1 Sistemski prompt: Ti si pomoćnik za administraciju Linux servera. Odgovaraj kratko i konkretno, na srpskom. Uz svaku komandu navedi šta tačno radi. Nikada ne predlaži komandu koja briše podatke bez izričitog upozorenja.
Prednost nad Modelfile pristupom je što se ovako napravljen model može podeliti sa ostalim korisnicima ili zadržati samo za sebe. U timu je to praktičnije nego da svako pravi svoj.
Rad sa dokumentima
Fajl se priloži u razgovoru znakom # ili spajalicom, a za trajnu zbirku ide Workspace → Knowledge. Dokumenti se seku na delove, pretvaraju u embeddinge i pri svakom pitanju se relevantni delovi ubacuju u prompt.
To je RAG, i radi bez ijedne linije koda. Ograničenja su ista kao kod svake RAG postavke:
- Kvalitet zavisi od toga koliko su dokumenti uredno strukturirani
- Skenirani PDF bez teksta ne daje ništa
- Pronađeni delovi troše kontekst, pa sa velikom zbirkom razgovor brzo naraste
Podrazumevani model za embeddinge je mali i radi na procesoru. Za ozbiljniju upotrebu zameni ga pod Admin Panel → Settings → Documents onim koji vrtiš na Ollami:
$ docker exec ollama ollama pull nomic-embed-text
Kako sve ovo radi ispod haube i kada je bolje sagraditi sopstveno rešenje, tema je teksta o RAG-u.
Izlaganje prema mreži
Interfejs traži lozinku, pa je za razliku od Ollame bar donekle zaštićen. To i dalje ne znači da sme direktno na internet — kolačići sesije preko HTTP-a putuju u čitljivom obliku.
Postavka koja se koristi:
Internet → Nginx (TLS) → Open WebUI → Ollama
:3000 :11434
lokalno lokalno
Oba servisa slušaju samo na 127.0.0.1, a napolju stoji jedino proxy sa sertifikatom. Postavka je opisana u tekstu o reverse proxy-ju.
Jedna stvar koja se ovde često previdi — bez podrške za WebSocket odgovori ne stižu postepeno, nego se čeka pa sve odjednom:
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 300s;
}
Dugačak proxy_read_timeout je takođe potreban, jer veći model ume da razmišlja duže od podrazumevanog roka.
Rezervne kopije
Sve što interfejs zna stoji u jednom direktorijumu — nalozi, razgovori, prilozi, sopstveni modeli:
$ ls /data/open-webui webui.db uploads/ vector_db/ cache/
Baza je SQLite, pa kopija ide pri zaustavljenom kontejneru:
$ docker compose stop webui $ sudo tar -czf /backup/open-webui-$(date +%F).tar.gz -C /data open-webui $ docker compose start webui
Ako servis ne sme da stane, koristi ugrađenu komandu koja pravi ispravnu kopiju baze u radu:
$ docker compose exec webui sqlite3 /app/backend/data/webui.db ".backup '/tmp/webui.db'" $ docker compose cp webui:/tmp/webui.db /backup/
Kopiranje SQLite fajla dok se u njega piše daje oštećenu bazu. Ovo je greška koja se otkriva tek kad kopija zatreba.
Automatizacija preko cron zadatka je posao od pet minuta i vredi je odraditi odmah.
Ažuriranje
$ docker compose pull $ docker compose up -d
Projekat se menja brzo i podešavanja povremeno menjaju mesto u interfejsu. Napravi kopiju pre ažuriranja — vraćanje na staru sliku je lako, vraćanje pokvarene baze nije.
$ docker image prune -a
Praktični scenariji
Scenario 1: interfejs radi, ali nema nijednog modela
Veza sa Ollamom nije uspostavljena. Proveri iz samog kontejnera:
$ docker compose exec webui curl -s http://ollama:11434
Ako odgovora nema, greška je u nazivu servisa ili u tome što Ollama sluša na pogrešnoj adresi.
Scenario 2: odgovor se pojavljuje tek na kraju, odjednom
Reverse proxy ne propušta WebSocket. Dodaj zaglavlja Upgrade i Connection.
Scenario 3: prekid veze usred dužeg odgovora
Podigni proxy_read_timeout na pet minuta ili više.
Scenario 4: neko je napravio nalog bez odobrenja
Registracija je bila otvorena, a podrazumevana uloga postavljena na user. Isključi registraciju i pregledaj spisak naloga u administratorskom panelu.
Scenario 5: priloženi PDF daje besmislene odgovore
Verovatno je skeniran, bez tekstualnog sloja. Proveri:
$ pdftotext dokument.pdf - | head
Ako je ispis prazan, treba OCR pre nego što dokument ima smisla priložiti.
Scenario 6: posle ažuriranja nema razgovora
Volumen nije bio podešen, pa je baza ostala u starom sloju kontejnera. Ovo je razlog zbog koga se rezervna kopija radi pre ažuriranja, a ne posle.
Kratka referenca
ghcr.io/open-webui/open-webui:main— zvanična slika-v /data/open-webui:/app/backend/data— sve što servis pamtiOLLAMA_BASE_URL— adresa OllameOPENAI_API_BASE_URL— vLLM ili spoljni servis--add-host=host.docker.internal:host-gateway— pristup domaćinuWEBUI_AUTH=true— prijava uključena; nikad nafalsevan lokalne mašineENABLE_SIGNUP=false— zatvaranje registracijeDEFAULT_USER_ROLE=pending— novi nalozi čekaju odobrenje- Prvi nalog je administratorski — napravi ga odmah
- Workspace → Models — sopstveni sistemski promptovi
- Workspace → Knowledge — RAG nad zbirkom dokumenata
proxy_set_header Upgrade— bez toga nema postepenog ispisasqlite3 ... ".backup"— ispravna kopija baze u radudocker compose pull && up -d— ažuriranje
Vežba
- Pokreni Open WebUI uz Ollamu kroz compose i napravi administratorski nalog.
- Proveri sa
ss -tulpnda je vidljiv samo port interfejsa, ne i Ollamin. - Napravi sopstveni model sa svojim sistemskim promptom i uporedi odgovore sa osnovnim.
- Priloži jedan tekstualni dokument i postavi tri pitanja čiji su odgovori u njemu.
- Napravi drugi nalog i ograniči mu spisak modela koje vidi.
- Napravi rezervnu kopiju, obriši volumen, vrati kopiju i potvrdi da su razgovori tu.
Sledeći tekst u serijalu: OpenAI-kompatibilan API na svom serveru
Povezano:
- AI na Linux serveru — pregled celog serijala
- Ollama u Dockeru sa GPU passthrough-om — prethodni tekst
- Ollama: instalacija na Linux serveru — servis ispod interfejsa
- Docker Compose — više kontejnera odjednom
- cron — zakazivanje rezervnih kopija
Comments
Post a Comment