9.0 KiB
O que é
Um servidor HTTP e WebSocket em Rust (Actix Web) que cuida do Ollama por você: verifica se ele está instalado e respondendo, instala quando falta, lista e baixa modelos de um catálogo e conversa com eles por WebSocket. Traz também criptografia AES-256-GCM e um CRUD de usuários, com JWT e Swagger UI. O .env.example indica que os tokens vêm de um frontend separado.
Por que usar
- Setup do Ollama num lugar só.
GET /v2/api/ollama/checkdiz se o Ollama está noPATH, qual a versão e se a API responde (reachable,unreachableoudegraded).POST /v2/api/ollama/installinstala por sistema: no Windows baixa oOllamaSetup.exee roda/silent, no Linux usa o script oficial e no macOS extrai o zip em/Applications. - Chat que prepara o modelo. Em
/v2/ws/chat, se o modelo pedido não estiver instalado, o servidor o baixa antes de responder e avisa o progresso por mensagens de status. - Contrato documentado pelo código. O OpenAPI é gerado com utoipa e servido no Swagger UI em
/docs.
Quando não usar: exposto na internet ou em produção. Rotas que baixam e executam instaladores são públicas, os usuários ficam só em memória e o chat não faz streaming incremental. Se você só precisa conversar com um Ollama já instalado, a API dele na porta 11434 basta.
Important
Nem toda rota exige JWT. O middleware só protege
/api/v1/*,/v2/api/crypto*e/v2/api/models*. Ficam públicas/health,/v2/health,/v2/api/ollama/*(inclusivePOST /v2/api/ollama/install, que baixa e executa o instalador do Ollama),/docse os WebSockets/v2/ws*. Por padrão o servidor escuta só em127.0.0.1; só mudeHOSTsabendo disso. O.env.examplevem com umJWT_SECRETpreenchido (sem ele, o padrão échangeme-dev-secret): troque pelo seu.
Como funciona
src/main.rs,src/config.rsesrc/state.rs: sobem o servidor, leem a configuração das variáveis de ambiente e montam oAppContext(eventos, criptografia, URL do Ollama, catálogo, segredo JWT).src/api/: rotas v2 de saúde, modelos, Ollama e criptografia.src/core/models.rs: lê omodelList.json(93 modelos; a API expõenameedescription), consulta/api/tagse baixa com/api/pulldo Ollama.src/services/install/: instalação do Ollama por sistema operacional.src/ws/: WebSockets de eventos (/v2/ws) e de chat (/v2/ws/chat).src/crypto/: AES-256-GCM com nonce aleatório de 12 bytes antes do ciphertext; a chave fica em hex em<config do usuário>/OllaHubBackend/crypto_v2.key.src/middlewares/: JWT, CORS com uma única origem, log de requisições e erros no formato{"error": "..."}.src/routes/,src/controllers/esrc/repositories/: CRUD de usuários em/api/v1, com repositório em memória.
Início rápido
Requisitos: Rust (edição 2021) e um Ollama acessível, ou use POST /v2/api/ollama/install depois de subir o servidor.
Warning
No Windows, o servidor mexe na configuração da máquina ao iniciar. Se estiver elevado (administrador), cria regras de entrada no Firewall para as portas
8080e11434(perfis Domain, Private e Public) e adiciona uma exclusão do Windows Defender para o próprio executável (Add-MpPreference). Sem privilégios de administrador, só registra avisos e segue.
git clone https://git.evandro.dev.br/evandro/OllaHubBackend.git
cd OllaHubBackend
cp .env.example .env # troque JWT_SECRET e ajuste ALLOWED_ORIGINS
cargo run # sobe em http://127.0.0.1:8080
curl http://127.0.0.1:8080/health
curl http://127.0.0.1:8080/v2/api/ollama/check
curl -H "Authorization: Bearer <jwt>" http://127.0.0.1:8080/v2/api/models
cargo build --release gera o binário em target/release; cargo test roda o único teste do repositório (ida e volta da criptografia).
Uso
Swagger UI em /docs, OpenAPI em /api-doc/openapi.json. Referência completa em docs/API.md.
| Método | Rota | JWT | O que faz |
|---|---|---|---|
| GET | /health |
não | Resposta simples "ok" |
| GET | /v2/health |
não | {"status":"ok"} |
| GET | /v2/api/ollama/check |
não | Estado do Ollama: PATH, versão, API alcançável e problemas encontrados |
| POST | /v2/api/ollama/install |
não | 202 com operation_id; instala em background e espera a API responder (até 60 s). Falhas não voltam na resposta |
| GET | /v2/api/models |
sim | Modelos do modelList.json |
| POST | /v2/api/models/install |
sim | 202; baixa o modelo ({"name": "..."}) em background via /api/pull |
| POST | /v2/api/crypto/set-key |
sim | Define a chave AES-256 ({"hex_key": "<64 hex>"}) e a grava em disco |
| POST | /v2/api/crypto/rotate-key |
sim | Gera uma chave nova e a devolve em hex |
| POST | /v2/api/crypto/encrypt |
sim | {"data": "texto"} → {"ciphertext": "<base64>"} |
| POST | /v2/api/crypto/decrypt |
sim | {"data": "<base64>"} → {"plaintext": "texto"} |
| GET/POST | /api/v1/users |
sim | Lista ou cria usuário (nome com 2+ caracteres, e-mail válido) |
| GET/PUT/DELETE | /api/v1/users/{id} |
sim | Lê, atualiza ou remove usuário |
| WS | /v2/ws |
não | Eco de mensagens e pong |
| WS | /v2/ws/chat |
não | Chat com um modelo do Ollama |
Autenticação: Authorization: Bearer <jwt>, assinado em HS256 com JWT_SECRET, com as claims sub e exp (e role opcional). A API não emite tokens: o segredo precisa ser o mesmo do serviço que os emite.
No /v2/ws/chat, envie um JSON por mensagem de texto:
{ "model": "llama3.2", "messages": [{ "role": "user", "content": "Olá" }], "options": { "temperature": 0.7 } }
O servidor responde com status (checking, ready, installing com progress, installed) e depois com as linhas JSON do /api/chat do Ollama. Falhas chegam como {"error": "...", "done": true}. Há ping a cada 5 s, e a conexão fecha após 30 s sem atividade do cliente.
Configuração
O .env é carregado com dotenv na inicialização; as variáveis são lidas em src/config.rs e src/middlewares/.
| Variável | Padrão | Uso |
|---|---|---|
HOST |
127.0.0.1 |
Endereço de escuta |
PORT |
8080 |
Porta de escuta |
OLLAMA_BASE_URL |
http://localhost:11434 |
API do Ollama |
MODEL_LIST_PATH |
modelList.json |
Catálogo exposto em /v2/api/models |
JWT_SECRET |
changeme-dev-secret |
Segredo HS256; deve ser o mesmo de quem emite os tokens |
ALLOWED_ORIGINS |
http://localhost:3000 |
Única origem aceita pelo CORS (com credenciais) |
SKIP_ANTIVIRUS_WARNINGS aparece no .env.example, mas nenhum código lê essa variável.
Estado do projeto
Versão 0.1.0, com três commits entre 2025-11-05 e 2025-11-18: estrutura inicial com API v2, WebSocket e instalação do Ollama. Limites conhecidos:
- Usuários só em memória: o CRUD de
/api/v1/usersperde os dados ao reiniciar. /v2/wsnão envia eventos: só ecoa mensagens e responde a pings. O envio de eventos (PushEvent) existe no código, mas nunca é acionado.- Chat sem streaming incremental: a resposta do Ollama é lida por inteiro (timeout de 300 s) antes de as linhas serem repassadas. O
pull_modelfaz o mesmo, então downloads também não mostram progresso em tempo real. - Erros silenciosos: falhas de instalação do Ollama e de download de modelos em background são descartadas.
- Firewall fixo: a regra criada no Windows usa a porta
8080literal, mesmo com outroPORT. - Documentação defasada:
docs/OLLAMA.mdedocs/API_EXAMPLES.mdcitam rotas antigas como/ollama/install-check; as atuais são/v2/api/ollama/checke/v2/api/ollama/install.
Licença
GPL-3.0: você pode usar, estudar, modificar e redistribuir o código, desde que versões distribuídas mantenham o código-fonte aberto sob a mesma licença. Construído com Actix Web, utoipa, jsonwebtoken, aes-gcm e sysinfo.
Feito por Evandro Fonseca Junior · git.evandro.dev.br