Ollama in production: what changes after the first start
Deploying Ollama takes a few minutes. Running it reliably over time takes more attention. In production, three points concentrate most of the problems: model management (which to load, which to remove to free disk space), the API attack surface (unauthenticated by default on port 11434), and memory usage (an oversized model saturates RAM and gets killed by the kernel). This guide assumes the ollama container is already running and focuses on these three areas, plus integration with your stack tools.
What advanced management brings in practice
- Selective pull — you download only the model you need, without filling the disk with unused variants.
- Clean removal —
ollama rmfrees disk space and reduces the load time of remaining models. - Documented REST API — Ollama exposes
/api/generate,/api/chatand/v1/chat/completions; a reverse proxy in front gives an HTTPS endpoint with authentication. - Controlled concurrency —
OLLAMA_MAX_LOADED_MODELSprevents several models from loading simultaneously and exhausting the RAM. - Persistent environment variables —
OLLAMA_KEEP_ALIVE,OLLAMA_NUM_THREADSandOLLAMA_CONTEXT_SIZEare injected into thedocker runor in a versionedcompose.yml. - Scriptable model rotation — a simple
curlcall to/api/pullis enough to automate model updates from a CI pipeline. - Selective exposure — you can expose the API only to your internal tools (Open WebUI, n8n, LangFlow) without making it public.
Choosing and managing models: size, RAM and quantization
A model's size is expressed in billions of parameters (B) and determines the RAM required. A 1B/3B model fits in 2 to 3 GB and suits simple tasks (classification, short summary) on a modest VPS. A 7B/8B requires 5 to 6 GB in Q4: this is the most common quality/resource ratio. A 13B needs 9 to 10 GB, and a 70B exceeds 40 GB — reserved for high-memory VPS or GPU configurations. For each size, quantization adjusts the quality/speed trade-off: Q4_K_M offers a good quality/speed balance on CPU, Q8 preserves more precision at the cost of doubled RAM. Before pulling a model, check free space with df -h and available RAM with free -h.
Common operations: pull, removal and API exposure
List available models
Run docker exec ollama ollama list to see already downloaded models, their disk size and the date they were added.
Download a new model
Run docker exec ollama ollama pull llama3.2:3b for a lightweight model, or docker exec ollama ollama pull qwen2.5:7b-instruct-q4_K_M for a quantized 7B. The q4_K_M suffix specifies the quantization directly in the tag.
Remove an old model
Free up space with docker exec ollama ollama rm llama3.1:8b. Verify afterwards with docker exec ollama ollama list that the model no longer appears.
Test the REST API locally
Call the chat endpoint: curl http://127.0.0.1:11434/api/chat -d '{"model":"qwen2.5:7b-instruct-q4_K_M","messages":[{"role":"user","content":"Ping"}],"stream":false}'. The JSON response contains the message.content field.
Configure environment variables
Restart the container with the desired options: docker run -d -v ollama:/root/.ollama -p 127.0.0.1:11434:11434 -e OLLAMA_KEEP_ALIVE=-1 -e OLLAMA_MAX_LOADED_MODELS=1 -e OLLAMA_NUM_THREADS=4 --name ollama ollama/ollama. These parameters keep the model in memory and limit CPU load.
Apply a rate-limit via nginx
In your nginx server block, add limit_req_zone $binary_remote_addr zone=ollama:10m rate=10r/m; in the http section, then limit_req zone=ollama burst=5 nodelay; in the location. This protects the API from repeated burst calls.
Update Ollama itself
Stop and remove the container: docker stop ollama && docker rm ollama. Pull the new image: docker pull ollama/ollama. Restart with the same parameters. Models are stored in the ollama volume and are not affected.
Check service health
Run curl http://127.0.0.1:11434/api/tags to get the list of loaded models. An HTTP 200 with valid JSON confirms the service is responding correctly.
Ollama behind an nginx reverse proxy with a token
By default, Ollama listens on 127.0.0.1:11434 without authentication. To expose it to your tools (Open WebUI, n8n, a remote script), place nginx as a front end with a Bearer token. The configuration block below delegates access to a secret token defined in the $api_token variable, checks the Authorization header and proxies to Ollama. CORS is configured to accept requests from your interface without exposing the API to all origins.
In /etc/nginx/sites-available/ollama:
map $http_authorization $api_token_valid {
default 0;
"Bearer YOUR_SECRET_TOKEN" 1;
}
server {
listen 443 ssl;
server_name api-ia.your-domain.com;
ssl_certificate /etc/letsencrypt/live/api-ia.your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api-ia.your-domain.com/privkey.pem;
location / {
if ($api_token_valid = 0) { return 401; }
proxy_pass http://127.0.0.1:11434;
proxy_set_header Host $host;
add_header Access-Control-Allow-Origin "https://ui.your-domain.com";
}
}Activate with ln -s /etc/nginx/sites-available/ollama /etc/nginx/sites-enabled/ then nginx -t && systemctl reload nginx.
CPU performance: choosing the right quantization
On CPU, Q4_K_M is the recommended balance point: marginal quality loss compared to Q8, with approximately 40% faster generation speed and half the memory usage. Reserve Q8 for cases where precision is critical (code, formal logic) and your VPS has at least 16 GB of free RAM. Adjust OLLAMA_NUM_THREADS to the number of physical cores (not logical) to avoid contention: on a 4 vCPU VPS, start at 3. The OLLAMA_CONTEXT_SIZE parameter (default: 2048 tokens) directly affects RAM per request; reduce it if you handle many short calls in parallel.
Troubleshooting: the most common cases
Four situations come up regularly in production.
Model too slow. Generation exceeds 2-3 tokens per second on CPU for a 7B? Check that OLLAMA_NUM_THREADS is not at 1 (default if not set on some images). Also check that only one model is loaded (OLLAMA_MAX_LOADED_MODELS=1): two simultaneous models compete for cores and memory bandwidth.
Insufficient VRAM (GPU). If the Docker log shows CUDA out of memory or ROCm error, the model does not fit in VRAM. Switch to the q4_K_M tag or reduce OLLAMA_CONTEXT_SIZE. Ollama falls back to CPU if VRAM is insufficient, but without clearly indicating it: compare generation speeds to detect this.
API connection refused. curl: (7) Failed to connect from outside while the service is listening? The firewall is blocking port 11434, or nginx is not started. Check with ss -tlnp | grep 11434 (should show 127.0.0.1, not 0.0.0.0) and systemctl status nginx.
Signal killed / OOM. The process is killed by the kernel (OOM killer). The VPS RAM is insufficient for the selected model. Switch to a smaller size or enable a 4 to 8 GB swap as a buffer: fallocate -l 4G /swapfile && chmod 600 /swapfile && mkswap /swapfile && swapon /swapfile. Swap slows generation but avoids brutal stops.
Integration with other VPS tools
Ollama is a backend: it takes its full value when other services connect to it. Three tools integrate naturally on the same VPS.
Open WebUI exposes a conversation interface similar to ChatGPT, connected to the local Ollama API. In its environment file, set OLLAMA_BASE_URL=http://ollama:11434 (if both containers share a Docker network) or OLLAMA_BASE_URL=http://127.0.0.1:11434 if Open WebUI runs on the same host. Open WebUI handles model selection, conversation history and user management. Note: the Ollama ↔ Open WebUI coupling exposes an additional attack surface — see the CVE-2026-45672 section below.
LangFlow is a visual LLM pipeline builder. Add an Ollama node to your flow, enter http://127.0.0.1:11434 as the base URL and select the model from the dropdown. LangFlow calls the /api/generate endpoint directly without internal authentication — place it on the VPS private network, not exposed publicly.
n8n lets you trigger Ollama calls from an automation workflow. Use the HTTP Request node pointing to http://127.0.0.1:11434/api/chat with a JSON body containing model and messages. From n8n, you can chain an Ollama call to a data retrieval step, email send or outgoing webhook without writing code.
CVE-2026-45672: authorization bypass in Open WebUI
Published on May 21, 2026 (GHSA-482j-2pq6-q5w4), this vulnerability affects all versions of Open WebUI prior to 0.8.12. CVSS score: 8.8 (high).
Attack mechanics. An authenticated user can execute arbitrary Python code via the /api/v1/utils/code/execute endpoint, even if the administrator has disabled code execution in settings (ENABLE_CODE_EXECUTION=false). The guard is declared in the configuration but is never enforced at the API layer: any verified account on the instance can trigger execution.
Impact. The attacker gains access to the underlying Jupyter backend and can read arbitrary files on the VPS, steal secrets (API keys, Ollama Bearer token, environment variables), or establish persistence. The confidentiality, integrity and availability of the server are compromised.
Why this is critical in an Ollama ↔ Open WebUI coupling. Ollama and Open WebUI often run on the same VPS, sometimes in the same Docker network, with shared secrets (fallback OpenAI API key, Ollama API Bearer token). An RCE on Open WebUI therefore gives direct access to the Ollama API and models in memory, bypassing the reverse proxy entirely.
Fix. Update Open WebUI to version 0.8.12 or later. This version enforces the ENABLE_CODE_EXECUTION check at the API endpoint level, where it should always have been.
Check your version. From the container: docker exec open-webui cat /app/package.json | grep '"version"'. If the output is below 0.8.12, the update is urgent: docker pull ghcr.io/open-webui/open-webui:main && docker stop open-webui && docker rm open-webui then restart with the same environment parameters.
Hardening the Ollama ↔ Open WebUI coupling after CVE-2026-45672
Four additional measures to apply after updating to 0.8.12.
1. Isolate Docker networks. Create a dedicated bridge network (docker network create llm-private) and place both containers on it. Ollama is then only reachable from Open WebUI via the service name (http://ollama:11434), without going through the VPS public interface.
2. Never expose port 11434 externally. Confirm the binding stays on 127.0.0.1:11434. On the internal Docker network, Ollama responds on port 11434 without authentication — this is acceptable if the network is private; it becomes a vector as soon as it is accessible from outside.
3. Disable code execution if you do not need it. In Open WebUI environment variables, set ENABLE_CODE_EXECUTION=false. After updating to 0.8.12, this setting is finally enforced at the API level. If your use case does not include code execution, disable it as a defense-in-depth measure.
4. Restrict registrations. In the Open WebUI admin interface (Settings → Administration), disable public sign-ups (ENABLE_SIGNUP=false) if the instance is exposed to the Internet. CVE-2026-45672 requires a verified account: reducing the sign-up surface reduces the attack surface.