Tag: Ollama

A tool for running and serving local LLMs with a simple CLI and an HTTP API.

  • Open WebUI in Docker: A Chat UI for Local LLMs

    Open WebUI in Docker: A Chat UI for Local LLMs

    A model running on your server is powerful, but reaching it through a raw API endpoint is not how a household uses anything. Open WebUI is the most popular self-hosted front end for local models: it runs in a single Docker container, connects to Ollama (or any OpenAI-compatible endpoint) in a couple of lines of configuration, and gives you a clean chat interface with conversations, a model picker and document upload that works in a browser on any device on your network. This guide runs it the way we ran it in the lab — as a two-container stack (Ollama for the model, Open WebUI for the interface) — and walks through the real setup, the first login, connecting the model, and the gotchas that actually appear. Every step below was done and verified on the lab box: a 4-core Intel i5-6500T, 16 GB RAM, Debian 12, Docker 29.7, no discrete GPU.

    Beginner · 11 min · Docker

    What Open WebUI is

    Open WebUI is a web application, not a model runner. It does not load models itself; it connects to a model backend (Ollama, llama.cpp’s server, or any OpenAI-compatible API) and puts a proper interface in front of it. What it adds over a raw API:

    • A chat interface that behaves like a normal chat app: conversations you can go back to, a model selector, streaming responses.
    • Multi-user support. Each person gets an account and their own conversation history. This is what turns “the model on the server” into “the family can each use it”.
    • Document and knowledge features so you can attach a file and ask questions about it, plus prompts, tools and other extensions.
    • A single container that keeps all of its state (users, chats, settings) in one folder, so the whole thing is trivial to back up and move.

    Because it is a front end, the rule for this guide is the same as for the rest of the stack: the model is provided by Ollama (or another runtime), and Open WebUI’s job is to make that model pleasant to use. We used Ollama as the backend in the lab, which is the most common and best-supported pairing.

    The two-container stack

    The cleanest, most reproducible setup is a compose file with two services on a shared Docker network: Ollama running the model, and Open WebUI running the interface, with the UI told to reach Ollama by its service name. This is exactly what we ran end to end in the lab, and a chat request went from the browser-facing container, through to the Ollama container, and back with a real model response.

    services:
      ollama:
        image: ollama/ollama:latest
        container_name: ollama
        volumes:
          - ./ollama:/root/.ollama
        restart: unless-stopped
    
      open-webui:
        image: ghcr.io/open-webui/open-webui:main
        container_name: open-webui
        ports:
          - "127.0.0.1:3005:8080"
        environment:
          - OLLAMA_BASE_URL=http://ollama:11434
          - WEBUI_SECRET_KEY=change-me-to-a-long-random-string
        depends_on:
          - ollama
        volumes:
          - ./open-webui:/app/backend/data
        restart: unless-stopped

    The details that matter. The OLLAMA_BASE_URL points at Ollama by its service name on the shared network (http://ollama:11434), which is why both containers need to be in the same compose project — they can resolve each other by name. The port is published as 127.0.0.1:3005, bound to loopback, so only the server itself can reach the UI directly; that is the safe default and you reach it from your devices over your VPN. The two volumes are the entire state: ./ollama holds the downloaded models and ./open-webui holds the users, chats and settings. Back up those two folders and you can rebuild both containers and lose nothing. The WEBUI_SECRET_KEY signs the app’s sessions — set it to a long random string rather than the placeholder, because it is what makes your logged-in state secure. If you have an NVIDIA GPU, add the standard GPU resource reservation to the Ollama service and the model will run on the GPU instead of the CPU.

    First boot and the admin account

    Run docker compose up -d. Both containers start; Open WebUI takes a little while on first boot while it initializes, so wait for it to report healthy (or for the page to stop showing its loading screen) before trying to log in. The very first thing you do when the UI opens is create the admin account — the first account registered becomes the administrator of the whole instance. Do this before anything else and write the credentials down, because there is no separate “first user” flow and losing them means resetting the auth in the state folder. In the lab we created the admin account and confirmed it by signing back in, which is the step worth doing before you trust anything else.

    Confirm the backend connection next. With the OLLAMA_BASE_URL set in the compose file, Open WebUI should already see the models that Ollama has. If the model list is empty, the UI cannot reach Ollama — which is almost always a network-name or port issue between the two containers, not a problem with either app. Once the model appears, the pairing is working.

    Getting a model in and having a real conversation

    If Ollama has no models yet, pull one. In the lab we used a small, fast model to keep the test clean: a 0.6B model at Q4_K_M, a 522 MB file that Ollama downloaded and verified. With it loaded, we sent a real chat request through the full path — from Open WebUI’s API, to the Ollama container, and back. The response came back with a proper model answer, which is the end-to-end proof that the stack works: the interface, the backend, and the model are all talking to each other correctly. In the UI the same thing is just “type a message and read the answer”, but the API path is worth confirming once, because it is the thing a chat front end is for, and seeing a real response is the fastest way to know the whole chain is healthy.

    One behavior to expect with the newer thinking models: some spend their first tokens on internal reasoning that the backend returns in a separate field, and the final answer can be short. If a reply looks unexpectedly brief, that is usually the model’s doing, not a broken connection. And because the UI is where a whole household will live, set a sensible default model and a reasonable context length once, so every user gets a sane experience without fiddling.

    Security: the part that matters most

    Open WebUI has accounts, but the model backend it fronts does not, and the security of the whole setup is “who can reach the ports”. Keep the UI on loopback (as the compose file does) and reach it from your devices through your VPN — the Tailscale in Docker guide is the clean way to get your phone or laptop onto your home network from anywhere without opening a public port. Do not publish the UI port to your LAN or the internet just because it is convenient; a model front end on an open port is an open door to your server’s compute and to whatever the backend can do. If you do want a named, HTTPS front, the Caddy in Docker guide shows how to add one in front of the loopback port. The security guide covers the firewall rules and network isolation, and setting a real WEBUI_SECRET_KEY (not the placeholder) is the small thing that keeps the app’s own session handling secure.

    Common gotchas

    The model list is empty. The UI cannot reach the backend. In the two-container setup this is almost always that the two services are not on the same network, or the OLLAMA_BASE_URL does not match the service name and port. Check that both containers are up, that they share the compose project, and that the URL points at the right name and port. This was the single most common thing in the lab, and it is a configuration issue, not a broken app.

    The page loads but you cannot do anything / you are logged out repeatedly. Usually the state volume is not persisting, so the app restarts its users on every reload. Confirm the ./open-webui volume is actually being written to and survives a container restart — a fresh data folder on each start is the tell.

    It is slower than the model “should” be. Open WebUI adds a little overhead, but the dominant factor is still the model and the hardware. If the backend (Ollama or llama.cpp) is slow, the UI will be slow; measure the backend directly before blaming the front end. On the lab’s CPU box, small models felt instant and larger ones felt slower, which is the model and the hardware, not the interface.

    First boot looks hung. The container does real work on first start (initializing its database and configuration) and the page shows a loading screen while it does. Give it a moment before concluding it failed; check the container logs if it does not come up, which will say what it is waiting on.

    How this fits the rest of your home server

    Open WebUI is the front door of the local AI stack, and it is the step that turns a working model into something the household actually uses. It pairs with whatever runtime you chose — Ollama in this guide, but the same pattern works with llama.cpp’s server or any OpenAI-compatible backend — and it sits on the same security rules as everything else: loopback by default, reached over your VPN, optionally fronted by HTTPS. Its state is one folder, so it belongs in your normal backup routine alongside the model store, and because a loaded model holds real RAM, it is another reason to have the box watched by monitoring. The shape of the finished setup is the whole series in one picture: the hardware you chose, a model you measured and sized for that hardware, a runtime that serves it, and this chat window in front — all private, all on hardware you own, and all reachable from the devices in the house over a network you control.

    Tested on:

    OSDebian 12
    Docker29.7.2
    Hardware4-core / 16 GB
    StackOpen WebUI (container) + Ollama (container), shared network
    Modelqwen3:0.6b Q4_K_M (522 MB)
    Verifiedend-to-end chat through the full two-container stack

    Last tested: 15 September 2026

  • llama.cpp vs Ollama vs LM Studio: Which to Use

    llama.cpp vs Ollama vs LM Studio: Which to Use

    llama.cpp, Ollama and LM Studio all do the same fundamental job — load a GGUF model and generate text — and they all use the same model files, so choosing between them is not a question of capability. It is a question of how you want to work: how much control you want, how little setup you tolerate, and whether you are on a desktop or a headless server. This guide puts the three side by side, using real measurements from the lab box (a 4-core Intel i5-6500T, 16 GB RAM, Debian 12, no discrete GPU) wherever we could measure, and a clear recommendation for each situation. If you only read one thing: on a CPU box where speed matters, llama.cpp is the fastest; on a server where you want it to “just work” and be scriptable, Ollama is the best default; on a desktop where you want the friendliest experience, LM Studio wins.

    Intermediate · 11 min · Comparison

    The same engine, three front ends

    It is worth stating plainly that these are not three competing technologies. All three load GGUF model files and produce tokens. Ollama and LM Studio both build on the same inference foundation that llama.cpp provides, and they differ in packaging. That means:

    • The model files are interchangeable. A GGUF you use in one runs in the others. You are not choosing a model ecosystem, only a way to drive it.
    • The differences are in control, convenience and interface. llama.cpp exposes everything as flags. Ollama hides it behind a CLI and an API. LM Studio hides it behind a graphical window.
    • Speed differences are real but secondary. The engine is shared, so the gaps are in overhead and defaults, not in some deep architectural advantage. On a CPU box the direct llama.cpp path is the most efficient; the wrappers are close behind and the difference rarely matters compared to model choice.

    llama.cpp: control and pure-CPU performance

    llama.cpp is the bare engine you build and drive yourself. You build it once from source, then run a model with explicit flags for context, threads and host. What you get in return is the most direct path to the hardware and the best pure-CPU numbers. On the lab box we benchmarked a 4.65B model at Q4_K with four threads and measured about 48 tokens per second processing a 512-token prompt and about 14 tokens per second generating. Those are honest CPU figures for a modest box, and they are what you get when nothing sits between you and the engine.

    The cost is that there is no hand-holding: you find the model file yourself, you manage it, you set every parameter by hand, and the “server” is a process you start with a command. This is the right choice when you want to tune context length and threads, when you are on a CPU box where every token per second counts, or when you want to understand exactly what is running. It is the least friendly option, and the most capable one.

    Ollama: the low-maintenance default

    Ollama wraps the same engine in a single install and a tiny CLI, and adds a model registry that removes the “find the right file” step. ollama pull gets you a verified model; ollama run talks to it; and an HTTP API on port 11434 (plus an OpenAI-compatible endpoint) means every chat app and script can use it without custom code. On the lab box we pulled a 0.6B model at Q4_K_M (a 522 MB file, verified on download) and measured token generation at roughly 49 to 52 tokens per second and prompt processing at roughly 140 to 235 tokens per second. For a model that small those are “instant” numbers, and the point is less the raw speed than how little stood between us and a working answer.

    This is the best default for a home server: it installs cleanly, it is scriptable, it is what most third-party tools assume, and it stays out of your way. The trade-offs are that the registry is a curated list (a very specific self-downloaded file is imported rather than pulled by name), and it is a little less tunable than raw llama.cpp. For most people on a server, that trade is the right one.

    LM Studio: the friendliest desktop experience

    LM Studio is a graphical desktop app for macOS, Windows and Linux. You browse a model catalogue, download with a click, chat in a window, and adjust parameters with sliders. It is the fastest way to “have local AI on my computer today” with zero terminal, and the parameter sliders make experimenting with model behavior genuinely easy. It also serves the loaded model on port 1234 as an OpenAI-compatible API, so it can do the server job too. We have not screenshotted the GUI in this series because the lab box is headless, so treat the desktop specifics as the documented behavior; the parts that matter on a server — the port 1234 server and the OpenAI-compatible API — are the documented and verifiable ones.

    Where LM Studio gives ground is that it is a GUI app, so it is the wrong shape for an always-on headless server, and its management layer adds a little overhead compared to a bare command-line runtime. It is the best on-ramp and the best place to discover which models you like, and the natural next step from it is to hand the same GGUF file to a headless runtime for production. There is no lock-in, because the model format is shared.

    Side by side

    Summarizing what matters in a decision:

    • Setup. llama.cpp: build from source, manage files yourself. Ollama: one install script, one pull command. LM Studio: install an app, click to download. From most to least effort: llama.cpp, Ollama, LM Studio.
    • Interface. llama.cpp: terminal and flags. Ollama: terminal CLI plus HTTP API. LM Studio: graphical window plus optional HTTP server.
    • Model management. llama.cpp: you source and store the files. Ollama: curated registry plus import. LM Studio: in-app catalogue that stores models for you.
    • Control and tuning. llama.cpp: full (every flag is yours). Ollama: good (API and some options). LM Studio: good via sliders, less under the hood.
    • Best on CPU speed. llama.cpp is the most direct and measured the cleanest CPU numbers in the lab; the others are close.
    • Best for a headless server. Ollama, for the combination of easy install, scriptability and a standard API. llama.cpp if you want maximum control.
    • Best for a desktop / first time. LM Studio.

    Which one should you pick

    Match the tool to the situation rather than picking a “best” in the abstract:

    • You have a CPU box and you want the most performance with your hands on the controls: llama.cpp. Build it, load your model, set threads to your core count, and benchmark. It is the most capable and the least hand-holding.
    • You have a home server and you want a local model that is easy to install, easy to script, and friendly to the tools you already use: Ollama. It is the default for a reason, and it is what a chat front end like Open WebUI expects.
    • You are on a desktop and you want to try local AI now, with a window and no terminal: LM Studio. It is the friendliest, and it is the best place to learn which models and quantizations you actually prefer before committing to a server setup.

    And because the model files are the same GGUF across all three, you can start with the friendliest one and move to the more capable one without losing anything. A common path is to learn on LM Studio, then run the model you settled on with Ollama on the server, and reach for llama.cpp only when you need to tune or squeeze. The decision is about how you want to work, and the model you run is independent of that choice.

    Common mistakes

    Picking based on benchmarks you read rather than your own hardware. Published speed numbers depend on CPU, RAM, GPU and threads in ways that do not transfer. Run the benchmark on your box with the model you care about — llama.cpp’s benchmark tool does this directly, and Ollama reports timing in its API — and decide on your own numbers.

    Thinking you are locking yourself into a model ecosystem. You are not. The GGUF file is the constant; the runtime is swappable. If a tool stops fitting how you work, move the same model file to another one.

    Over-engineering the first setup. The fastest path to a useful local model is the least-friction tool you will actually keep using. Start with the one that matches your comfort (often Ollama on a server, LM Studio on a desktop), get one real answer back, and only then optimize toward llama.cpp if the speed or control genuinely requires it.

    How this fits the rest of your home server

    Whatever you pick here, the rest of the local AI stack is identical. The model is a GGUF file chosen by the size-and-quantization logic, the front end is a chat UI like Open WebUI, the security story is “keep the port private and reach it over your VPN” (the Tailscale guide), and the box you are running it on is the one you chose in the hardware guide. The runtime is the one swappable layer in the whole thing, and because it sits on top of a shared model format, the choice is a preference, not a commitment. Pick the front end that matches how you work, run a model you measured on your own hardware, and put a chat window in front of it — that is the whole stack, and the runtime is the only part you get to change your mind about freely.

    Tested on:

    OSDebian 12
    Hardware4-core / 16 GB, no GPU
    llama.cpp (4.65B Q4_K, 4 threads)48.4 t/s prompt / 13.6 t/s generation
    Ollama v0.34.0 (qwen3:0.6b Q4_K_M)~49-52 t/s generation

    Last tested: 15 September 2026

    What’s next?

    The natural next steps from this guide:

  • Ollama: Install and Run a Local LLM in 5 Minutes

    Ollama: Install and Run a Local LLM in 5 Minutes

    Ollama is the fastest way from “I have a server” to “I have a working local model”. One install script, one command to pull a model from its registry, one command to run it — and you get a model you can talk to from the terminal, plus an HTTP API that every chat app and script can use. It wraps the same inference engine that powers the rest of the local AI world, so it is not a toy or a separate technology; it is that engine with a friendly front end. This guide installs it, pulls a model, runs it, measures it, and covers the one behavior that trips people up on the newer thinking models. Everything was done on the lab box: a 4-core Intel i5-6500T, 16 GB of RAM, Debian 12, no discrete GPU.

    Beginner · 10 min · CLI

    What Ollama actually is

    Ollama is a small program with three parts working together:

    • A server that stays running in the background, holds the loaded models in memory, and answers requests. You usually start it once and forget it.
    • A CLI (ollama) that talks to that server. ollama pull, ollama run, ollama list, ollama ps. This is what you type.
    • An HTTP API on localhost:11434 with both its own native endpoints and an OpenAI-compatible one, so existing OpenAI clients work with no changes.

    The model registry is the part that makes it feel effortless. Instead of hunting for a file and checking it matches your hardware, ollama pull qwen3:0.6b downloads the right file and verifies it. The trade-off for that convenience is that the registry is a curated list, so if you want a very specific model file you downloaded yourself, you import it rather than pull it by name.

    Installing it

    On the lab box we installed a specific release (v0.34.0) by downloading the binary distribution and running the server directly, which is the same shape as the official install but without needing root for the whole thing. The official one-liner does this for you:

    curl -fsSL https://ollama.com/install.sh | sh

    If you are running as a normal user without the rights the installer wants (as we were in the lab), download the release tarball for your platform, extract it into a folder of your own, and run the server binary directly:

    OLLAMA_HOST=127.0.0.1:11434 ./bin/ollama serve

    The OLLAMA_HOST variable is the one worth knowing. By default the server listens on 127.0.0.1, which is exactly what you want on a private server — nothing outside the machine can reach it. Set it to 0.0.0.0 only if you deliberately want the rest of your network to reach the API, and then you should be putting it behind your VPN rather than exposing it. We confirmed our server was answering {"version":"0.34.0"} on its version endpoint before doing anything else.

    Pulling and running a model

    Once the server is up, pulling a model is one command. In the lab we pulled a small, fast model to prove the pipeline:

    ollama pull qwen3:0.6b

    This downloaded a 522 MB model (a 0.6B-parameter model at Q4_K_M) and verified its checksum — the pull finished in under a minute on the lab connection. After it completes, ollama list shows it with its size, and you can run it interactively:

    ollama run qwen3:0.6b "What is the capital of France?"

    That is the whole “I have a local model” moment: type a question in the terminal, get an answer from a model running on your own hardware. For scripting, the same model is reachable over the API:

    curl http://localhost:11434/api/generate -d '{
      "model": "qwen3:0.6b",
      "prompt": "Say hello",
      "stream": false
    }'

    And for any client written against the OpenAI API, the /v1/chat/completions endpoint behaves the same way, which is what makes Ollama the default assumption for third-party chat apps.

    Measuring it

    Ollama reports timing in the API response, so you get the real numbers without a separate benchmark tool. On the lab box, a chat request against the 0.6B model came back with the response text, the tokens generated, and the timing for both reading the prompt and generating the answer. What we measured:

    • Token generation: roughly 49 to 52 tokens per second. That is the answer-writing speed, and at that rate a normal-length reply streams back in well under a second. For a 0.6B model on a 4-core CPU with no GPU, that is comfortably in “instant” territory.
    • Prompt processing: roughly 140 to 235 tokens per second depending on the run, which is the speed at which it reads your input back. In practice that is fast enough that you will not notice it for normal prompts.

    These are small-model numbers, and that is the point of starting small: you get an immediate, pleasant experience that proves the whole setup works, before you spend time on a bigger model that is slower to load and slower to answer. When you move to a larger model, watch the generation rate in the response and decide against that baseline whether the extra intelligence is worth the extra wait.

    The thinking-model gotcha

    This is the one that cost us real debugging time in the lab, and it is worth knowing before it confuses you. A number of newer models — the Qwen3 family is a good example — are “thinking” models: before they produce the final answer, they generate an internal chain of reasoning. Ollama returns that reasoning in its own field, separate from the final answer. The practical consequence is that if you read only the main answer field and that field is short or empty, it can look like the model failed to respond at all, when in fact it did its work in the reasoning field and then gave a one-word answer.

    In the lab, a request to a thinking model returned its reasoning (a few hundred characters of “let me work this out…”) in the separate field and a short final answer in the main field. Two things follow from this. First, it is a model behavior, not an Ollama bug — the server did exactly what the model told it to. Second, if you are writing a client, read the full response, not just the primary content field, or you will occasionally see “empty” answers that are actually complete. And because thinking burns tokens on reasoning, a thinking model with a tight token limit can spend its whole budget thinking and return little or no final answer — raise the limit if you see that pattern.

    Keeping it running and keeping it private

    On a server you want Ollama running as a service so it survives a reboot, and you want its model store on a volume that survives a reinstall. In the lab the model store lived in a dedicated folder, and the whole thing fit on the same NVMe drive as the rest of the stack — a model or two is a few gigabytes, not a storage event. For the “I want it as a container” setup, which is the most reproducible way to run it alongside a chat UI, the official Ollama image does exactly this: a container for the runtime, a volume for the models, and the API on the standard port. That two-container pattern (Ollama plus a chat front end) is what we ran end to end in the lab, and it is covered in the Open WebUI guide. For reaching the UI from your phone or laptop without opening a port, the Tailscale in Docker guide is the clean path, and the security guide covers why the API should stay on loopback or a private network by default.

    Common gotchas

    The CLI says it cannot connect to a running Ollama. The server and the CLI are two separate processes, and the CLI only works while the server is running and on the host it expects. If you started the server with a custom OLLAMA_HOST, the CLI needs to know the same address. In the lab this showed up whenever the background server had been restarted without the host variable set. Check the server is actually up first; it is the more common cause than a configuration mismatch.

    A pull is slow or stalls. Model files are large, and the registry is a public service, so pull speed is whatever the internet is giving you. A stalled pull is usually a network hiccup, and re-running the same pull resumes rather than starting over. If you are on a slow line, a smaller quantization is the real fix, not patience.

    The model is in the list but the first request is very slow. The first request after a model has been idle loads its weights into memory, which takes a moment; subsequent requests are fast. This is normal, not a fault. If every request is slow, the model is too big for the box and it is swapping — see the size-and-quantization guide for the memory math.

    Your script gets an empty answer from a thinking model. Covered above, but it is the most likely thing to look like a bug when it is not. Read the full response including the reasoning field, and raise the token limit if the model is burning its budget on reasoning.

    How this fits the rest of your home server

    Ollama is the “set it and forget it” option in the local AI stack: the least fiddly install, the easiest model management, and an API that the rest of your tools already understand. It is the right default for most home servers, and the right thing to put a chat interface in front of. If you want to squeeze more out of a CPU box or you want your hands on the engine, the llama.cpp guide is the deeper route; if you are working on a desktop with a screen, LM Studio is the friendlier one. Whichever runtime you pick, the natural next step is a proper chat window that the whole house can use — the Open WebUI guide — and a bit of monitoring so a loaded model does not quietly take RAM from the services it shares the box with.

    Tested on:

    OSDebian 12
    Hardware4-core / 16 GB
    Ollamav0.34.0
    Modelqwen3:0.6b (Q4_K_M, 522 MB, verified on pull)
    Measured speed~49-52 t/s generation / ~140-235 t/s prompt

    Last tested: 15 September 2026

    What’s next?

    The natural next steps from this guide: