Dokumen yang paling mau ditanyain tim kamu justru yang nggak boleh keluar dari jaringan. Kontrak, postmortem insiden, data pelanggan, spec internal yang udah bertahun-tahun nggak ada yang baca. Akhirnya pilihannya jelek dua-duanya: tool chat yang nggak boleh dipakai buat kerja beneran, atau ritual copy-paste yang tetep bikin datanya keluar.
Jalanin frontend sendiri nyelesaiin ini dengan bener. Open WebUI itu antarmuka chat yang kamu host sendiri. Dia nyambung ke Ollama, OpenAI, Anthropic, atau endpoint apa pun yang OpenAI-compatible, nyimpen semua percakapan di database lokal, dan nambahin hal yang nggak dimiliki endpoint model mentah: akun, retrieval dokumen, web search, dan UI yang bisa dibuka tim kamu dari HP. Versi v0.11.3 adalah rilis stabil saat ini.
Panduan ini jalan dari satu kali docker run sampai punya knowledge base yang bisa di-query dan web search yang nggak ngebenci query kamu ke pihak ketiga. File compose di bawah udah divalidasi, dan tag versinya udah saya cek langsung ke registry.
Prerequisites
- Docker Engine dengan plugin Compose v2.
docker compose versionharus ngeprint nomor versi. - Ollama bisa dijangkau dari host kamu, install native atau di container.
- Mesin yang nyala terus. Ini service, bukan script sekali jalan.
- Sisa disk dan memori. Container UI-nya ringan; yang makan resource itu modelnya. Siapin ruang buat bobot model yang beneran mau kamu jalanin.
Langkah 1: satu perintah sampai UI jalan
docker pull ghcr.io/open-webui/open-webui:v0.11.3
docker run -d -p 3000:8080 -v open-webui:/app/backend/data --name open-webui ghcr.io/open-webui/open-webui:v0.11.3
Buka http://localhost:3000. Dua flag yang penting. -v open-webui:/app/backend/data itu tempat chat, akun, dan file upload disimpen, jadi kalau flag ini dihapus semua isinya hilang di recreate berikutnya. -p 3000:8080 mindahin port 8080 internal container ke 3000 di host kamu.
Akun pertama yang kamu daftarin jadi administrator. Semua pendaftaran setelah itu statusnya Pending sampai admin nge-approve.
Pin versinya, dan bukan karena paranoid. :main dan :latest itu rolling tag yang di-rebuild tiap ada merge ke branch main, jadi update bisa masuk semalam dan ngubah perilaku pas kamu tidur. :v0.11.3 nggak pernah bergerak. Docs-nya juga nyediain varian :ollama (Ollama ikut di dalam) dan :cuda.
Langkah 2: benerin dua hal yang baru kerasa belakangan
Bikin secret key dulu.
openssl rand -hex 32
Hasilnya dipasang sebagai WEBUI_SECRET_KEY. Tanpa key yang stabil, tiap kali container di-recreate semua user ke-logout dan session-nya hangus. Ini keluhan "kenapa harus login lagi" yang paling sering muncul, dan fix-nya cuma satu environment variable.
Terus tentuin cara loginnya sebelum URL-nya kamu sebar:
- Multi-user: biarin auth nyala, lalu set
ENABLE_SIGNUP=falsesetelah tim kamu terdaftar, biar nggak ada yang bisa daftar sendiri di instance yang kebetulan bisa diakses. - Single user:
WEBUI_AUTH=Falsebikin halaman login dilewatin sepenuhnya.
Satu peringatan dari docs yang gampang kelewat: kamu nggak bisa pindah antara mode single-user dan multi-account setelah perubahan itu. Pilih bentuk yang beneran kamu mau di hari pertama.
Langkah 3: stack compose yang layak disimpen
Satu container cukup buat coba-coba. Buat yang mau kamu biarin nyala, masukin ke compose bareng bagian yang bakal kamu butuhin: image yang di-pin, secret dari .env, dan SearXNG di network yang sama biar web search tetep di rumah sendiri.
services:
open-webui:
image: ghcr.io/open-webui/open-webui:v0.11.3
container_name: open-webui
ports:
- "3000:8080"
volumes:
- open-webui:/app/backend/data
environment:
- OLLAMA_BASE_URL=http://host.docker.internal:11434
- WEBUI_SECRET_KEY=${WEBUI_SECRET_KEY}
- ENABLE_SIGNUP=false
- ENABLE_WEB_SEARCH=true
- WEB_SEARCH_ENGINE=searxng
- SEARXNG_QUERY_URL=http://searxng:8080/search?q=<query>
extra_hosts:
- "host.docker.internal:host-gateway"
depends_on:
- searxng
restart: unless-stopped
searxng:
image: searxng/searxng:latest
container_name: searxng
volumes:
- ./searxng:/etc/searxng:rw
environment:
- SEARXNG_BASE_URL=http://localhost:8080/
cap_drop:
- ALL
restart: unless-stopped
volumes:
open-webui:
Kenapa bentuknya gini. Baris extra_hosts itu yang bikin host.docker.internal nunjuk ke host kamu di Linux; Docker Desktop nyediain nama itu otomatis di macOS dan Windows. Dua container-nya share network default, jadi Open WebUI nyampe SearXNG di http://searxng:8080 tanpa perlu publish SearXNG ke luar. cap_drop: ALL di container search ngikutin saran hardening dari docs. Kamu bisa cek file-nya sendiri pakai docker compose config -q, yang diem aja kalau sintaks dan interpolasi variabelnya valid.
Jalanin:
echo "WEBUI_SECRET_KEY=$(openssl rand -hex 32)" > .env
docker compose up -d
Langkah 4: arahin UI ke model
Kalau Ollama jalan di host, OLLAMA_BASE_URL=http://host.docker.internal:11434 udah cukup. Jalan di mesin lain? Pakai alamat itu. Kalau model picker-nya kosong, masuk Admin > Connections, tambahin URL-nya di situ, lalu pull model dari Model Selector.
Connection type "Ollama" artinya HTTP API Ollama di port 11434. Backend yang cuma ngomong standar OpenAI (vLLM, LocalAI, Docker Model Runner) tempatnya di OpenAI-compatible connections, dan di situ fiturnya lebih lengkap buat protokol itu. Kamu juga bisa daftarin beberapa instance Ollama sekaligus, dan Open WebUI nyebarin request ke semuanya dengan random selection, tapi ID model-nya harus sama persis atau di picker muncul entri dobel.
Langkah 5: query dokumen kamu sendiri
Ada dua cara pakai retrieval, dan dua-duanya beda fungsi. Drag file ke chat buat pertanyaan sekali lewat, file-nya di-chunk dan di-embed cuma buat percakapan itu. Buat yang bakal kamu tanyain berulang, bikin knowledge base di Workspace > Knowledge, terus attach ke chat pakai shortcut # atau bind ke sebuah model di Workspace > Models biar semua percakapan punya akses.
Default bawaan udah cukup buat satu orang dengan beberapa PDF. Sebelum tim kamu pakai, ubah ini dulu:
| Setting | Default | Rekomendasi | Alasan |
|---|---|---|---|
| Text splitter | character | token | ukuran chunk lebih konsisten antar jenis dokumen |
| Chunk size / overlap | 1000 / 100 | 2000 / 200 | konteks sekitar lebih banyak per hit, kalimat nggak kepotong tengah |
| Top K | 3 | 15 | kandidat yang diambil lebih luas buat dipilih model |
Tiga setting infrastruktur baru kerasa setelah lewat sekitar seratus dokumen atau sepuluh user bersamaan, dan ketiganya ada di docs Open WebUI:
- Embeddings. Model default
all-MiniLM-L6-v2jalan lokal di CPU dan makan sekitar 500 MB RAM per worker. SetRAG_EMBEDDING_ENGINE=ollamapakainomic-embed-text, atau arahin ke embeddings API, biar memorinya balik. - Content extraction. Extractor default
pypdfbocor memori pas ingestion berat. Ganti ke Tika atau Docling lewatCONTENT_EXTRACTION_ENGINE. - Vector database. Client ChromaDB default berbasis SQLite dan nggak tahan multi-worker. PGVector satu-satunya vector database yang di-maintain tim Open WebUI.
Satu switch lagi yang sayang dilewatin: ENABLE_KB_EXEC=True ngasih model antarmuka bergaya filesystem di atas knowledge base kamu, dengan akses ala ls, tree, grep, dan cat. Model yang capable lebih andal ngerangkai itu daripada manggil search satu-satu. Ini nggak ngaruh buat model yang di-set ke mode tool-calling legacy, karena built-in tools nggak ada di mode itu.
Langkah 6: web search tanpa API key
SearXNG itu metasearch engine yang kamu host sendiri, jadi query-nya nggak pernah keluar dari infrastruktur kamu. Docs Open WebUI nyebut setup ini sebagai tutorial komunitas, bukan jalur yang di-support resmi, tapi langkahnya singkat.
git clone https://github.com/searxng/searxng-docker.git
cd searxng-docker
sed -i 's/127.0.0.1:8080/0.0.0.0:8080/' docker-compose.yaml
Bikin searxng/limiter.toml dengan batas bot-detection dilonggarin, karena Open WebUI manggil API-nya langsung:
[botdetection.ip_limit]
link_token = false
[botdetection.ip_lists]
block_ip = []
pass_ip = []
Terus hapus searxng/settings.yml, nyalain container sebentar biar dia generate yang baru, lalu matiin lagi:
rm searxng/settings.yml
docker compose up -d ; sleep 10 ; docker compose down
sed -i 's/- html/- html\n - json/' searxng/settings.yml
docker compose up -d
Baris terakhir itu yang paling sering dilewatin. SearXNG defaultnya cuma ngehasilin HTML, dan Open WebUI baca JSON. Tanpa baris format itu, search balik kosong tanpa error yang jelasin kenapa.
Lalu pastiin sisi Open WebUI punya WEB_SEARCH_ENGINE=searxng dan query URL-nya nunjuk ke container: http://searxng:8080/search?q=<query>. Karena native function calling jadi mode default, model yang mutusin sendiri kapan pertanyaan butuh web terbaru. Toggle di kolom prompt cuma ada buat maksa pencarian baru.
Langkah 7: dua setting yang bikin kerasa cepat
Judul chat, tag, pertanyaan lanjutan, dan autocomplete prompt semuanya jalan di model chat utama kamu sebelum kamu bilang sebaliknya. Di model lokal 30B itu artinya kolom teks kerasa lag dan compute kebuang buat tugas dua kata. Set model kecil khusus buat task di Admin > Interface, dan overhead itu hilang.
Yang kedua cuma penting kalau kamu pakai model hosted. Definisi tool duduk bersebelahan sama system prompt di bagian prefix yang di-cache, jadi ganti kategori tool atau nyalain web search di tengah percakapan bikin prompt cache-nya hangus dari titik itu. Jaga daftar tool-nya stabil selama kerja.
Jebakan ConfigVar
Kalau kamu terbiasa sama environment variable biasa, yang ini bisa makan seharian. Banyak setting, termasuk web search, ditandai ConfigVar di docs. Di launch pertama Open WebUI baca nilainya dari environment lalu nyimpennya internal. Restart dengan env var yang udah diubah dan nggak terjadi apa-apa, karena nilai yang tersimpan yang menang. Docs-nya jelas bilang ini memang by design.
Ada dua jalan keluar. Edit setting-nya di admin UI, yang memang tempatnya, atau set ENABLE_PERSISTENT_CONFIG=False biar environment variable selalu menang. Dua-duanya sah; pilihan kedua artinya edit di admin UI nggak akan tersimpan, jadi pilih dengan sadar.
Kapan pakai ini vs alternatif
Perbandingan jujurnya, karena pilihan yang salah di sini lebih mahal dari satu container.
| Open WebUI | LibreChat | AnythingLLM | Ollama CLI | |
|---|---|---|---|---|
| Fokus | platform lengkap: chat, knowledge, tools, fitur tim | antarmuka chat multi-provider | workspace tanya-jawab dokumen | runner model satu mesin |
| Lisensi | Open WebUI License (harus pertahankan branding) | MIT | MIT | MIT |
| Paling cocok kalau | kamu butuh knowledge base, channels, dan role tim | kamu mau chat fokus dengan perbandingan model berdampingan | kamu utamanya mau ngobrol sama dokumen, desktop dulu | kamu cuma mau jawaban sekarang |
Dua lisensi di situ lebih penting dari yang orang kira. LibreChat dan AnythingLLM itu MIT, jadi kamu bebas fork dan ganti merek. Lisensi Open WebUI saat ini bawa syarat mempertahankan branding, sedangkan kontribusi lama tetap pakai ketentuan aslinya. Baca lisensinya sebelum berencana white-label.
Kapan Open WebUI justru jawaban yang salah:
- Kamu butuh beberapa replica atau lebih dari satu worker Uvicorn. Client ChromaDB default nggak fork-safe dan tulisan bersamaan bikin worker crash, jadi vector database-nya harus dipindah dulu. Ini ada di docs, bukan bug yang bisa diakalin.
- Tim kamu nggak mau ngurusin operasional apa pun. Produk hosted lebih murah dari jam kerja kamu buat upgrade.
- Satu model di satu laptop, nggak dipakai orang lain. CLI lebih cepat sampai jawaban.
Troubleshooting yang sering muncul
Halaman blank atau tombol mati di belakang reverse proxy: Open WebUI butuh dukungan WebSocket, dan proxy yang nggak nerusin header upgrade bakal nampilin shell yang rusak. Docs-nya nyediain config Nginx, Caddy, dan HAProxy yang jalan.
Konflik port 8080: container listen di 8080 internal dan SearXNG default-nya 8080 di host. Jaga mapping di sisi host tetap beda. Di stack atas, SearXNG nggak di-publish ke host sama sekali, jadi masalahnya kelewat sampai kamu butuh UI-nya sendiri.
Model picker lambat atau nyangkut: endpoint yang udah nggak bisa dijangkau bikin request daftar model nunggu sampai timeout penuh. AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST=3 motong waktu tunggunya.
Langkah selanjutnya
Sekarang kamu punya platform chat self-hosted dengan retrieval dan web search, jalan dari file compose yang bisa dibaca sekali duduk. Langkah berikutnya, kira-kira urut dari yang paling ngefek: taruh di belakang HTTPS pakai Caddy atau Nginx, backup volume open-webui, lalu pindah ke PostgreSQL, Redis, dan PGVector kalau jumlah user-nya nambah.