Ollama + Open WebUI Avançado 2026: WSL2, GPU, HTTPS e RBAC
Ollama Open WebUI LLM local Docker Compose NVIDIA CUDA WSL2 GPU passthrough Cloudflare Tunnel RBAC backup troubleshooting Nemotron Qwen Llama Mistral DeepSeek Claude Code Continue.dev IA local AI sysadmin developer | ✎ Duarte Spínola | 2026-06-15
O artigo Ollama + Open WebUI cobriu a instalação básica — o docker-compose.yml, o download do NVIDIA Nemotron-3-Nano 30B, e os primeiros passos. Este artigo é o guia avançado para sysadmins e developers que já têm o stack a correr e precisam de o operar em produção: catálogo de 12+ modelos (Qwen 2.5/3, Llama 3.3, DeepSeek-R1, Mistral, Phi-4, Gemma 3, Granite 3) com VRAM e janela de contexto, tuning de performance (num_ctx, num_gpu, kv_cache_type, flash_attention), GPU passthrough em WSL2, HTTPS via Cloudflare Tunnel, multi-utilizador com RBAC (admin, user, grupos, ACLs), backup de modelos e DB (24GB+ por modelo), troubleshooting dos 8 problemas mais comuns, e integração com Claude Code / Continue.dev para usar Ollama como backend de coding assistants. Foco em PMEs, equipas de developers, e researchers AI que precisam de IA local sem custos de API e com privacidade total (dados nunca saem da máquina).
Conteúdos
- 1. 1. O que Está a Acontecer — Ollama 0.5+, Open WebUI 0.4+, e o Ecossistema de IA Local em 2026
- 2. 2. Cenários em que este setup avançado se aplica
- 3. 3. Catálogo de Modelos 2026 — Qual Modelo Para Que Caso
- 4. 4. Tuning de Performance — Os 8 Parâmetros que Mais Importam
- 5. 5. GPU Passthrough em WSL2 (Windows 11 24H2+)
- 6. 6. HTTPS com Cloudflare Tunnel (Expor Open WebUI com Segurança)
- 7. 7. Multi-Utilizador com RBAC (Open WebUI Admin Panel)
- 8. 8. Backup e Recuperação (Modelos + DB + Volumes)
- 9. 9. Troubleshooting — Os 8 Problemas Mais Comuns
- 10. 10. Integração com Coding Assistants (Claude Code, Continue.dev, Roo Code)
- 11. 11. FAQ para Sysadmins e Developers
- 12. 12. Outras Causas Comuns de Problemas em Operação
- 13. 13. Como Evitar Problemas — Boas-Práticas de Operação
- 14. 14. Anexos
1. O que Está a Acontecer — Ollama 0.5+, Open WebUI 0.4+, e o Ecossistema de IA Local em 2026
O ano de 2025-2026 foi de maturação explosiva para IA local. O Ollama atingiu 0.5.x com suporte estável a vision models, function calling, structured outputs (JSON mode), e embeddings; o Open WebUI atingiu 0.4+ com RAG (Retrieval-Augmented Generation) nativo, web search integrado, e RBAC empresarial. Os modelos open-weight passaram de “alternativa fraca ao GPT-4” para “competitivos ou superiores em tarefas específicas” (Tabela 1.1).
Tabela 1.1 — Marcos do Ecossistema IA Local (2024-2026)
| Marco | Data | Impacto |
|---|---|---|
| Llama 3.1 405B (Meta) | Jul 2024 | Primeiro modelo open-weight >400B; compete com GPT-4o em benchmarks |
| Qwen 2.5 72B (Alibaba) | Set 2024 | Melhor modelo bilingue EN/ZH; bate Llama 3.1 70B |
| DeepSeek-R1 (DeepSeek) | Jan 2025 | Reasoning model open-weight; compete com OpenAI o1 |
| Open WebUI 0.3 | Mar 2025 | RAG nativo com PDFs, URLs, YouTube transcripts |
| Nemotron-3-Nano 30B (NVIDIA) | Mar 2025 | MoE 30B/3.5B ativos; corre em 24GB VRAM |
| Phi-4 14B (Microsoft) | Dez 2024 | 14B parâmetros; bate GPT-4o em matemática |
| Gemma 3 27B (Google) | Mar 2025 | Modelo pequeno, alta qualidade; corre em 16GB VRAM |
| Ollama 0.5 | Jan 2026 | Vision models, function calling estável, JSON mode |
| Open WebUI 0.4 | Mar 2026 | Web search integrado, multi-modal (imagens, audio) |
| Granite 3.1 8B (IBM) | Dez 2024 | Otimizado para enterprise; licença Apache 2.0 |
Para contextualizar: o Ollama é o runtime de inferência (gera texto a partir de modelos), enquanto o Open WebUI é a interface web que oferece chat, RAG, gestão de utilizadores, e API compatível com OpenAI. Juntos formam um stack equivalente a ChatGPT, mas 100% local e privado. As fontes principais para este artigo são a documentação oficial do Ollama, o Open WebUI Docs, e os model cards no Hugging Face.
2. Cenários em que este setup avançado se aplica
Nem toda a equipa precisa deste nível de configuração. Os cenários típicos onde o stack avançado Ollama + Open WebUI justifica o investimento em hardware e tempo de configuração são:
- Equipas de development (5-25 pessoas) — querem um assistente de código local sem enviar código-fonte para APIs externas; usam Ollama como backend de Continue.dev ou Claude Code.
- Researchers e universidades — processam dados sensíveis (médicos, financeiros, jurídicos) que não podem sair da infraestrutura institucional por razões de compliance (GDPR, HIPAA, ética).
- PMEs com custos de API elevados — a fatura mensal de OpenAI/Anthropic ultrapassa os 200-500€/mês e justifica investir numa GPU local que se paga em 3-6 meses.
- Ambientes air-gapped / offline — fábricas, navios, datacenters sem internet; o Ollama funciona 100% offline após o download inicial dos modelos.
- Prototipagem e fine-tuning — developers que querem testar prompts, RAG pipelines, ou fine-tuning antes de ir para produção em APIs comerciais.
- Consultórios e gabinetes profissionais — advogados, contabilistas, médicos que precisam de analisar documentos confidenciais com IA sem violar o sigilo profissional.
A tabela seguinte resume os requisitos de hardware por dimensão de equipa — detalhada na secção 13 com recomendações de GPU, CPU, e RAM específicas:
| Tamanho de Equipa | GPU Recomendada | Modelo Máximo | Investimento |
|---|---|---|---|
| 1-5 pessoas | RTX 4060 16GB / RTX 3060 12GB | Llama 3.3 8B, Phi-4 14B (Q4) | 350-600€ |
| 5-25 pessoas | RTX 4090 24GB / 2x RTX 3090 | Qwen 2.5 32B, Nemotron 30B, DeepSeek-R1 32B | 1.500-2.500€ |
| 25-100 pessoas | 2x RTX 4090 / RTX 6000 Ada 48GB | Qwen 2.5 72B (Q4), Llama 3.3 70B (Q3) | 5.000-10.000€ |
3. Catálogo de Modelos 2026 — Qual Modelo Para Que Caso
O catálogo de modelos open-weight evoluiu rapidamente. Em meados de 2026, os modelos abaixo são os mais relevantes para uso local com Ollama. A tabela 3.1 mostra os parâmetros, VRAM necessária (em quantização Q4_K_M), e licença de cada modelo.
Tabela 3.1 — Modelos Open-Weight Disponíveis no Ollama (2026)
| Modelo | Parâmetros | VRAM (Q4_K_M) | Contexto | Licença |
|---|---|---|---|---|
| Llama 3.3 70B | 70B | ~40GB | 128K | Llama 3.3 Community |
| Llama 3.2 3B | 3B | ~2.5GB | 128K | Llama 3.2 Community |
| Qwen 2.5 72B | 72B | ~42GB | 128K | Apache 2.0 (até 70B) |
| Qwen 2.5 32B | 32B | ~20GB | 128K | Apache 2.0 |
| Qwen 2.5 7B | 7B | ~5GB | 128K | Apache 2.0 |
| DeepSeek-R1 32B | 32B (reasoning) | ~20GB | 128K | MIT |
| DeepSeek-R1 14B | 14B (reasoning) | ~9GB | 128K | MIT |
| Mistral Small 24B | 24B | ~14GB | 128K | Mistral Research |
| Phi-4 14B | 14B | ~9GB | 16K | MIT |
| Gemma 3 27B | 27B | ~16GB | 128K | Gemma Terms of Use |
| Granite 3.1 8B | 8B | ~5GB | 128K | Apache 2.0 |
| Nemotron-3-Nano 30B | 30B (MoE 3.5B ativos) | ~18GB | 128K | NVIDIA Open Model |
Para descarregar um modelo com Ollama basta um comando. Os modelos são armazenados em ~/.ollama/models (Linux) ou no volume Docker configurado:
# Descarregar modelos (o primeiro download pode demorar 10-30 min)
ollama pull llama3.3:70b # ~40GB, precisa de 2x RTX 4090
ollama pull qwen2.5:32b # ~20GB, corre em 1x RTX 4090
ollama pull deepseek-r1:32b # reasoning model, ~20GB
ollama pull phi4:14b # ~9GB, excelente para matemática
ollama pull gemma3:27b # ~16GB, ótimo compromisso
ollama pull mistral-small:24b # ~14GB, bom para coding
ollama pull granite3.1:8b # ~5GB, ideal para CPU-only
# Listar modelos instalados
ollama list
# Remover um modelo (liberta disco)
ollama rm llama3.2:3b
4. Tuning de Performance — Os 8 Parâmetros que Mais Importam
A diferença entre Ollama “aceitável” e Ollama “rápido” está nos parâmetros de runtime. Ollama usa llama.cpp por baixo, e expõe os parâmetros mais importantes via Modelfile ou via API. Os 8 parâmetros seguintes são os que mais impactam tokens/segundo, latência, e consumo de VRAM:
4.1. Quantização e Formato GGUF
O formato GGUF (GPT-Generated Unified Format) é o padrão do ecossistema Ollama/llama.cpp. Permite carregar modelos quantizados — ou seja, com pesos representados em menos bits (4-bit, 5-bit, 8-bit) em vez de 16-bit (FP16). A quantização reduz VRAM e disco em 2x a 4x, com perda mínima de qualidade:
| Quantização | Bits/Peso | VRAM vs FP16 | Perda de Qualidade |
|---|---|---|---|
| Q8_0 | 8-bit | ~50% do FP16 | ~1% (praticamente impercetível) |
| Q5_K_M | 5-bit | ~33% do FP16 | ~2-3% |
| Q4_K_M | 4-bit | ~28% do FP16 | ~3-5% (padrão recomendado) |
| Q3_K_M | 3-bit | ~22% do FP16 | ~5-8% (aceitável para modelos 70B+) |
4.2. Os 8 Parâmetros de Runtime
# Modelfile personalizado para tuning de performance
# Criar com: ollama create meu-modelo -f Modelfile
FROM qwen2.5:32b
# 1. num_ctx — janela de contexto (padrão: 2048, demasiado curto!)
# Aumentar para 8192 ou 16384 conforme necessário. Cada 2K tokens = ~0.5GB extra de VRAM
PARAMETER num_ctx 8192
# 2. num_gpu — camadas offloaded para GPU (padrão: auto)
# Definir como -1 para offload total (tudo na GPU) ou um número específico
PARAMETER num_gpu -1
# 3. flash_attention — ativa Flash Attention (reduz VRAM e aumenta velocidade)
# Requer modelos com formato GGUF recente (>= 2024)
PARAMETER flash_attention true
# 4. kv_cache_type — tipo de cache KV (q8_0 reduz VRAM em ~50% com perda mínima)
PARAMETER kv_cache_type q8_0
# 5. num_thread — threads de CPU (para a parte não-GPU)
# Recomendado = número de cores físicos (não lógicos/hyperthread)
PARAMETER num_thread 8
# 6. temperature — criatividade (0 = determinístico, 1 = criativo)
PARAMETER temperature 0.7
# 7. top_p — nucleus sampling (0.9 = equilibrado, 1.0 = desligado)
PARAMETER top_p 0.9
# 8. num_predict — máximo de tokens a gerar (padrão: 128, demasiado curto!)
PARAMETER num_predict 4096
num_ctx é o parâmetro mais subestimado. O padrão de 2048 tokens corta conversas a meio. Cada aumento de 2K tokens consome ~0.5GB de VRAM extra para o KV cache. Com kv_cache_type q8_0 podes reduzir esse consumo para metade.
flash_attention true pode dar +20-30% de velocidade em GPUs NVIDIA modernas (RTX 30/40/50 series). É a otimização com melhor ratio esforço/benefício — uma linha no Modelfile.
Após criar o Modelfile, aplica as definições e testa a velocidade:
# Criar modelo personalizado a partir do Modelfile
ollama create qwen-tuned -f Modelfile
# Testar com estatísticas de velocidade
ollama run qwen-tuned "Explica a diferença entre TCP e UDP em 3 parágrafos."
# Verificar se o modelo está a usar a GPU
ollama ps
# NAME SIZE PROCESSOR ENCODER DURATION
# qwen-tuned 20 GB 100% GPU ... ...
# Comparar tokens/segundo antes e depois do tuning
time ollama run qwen2.5:32b "Escreve um poema sobre Docker." --verbose
5. GPU Passthrough em WSL2 (Windows 11 24H2+)
Para utilizadores de Windows 11 24H2+, o WSL2 com GPU passthrough é a forma mais simples de correr Ollama com aceleração NVIDIA. O Windows 11 24H2 trouxe melhorias significativas no suporte a GPU no WSL2, incluindo CUDA 12.x nativo e melhor gestão de memória partilhada.
5.1. NVIDIA CUDA no WSL2
# No Windows PowerShell (como Administrador)
# 1. Instalar o driver NVIDIA para WSL2 (NÃO o driver Linux — o driver Windows normal já inclui suporte WSL2)
# Download de: https://www.nvidia.com/Download/index.aspx
# Escolher "GeForce" ou "RTX" conforme a tua GPU
# 2. Verificar que o WSL2 está atualizado
wsl --update
wsl --set-default-version 2
# 3. Dentro do WSL2 (Ubuntu 24.04)
# Verificar que a GPU é detetada
nvidia-smi
# Deve mostrar a tua GPU, driver version, e CUDA version
# 4. Instalar Ollama no WSL2
curl -fsSL https://ollama.com/install.sh | sh
# 5. Verificar que Ollama deteta a GPU
ollama ps
# O campo "PROCESSOR" deve mostrar "GPU" ou "100% GPU"
# 6. Testar velocidade
time ollama run llama3.2:3b "Olá, conta uma piada."
5.2. AMD ROCm no WSL2 (Alternativa)
Para GPUs AMD (RX 7900 XTX, RX 7800 XT), o ROCm é a alternativa ao CUDA. O suporte no WSL2 é mais recente e menos estável que o NVIDIA, mas funcional desde o Windows 11 23H2+ com ROCm 5.7+:
# No WSL2 (Ubuntu 24.04)
# Instalar ROCm
sudo apt update
sudo apt install -y rocm-dev
# Verificar deteção da GPU AMD
rocm-smi
# Deve listar a GPU AMD com memória VRAM
# Para Ollama usar ROCm, definir a variável de ambiente
export HSA_OVERRIDE_GFX_VERSION=11.0.0 # RX 7900 XTX
# Para RX 7800 XT: export HSA_OVERRIDE_GFX_VERSION=11.0.1
# Iniciar Ollama com ROCm
OLLAMA_ROCM_PATH=/opt/rocm ollama serve &
# Verificar utilização de GPU
ollama ps
HSA_OVERRIDE_GFX_VERSION mas sem garantias. Verifica a documentação oficial ROCm antes de comprar.
5.3. Docker com GPU Passthrough
Para correr Ollama em Docker com GPU, é necessário instalar o NVIDIA Container Toolkit:
# Instalar NVIDIA Container Toolkit (Ubuntu/Debian)
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \
| sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \
| sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \
| sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt update
sudo apt install -y nvidia-container-toolkit
# Configurar o runtime do Docker
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
# Testar que a GPU está acessível em Docker
docker run --rm --gpus all ubuntu nvidia-smi
6. HTTPS com Cloudflare Tunnel (Expor Open WebUI com Segurança)
Se precisares de aceder ao Open WebUI fora da rede local — para trabalho remoto, equipa distribuída, ou clientes — o Cloudflare Tunnel é a forma mais segura de expor o serviço sem abrir portas no router nem configurar VPNs. O tráfego é encriptado com HTTPS automático e protegido por Cloudflare Access (autenticação por email, SSO, ou IP whitelist).
6.1. Docker Compose Completo com Cloudflare Tunnel
# docker-compose.yml — Stack completo com Ollama + Open WebUI + Cloudflare Tunnel
services:
ollama:
image: ollama/ollama:latest
container_name: ollama
ports:
- "11434:11434"
volumes:
- ollama-models:/root/.ollama
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
restart: unless-stopped
open-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: open-webui
ports:
- "3000:8080"
environment:
- OLLAMA_BASE_URL=http://ollama:11434
- WEBUI_AUTH=true
- ENABLE_SIGNUP=false # desativar registo público
- DEFAULT_USER_ROLE=user # novos utilizadores como "user" (não admin)
volumes:
- open-webui-data:/app/backend/data
depends_on:
- ollama
restart: unless-stopped
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
command: tunnel run
environment:
- TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}
depends_on:
- open-webui
restart: unless-stopped
volumes:
ollama-models:
open-webui-data:
# .env file (NÃO commitar para git!)
CLOUDFLARE_TUNNEL_TOKEN=eyJhIjoi...copia_o_token_do_dashboard_cloudflare...
# Iniciar o stack completo
docker compose up -d
# Verificar que tudo está a correr
docker compose ps
# NAME STATUS PORTS
# ollama Up 0.0.0.0:11434->11434/tcp
# open-webui Up 0.0.0.0:3000->8080/tcp
# cloudflared Up
# Ver logs do Cloudflare Tunnel
docker compose logs cloudflared -f
# Se mostrar "Registered tunnel connection" = está a funcionar
No Cloudflare Zero Trust Dashboard, configura o túnel para apontar para http://open-webui:8080 (nome do serviço no Docker Compose). O Cloudflare gera automaticamente um certificado SSL válido para o domínio que escolheres (ex: ia.empresa.pt).
7. Multi-Utilizador com RBAC (Open WebUI Admin Panel)
O Open WebUI tem um sistema de RBAC (Role-Based Access Control) integrado com três níveis: admin, user, e pending. Para equipas, é essencial configurar corretamente os papéis e permissões antes de abrir o acesso.
7.1. Primeiros Passos: CLI e API REST do Ollama
Antes de configurar o Open WebUI, garante que o Ollama está acessível via API REST. A API do Ollama é compatível com OpenAI, o que permite usar qualquer cliente que suporte a OpenAI API:
# CLI Ollama — comandos básicos
ollama serve # iniciar o servidor (porta 11434)
ollama run llama3.3:70b # conversação interativa
ollama run qwen2.5:7b "Resumo em 2 frases: $(cat ficheiro.txt)"
ollama list # listar modelos instalados
ollama show qwen2.5:32b # mostrar detalhes do modelo
ollama ps # mostrar modelos carregados em memória
ollama stop qwen2.5:32b # descarregar modelo da memória
# API REST — endpoint /api/chat (compatível OpenAI)
curl http://localhost:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen2.5:32b",
"messages": [
{"role": "system", "content": "És um assistente técnico em português de Portugal."},
{"role": "user", "content": "Explica o que é RBAC em 3 frases."}
],
"temperature": 0.7,
"max_tokens": 500
}'
# API REST — endpoint nativo Ollama /api/chat (mais opções)
curl http://localhost:11434/api/chat \
-H "Content-Type: application/json" \
-d '{
"model": "qwen2.5:32b",
"messages": [
{"role": "user", "content": "Escreve uma função Python para validar NIF português."}
],
"stream": false,
"options": {
"num_ctx": 8192,
"temperature": 0.3
}
}' | jq .message.content
7.2. Configuração de RBAC no Open WebUI
No primeiro acesso ao Open WebUI (em http://localhost:3000), o primeiro utilizador criado torna-se automaticamente admin. A partir daí, a gestão de utilizadores faz-se no Admin Panel → Settings → Users:
| Papel | Permissões | Casos de Uso |
|---|---|---|
| admin | Gestão de utilizadores, modelos, RAG, configuração global | Sysadmin, IT lead |
| user | Chat, RAG pessoal, upload de documentos, criar modelos personalizados | Developers, researchers, utilizadores gerais |
| pending | Sem acesso até aprovação manual do admin | Novos registos quando ENABLE_SIGNUP=true |
# Variáveis de ambiente para RBAC no docker-compose.yml
environment:
- WEBUI_AUTH=true # ativar autenticação obrigatória
- ENABLE_SIGNUP=false # bloquear registo público (recomendado)
# Alternativa: permitir registo mas com aprovação manual
- ENABLE_SIGNUP=true
- DEFAULT_USER_ROLE=pending # novos utilizadores ficam "pending"
- USER_PERMISSIONS={"chat":{"file_upload":true,"web_search":false}}
# Para integrar com LDAP/Active Directory (Open WebUI 0.4+):
- ENABLE_LDAP=true
- LDAP_SERVER_URL=ldap://dc01.empresa.pt:389
- LDAP_BIND_DN=CN=svc_ollama,OU=ServiceAccounts,DC=empresa,DC=pt
- LDAP_BIND_PASSWORD=${LDAP_PASSWORD}
- LDAP_SEARCH_BASE=OU=Users,DC=empresa,DC=pt
- LDAP_SEARCH_FILTERS=(objectClass=user)
- LDAP_ATTRIBUTE_FOR_MAIL=mail
- LDAP_ATTRIBUTE_FOR_USERNAME=sAMAccountName
8. Backup e Recuperação (Modelos + DB + Volumes)
O backup do stack Ollama + Open WebUI tem três componentes: modelos (ficheiros GGUF em ~/.ollama/models), base de dados do Open WebUI (SQLite em /app/backend/data), e RAG (documentos e embeddings). Cada modelo ocupa 5-40GB; a DB do Open WebUI é tipicamente 10-500MB.
8.1. RAG Nativo: Documentos, PDFs e URLs
O Open WebUI tem RAG (Retrieval-Augmented Generation) nativo desde a versão 0.3. Podes fazer upload de PDFs, documentos, ou indicar URLs, e o sistema cria embeddings automaticamente usando um modelo de embedding (por padrão nomic-embed-text). Os documentos são armazenados numa base de dados vetorial (ChromaDB) integrada:
# Instalar modelo de embeddings no Ollama
ollama pull nomic-embed-text
# No Open WebUI Admin Panel → Settings → Documents:
# 1. Embedding Model: nomic-embed-text
# 2. Chunk Size: 1500 (padrão) — ajustar conforme tipo de documento
# 3. Chunk Overlap: 200 — sobreposição entre chunks para não cortar contexto
# 4. Top K: 4 — número de chunks recuperados por query
# Fazer upload de documentos via interface web:
# Admin Panel → Documents → Upload
# OU arrastar PDFs diretamente para o chat
# Alternativa: carregar documentos via API
curl -X POST http://localhost:3000/api/v1/documents/upload \
-H "Authorization: Bearer ${WEBUI_API_KEY}" \
-F "[email protected]"
# Criar uma coleção de documentos (ex: "politica-interna")
curl -X POST http://localhost:3000/api/v1/documents/collection \
-H "Authorization: Bearer ${WEBUI_API_KEY}" \
-H "Content-Type: application/json" \
-d '{"name": "politica-interna", "description": "Documentos de RH e políticas"}'
# Adicionar URL para indexação (crawler automático)
curl -X POST http://localhost:3000/api/v1/documents/web \
-H "Authorization: Bearer ${WEBUI_API_KEY}" \
-H "Content-Type: application/json" \
-d '{"url": "https://empresa.pt/politica-privacidade"}'
8.2. Script de Backup Completo
#!/bin/bash
# backup-ollama-stack.sh — Backup completo do stack Ollama + Open WebUI
# Correr via cron: 0 2 * * * /opt/scripts/backup-ollama-stack.sh
set -euo pipefail
BACKUP_DIR="/backup/ollama-stack/$(date +%Y%m%d)"
RETENTION_DAYS=14
mkdir -p "$BACKUP_DIR"
echo "=== Backup Ollama + Open WebUI ==="
echo "Data: $(date)"
echo "Destino: $BACKUP_DIR"
# 1. Backup dos modelos Ollama (volume Docker)
echo "[1/3] A copiar modelos Ollama..."
docker run --rm \
-v ollama-models:/data:ro \
-v "$BACKUP_DIR":/backup \
alpine tar czf /backup/ollama-models.tar.gz -C /data .
# 2. Backup da DB e dados do Open WebUI
echo "[2/3] A copiar dados do Open WebUI..."
docker run --rm \
-v open-webui-data:/data:ro \
-v "$BACKUP_DIR":/backup \
alpine tar czf /backup/open-webui-data.tar.gz -C /data .
# 3. Export da configuração (docker-compose.yml + .env)
echo "[3/3] A copiar configuração..."
cp /opt/ollama-stack/docker-compose.yml "$BACKUP_DIR/"
cp /opt/ollama-stack/.env "$BACKUP_DIR/env-backup" # NÃO incluir em git!
# Verificar tamanho do backup
echo ""
echo "=== Backup completo ==="
du -sh "$BACKUP_DIR"/*
echo ""
# Limpeza de backups antigos
find /backup/ollama-stack/ -maxdepth 1 -type d -mtime +$RETENTION_DAYS -exec rm -rf {} \;
echo "Backups com mais de $RETENTION_DAYS dias foram removidos."
# Restauração a partir de backup
BACKUP_DATE="20260614"
BACKUP_DIR="/backup/ollama-stack/$BACKUP_DATE"
# Parter o stack
cd /opt/ollama-stack && docker compose down
# Restaurar modelos
docker run --rm \
-v ollama-models:/data \
-v "$BACKUP_DIR":/backup \
alpine sh -c "rm -rf /data/* && tar xzf /backup/ollama-models.tar.gz -C /data"
# Restaurar dados do Open WebUI
docker run --rm \
-v open-webui-data:/data \
-v "$BACKUP_DIR":/backup \
alpine sh -c "rm -rf /data/* && tar xzf /backup/open-webui-data.tar.gz -C /data"
# Reiniciar
docker compose up -d
9. Troubleshooting — Os 8 Problemas Mais Comuns
Os problemas seguintes cobrem ~90% dos tickets de suporte em implementações Ollama + Open WebUI em ambiente de equipa:
Problema 1: Ollama não deteta a GPU
Sintoma: ollama ps mostra “100% CPU” em vez de “100% GPU”. Geração muito lenta (<10 tok/s).
# Verificar se a GPU é visível
nvidia-smi # deve listar a GPU
docker exec ollama nvidia-smi # se em Docker, verificar dentro do container
# Se nvidia-smi falhar em Docker:
# 1. Reinstalar nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
# 2. Verificar se o docker-compose.yml tem a secção deploy.resources
# (ver secção 6.1 deste artigo)
# 3. Forçar offload de GPU via Modelfile
PARAMETER num_gpu -1
Problema 2: “Error: model not found, try pulling it first”
# Listar modelos disponíveis
ollama list
# Se o modelo não estiver listado, descarregar
ollama pull qwen2.5:32b
# Verificar o nome exato (com tag)
ollama show qwen2.5:32b
# O nome deve corresponder exatamente ao usado no Open WebUI
Problema 3: OOM (Out of Memory) ao carregar modelo
Sintoma: Erro CUDA error: out of memory ou crash do processo.
# Verificar VRAM disponível
nvidia-smi --query-gpu=memory.used,memory.total --format=csv
# Solução 1: Usar quantização mais agressiva (Q4 em vez de Q8)
ollama pull qwen2.5:32b-q4_K_M
# Solução 2: Reduzir num_ctx
PARAMETER num_ctx 4096 # em vez de 8192+
# Solução 3: Ativar kv_cache_type q8_0 (reduz VRAM do KV cache em ~50%)
PARAMETER kv_cache_type q8_0
# Solução 4: Descarregar outros modelos da memória
ollama stop mistral-small:24b
ollama stop phi4:14b
# Solução 5: Offload parcial para CPU (apenas algumas camadas na GPU)
PARAMETER num_gpu 20 # em vez de -1 (todas as camadas)
Problema 4: Open WebUI não consegue ligar ao Ollama
# Verificar que o Ollama está a correr
docker compose ps
docker compose logs ollama --tail 20
# Verificar conectividade entre containers
docker exec open-webui curl -s http://ollama:11434/api/tags
# Se falhar, verificar rede Docker:
docker network inspect ollama-stack_default
# Variável de ambiente correta no docker-compose.yml:
environment:
- OLLAMA_BASE_URL=http://ollama:11434
# NÃO usar http://localhost:11434 (localhost dentro de Docker = o próprio container)
# Se Ollama estiver noutro servidor:
- OLLAMA_BASE_URL=http://192.168.1.100:11434
Problema 5: Respostas truncadas ou cortadas a meio
# Causa: num_predict demasiado baixo (padrão: 128)
# ou num_ctx demasiado pequeno para a conversa
# No Modelfile:
PARAMETER num_predict 4096
PARAMETER num_ctx 8192
# No Open WebUI: Admin Panel → Settings → Models
# Aumentar "Max Tokens" para 4096 ou superior
Problema 6: RAG não retorna resultados relevantes
# 1. Verificar que o modelo de embeddings está carregado
ollama list | grep nomic
# Se não estiver: ollama pull nomic-embed-text
# 2. Verificar se os documentos foram indexados
# No Open WebUI: Admin Panel → Documents
# Cada documento deve ter status "indexed" e mostrar número de chunks
# 3. Ajustar Top K (número de chunks recuperados)
# Admin Panel → Settings → Documents → Top K
# Padrão: 4. Aumentar para 6-8 se os resultados não são relevantes
# 4. Ajustar Chunk Size
# Para documentos técnicos: 1000-1500 tokens
# Para código: 500-800 tokens (chunks menores = mais precisão)
# 5. Verificar que o documento não é demasiado grande
# PDFs >100 páginas podem falhar na indexação — dividir em partes
Problema 7: Disco cheio (modelos ocupam demasiado espaço)
# Verificar espaço ocupado por modelos
du -sh ~/.ollama/models/
# ou em Docker:
docker exec ollama du -sh /root/.ollama/models/
# Listar modelos e respetivo tamanho
ollama list
# NAME ID SIZE MODIFIED
# qwen2.5:32b abc123... 20 GB 2 weeks ago
# llama3.3:70b def456... 40 GB 1 month ago
# Remover modelos não utilizados
ollama rm llama3.2:3b # liberta ~2.5GB
ollama rm mistral:7b # liberta ~5GB
# Verificar espaço livre
df -h ~/.ollama/
Problema 8: Cloudflare Tunnel desconecta frequentemente
# Verificar logs do cloudflared
docker compose logs cloudflared -f --tail 50
# Se aparecer "connection closed" repetidamente:
# 1. Verificar conectividade de internet
ping 1.1.1.1
# 2. Verificar que o token do túnel é válido
# Cloudflare Zero Trust → Networks → Tunnels → editar túnel
# 3. Adicionar healthcheck no docker-compose.yml
cloudflared:
image: cloudflare/cloudflared:latest
command: tunnel --no-autoupdate run
environment:
- TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}
healthcheck:
test: ["CMD", "cloudflared", "version"]
interval: 30s
timeout: 10s
retries: 3
restart: unless-stopped
10. Integração com Coding Assistants (Claude Code, Continue.dev, Roo Code)
Uma das vantagens do Ollama é servir como backend de coding assistants — permitindo autocomplete e chat de código sem enviar o código-fonte para APIs externas. A API compatível com OpenAI torna a integração quase imediata.
10.1. Continue.dev (VS Code e JetBrains)
O Continue.dev é uma extensão open-source para VS Code e JetBrains que oferece autocomplete, chat inline, e refactoring com IA. Configura-se num ficheiro config.json dentro do projeto:
// .continue/config.json — Configuração do Continue.dev com Ollama
{
"models": [
{
"title": "Ollama Qwen 2.5 32B",
"provider": "ollama",
"model": "qwen2.5:32b",
"apiBase": "http://localhost:11434",
"contextLength": 8192
},
{
"title": "Ollama DeepSeek-R1 (Reasoning)",
"provider": "ollama",
"model": "deepseek-r1:32b",
"apiBase": "http://localhost:11434"
},
{
"title": "Ollama Qwen 7B (Autocomplete)",
"provider": "ollama",
"model": "qwen2.5:7b",
"apiBase": "http://localhost:11434",
"contextLength": 2048
}
],
"tabAutocompleteModel": {
"title": "Ollama Autocomplete",
"provider": "ollama",
"model": "qwen2.5:7b",
"apiBase": "http://localhost:11434"
},
"embeddingsProvider": {
"provider": "ollama",
"model": "nomic-embed-text",
"apiBase": "http://localhost:11434"
}
}
10.2. Claude Code com Ollama
O Claude Code pode ser configurado para usar Ollama como endpoint de inferência, aproveitando a API compatível com OpenAI:
# Configurar Claude Code para usar Ollama
# Definir variável de ambiente:
export ANTHROPIC_BASE_URL=http://localhost:11434/v1
export ANTHROPIC_API_KEY=ollama # valor arbitrário, Ollama não valida key
# Ou em ~/.claude/config.json:
{
"api": {
"baseURL": "http://localhost:11434/v1",
"apiKey": "ollama"
},
"model": "qwen2.5:32b"
}
# Testar:
claude "Escreve uma função Python para ler CSV com pandas e filtrar linhas."
10.3. Outras Integrações (Obsidian, n8n, VS Code)
Para além dos coding assistants, o Ollama integra-se com várias ferramentas do dia-a-dia:
- Obsidian — plugin Text Generator ou Bramses AI permitem gerar texto, resumir notas, e fazer Q&A sobre o vault usando Ollama como backend.
- n8n — usar o node “HTTP Request” para chamar
http://ollama:11434/api/chatem workflows de automação. Permite pipelines como: email recebido → resumir com Ollama → criar ticket no Jira. - VS Code (sem Continue) — extensão Ollama VS Code oferece chat lateral com modelos locais.
- Roo Code — extensão VS Code que usa Ollama para agent-based coding, com suporte a múltiplos modelos em simultâneo (um para planning, outro para coding).
# n8n workflow — chamar Ollama via HTTP Request node
# Configuração do node:
Method: POST
URL: http://ollama:11434/api/chat
Headers: Content-Type: application/json
Body (JSON):
{
"model": "qwen2.5:7b",
"messages": [
{"role": "system", "content": "Resume o seguinte email em 3 pontos."},
{"role": "user", "content": "{{$json.textBody}}"}
],
"stream": false
}
# O resultado (resumo) pode ser enviado para Slack, Notion, etc.
11. FAQ para Sysadmins e Developers
Perguntas frequentes sobre funcionalidades avançadas — function calling, structured outputs, e casos de uso práticos:
11.1. Function Calling e Structured Outputs
O Ollama 0.5+ suporta function calling (o modelo pode chamar funções externas) e structured outputs (forçar o modelo a responder em JSON válido). Isto é essencial para integração programática — parsing automático, pipelines de dados, automação:
# Structured Outputs — forçar JSON com schema definido
curl http://localhost:11434/api/chat \
-H "Content-Type: application/json" \
-d '{
"model": "qwen2.5:32b",
"messages": [
{"role": "user", "content": "Extrai o nome, idade e email: \"O João Silva tem 34 anos e o email é [email protected]\""}
],
"format": {
"type": "object",
"properties": {
"nome": {"type": "string"},
"idade": {"type": "integer"},
"email": {"type": "string"}
},
"required": ["nome", "idade", "email"]
},
"stream": false
}' | jq .message.content
# Resposta garantida em JSON válido:
# {"nome":"João Silva","idade":34,"email":"[email protected]"}
# Function Calling — o modelo decide chamar uma função
curl http://localhost:11434/api/chat \
-H "Content-Type: application/json" \
-d '{
"model": "qwen2.5:32b",
"messages": [
{"role": "user", "content": "Que tempo faz em Lisboa hoje?"}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Obter meteorologia para uma cidade",
"parameters": {
"type": "object",
"properties": {
"cidade": {"type": "string", "description": "Nome da cidade"}
},
"required": ["cidade"]
}
}
}
],
"stream": false
}' | jq .message.tool_calls
# Resposta:
# [{"function":{"name":"get_weather","arguments":{"cidade":"Lisboa"}}}]
11.2. FAQ Rápida
P: Quantos utilizadores simultâneos suporta?
R: O Ollama processa um pedido de cada vez por modelo carregado (fila interna). Para 5+ utilizadores em simultâneo, considera múltiplas instâncias com um load balancer (ex: nginx) à frente. Cada pedido enfileira e é processado sequencialmente; com OLLAMA_MAX_QUEUE=10 podes limitar a fila.
P: Posso correr vários modelos em simultâneo?
R: Sim, desde que a VRAM total seja suficiente. O Ollama carrega cada modelo numa “sessão” separada. Usa OLLAMA_MAX_LOADED_MODELS=3 para limitar quantos modelos ficam residentes em VRAM.
P: Como atualizar o Ollama sem perder modelos?
R: Os modelos ficam em volumes Docker persistentes — atualizar o container não os afeta: docker compose pull && docker compose up -d.
P: O Ollama envia dados para a nuvem?
R: Não. Após o download inicial dos modelos, toda a inferência é 100% local. Nenhuma telemetria é enviada por padrão (pode desativar-se com OLLAMA_NOHISTORY=true).
12. Outras Causas Comuns de Problemas em Operação
Para além dos 8 problemas da secção 9, existem questões de segurança e isolamento que causam problemas subtis em ambiente de equipa. Estes são frequentemente ignorados em setups de desenvolvimento mas tornam-se críticos em produção:
12.1. Segurança e Isolamento
0.0.0.0:11434 sem autenticação. Se o servidor tiver IP público, qualquer pessoa pode usar os teus modelos (e consumir a tua VRAM). Usa firewall para bloquear a porta ou liga apenas a 127.0.0.1.
# Restringir Ollama a localhost apenas
# No docker-compose.yml:
services:
ollama:
ports:
- "127.0.0.1:11434:11434" # só acessível localmente
# OU remover "ports" e usar apenas rede interna Docker:
# expose:
# - "11434"
# Firewall (UFW) — bloquear porta externamente
sudo ufw deny 11434
sudo ufw allow from 192.168.1.0/24 to any port 11434 # só LAN
# Variáveis de segurança no Ollama:
environment:
- OLLAMA_HOST=127.0.0.1:11434 # escutar só em localhost
- OLLAMA_ORIGINS=http://localhost:3000,https://ia.empresa.pt # CORS whitelist
- OLLAMA_NOHISTORY=true # não guardar histórico de prompts
12.2. Isolamento de Rede entre Containers
# docker-compose.yml com redes isoladas
services:
ollama:
networks:
- backend # só rede interna
open-webui:
networks:
- backend
- frontend # exposta ao exterior via Cloudflare
cloudflared:
networks:
- frontend
networks:
backend:
internal: true # sem acesso à internet
frontend:
# rede normal — pode aceder ao exterior
12.3. Boas Práticas de Segurança
- Ativar autenticação no Open WebUI (
WEBUI_AUTH=true) — nunca deixar a interface sem password. - Desativar registo público (
ENABLE_SIGNUP=false) ou exigir aprovação manual (DEFAULT_USER_ROLE=pending). - Usar Cloudflare Access à frente do túnel para dupla autenticação.
- Backup regular da DB do Open WebUI (contém conversas, prompts, documentos RAG — dados sensíveis).
- Atualizar containers regularmente:
docker compose pull && docker compose up -d. - Restringir CORS com
OLLAMA_ORIGINSpara apenas os domínios autorizados. - Monitorizar logs com
docker compose logs -f --tail 100para detetar acessos não autorizados.
13. Como Evitar Problemas — Boas-Práticas de Operação
A escolha de hardware correta é a primeira linha de defesa contra problemas de operação. A tabela seguinte detalha recomendações de hardware por tamanho de equipa, incluindo CPU, RAM, GPU, e armazenamento:
13.1. Recomendações de Hardware Detalhadas
| Componente | 1-5 Pessoas | 5-25 Pessoas | 25-100 Pessoas |
|---|---|---|---|
| GPU | RTX 4060 16GB ou RTX 3060 12GB | RTX 4090 24GB ou 2x RTX 3090 24GB | 2x RTX 4090 24GB ou RTX 6000 Ada 48GB |
| VRAM Total | 12-16GB | 24-48GB | 48-96GB |
| CPU | Ryzen 5 7600 / i5-13600K | Ryzen 9 7950X / i7-14700K | Ryzen 9 7950X / Xeon W-2400 |
| RAM | 32GB DDR5 | 64GB DDR5 | 128GB DDR5 ECC |
| Disco | 1TB NVMe SSD | 2TB NVMe SSD (Gen4) | 4TB NVMe SSD (Gen5) + NAS backup |
| Modelo Máximo | Phi-4 14B (Q4), Qwen 2.5 7B | Qwen 2.5 32B, Nemotron 30B, DeepSeek-R1 32B | Llama 3.3 70B (Q4), Qwen 2.5 72B (Q3) |
| Tokens/s Esperados | 40-80 (7B), 15-25 (14B) | 30-50 (32B), 12-20 (70B Q3) | 20-35 (72B Q4), 8-15 (70B Q4) |
| Investimento | 350-600€ | 1.500-2.500€ | 5.000-10.000€ |
13.2. Boas Práticas de Operação Diária
- Monitorização de VRAM — script cron que verifica
nvidia-smie alerta se VRAM >90%. - Limpeza automática de modelos —
OLLAMA_KEEP_ALIVE=30mpara descarregar modelos não usados após 30 min. - Atualizações programadas —
docker compose pull && docker compose up -dmensalmente, em janela de manutenção. - Teste de backup — restaurar o backup mensalmente em ambiente de teste para verificar integridade.
- Gestão de modelos — manter apenas 2-3 modelos em produção; remover modelos experimentais com
ollama rm. - Logs centralizados — encaminhar logs Docker para um sistema de monitoring (Grafana Loki, ELK).
14. Anexos
14.1. Checklist Final de Implementação
Checklist para validar que o stack está pronto para produção:
- ☐ Docker e Docker Compose instalados (versão 2.20+)
- ☐ NVIDIA Container Toolkit instalado e
nvidia-smifuncional dentro de container - ☐
docker-compose.ymlcom volumes persistentes para modelos e dados - ☐ Ollama acessível em
http://ollama:11434a partir do Open WebUI - ☐ Pelo menos 1 modelo descarregado e testado (
ollama run) - ☐ Open WebUI acessível em
http://localhost:3000
🔧 Performance
- ☐
ollama psmostra “100% GPU” (não CPU) - ☐ Modelfile com
num_ctx 8192+configurado - ☐
flash_attention trueativado - ☐
kv_cache_type q8_0configurado - ☐ Tokens/s medidos e dentro do esperado (ver tabela 13.1)
🔧 Segurança
- ☐ Porta 11434 não exposta publicamente (bind a 127.0.0.1)
- ☐
WEBUI_AUTH=trueno docker-compose.yml - ☐
ENABLE_SIGNUP=falseouDEFAULT_USER_ROLE=pending - ☐
OLLAMA_ORIGINSconfigurado com CORS whitelist - ☐ Cloudflare Tunnel + Access configurados (se acesso externo)
- ☐ LDAP/AD integrado (se equipa >10 pessoas)
🔧 Operação
- ☐ Script de backup configurado em cron (diário, retenção 14 dias)
- ☐ Teste de restauração de backup efetuado com sucesso
- ☐
OLLAMA_KEEP_ALIVE=30mpara libertar VRAM - ☐ Monitorização de VRAM configurada (alerta >90%)
- ☐ Documentação interna criada (modelo a usar, procedimentos)
🔧 RAG (se aplicável)
- ☐ Modelo de embeddings
nomic-embed-textdescarregado - ☐ Documentos indexados e testados com queries reais
- ☐ Chunk size e Top K ajustados ao tipo de documento
14.2. Comandos de Referência Rápida
# === Comandos essenciais ===
ollama serve # iniciar servidor
ollama list # listar modelos
ollama pull qwen2.5:32b # descarregar modelo
ollama run qwen2.5:32b # conversação interativa
ollama ps # modelos em memória
ollama stop qwen2.5:32b # descarregar modelo
ollama rm mistral:7b # remover modelo
ollama create meu-modelo -f Modelfile # criar modelo personalizado
ollama show qwen2.5:32b # detalhes do modelo
# === Docker ===
docker compose up -d # iniciar stack
docker compose down # parar stack
docker compose pull # atualizar imagens
docker compose logs -f --tail 50 # ver logs em tempo real
docker compose restart ollama # reiniciar serviço específico
docker exec ollama ollama list # executar comando dentro do container
# === API REST ===
curl http://localhost:11434/api/tags # listar modelos
curl http://localhost:11434/api/chat -H "Content-Type: application/json" -d '{"model":"qwen2.5:7b","messages":[{"role":"user","content":"Olá"}],"stream":false}'
# === GPU ===
nvidia-smi # estado da GPU
nvidia-smi --query-gpu=memory.used,memory.total --format=csv # VRAM usada/total
watch -n 2 nvidia-smi # monitorização contínua
💡 Alternativa sem hardware
Se não queres comprar GPU ou configurar Ollama localmente, o ChatLLM Teams dá-te acesso a GPT-4, Claude, Gemini, DeepSeek e outros SOTA LLMs numa só plataforma. (afiliado)
