2025-11-05 20:33:04 -03:00
2025-11-05 20:33:04 -03:00

OllaHubBackend

API HTTP + WebSocket em Rust (Actix Web) para gerenciar o Ollama: verifica e instala o Ollama, lista e baixa modelos, faz chat com streaming e oferece criptografia AES-256-GCM, com JWT e Swagger UI.

Rust Actix Web Licença

Endpoints · Como funciona · Configuração · Executar · Limitações

Note

Estado do projeto: versão 0.1.0 (Cargo.toml), com 3 commits entre 2025-11-05 e 2025-11-18 — estrutura inicial com API v2 modular, WebSocket, serviços de instalação do Ollama e documentação. A referência completa dos endpoints está em docs/API.md e exemplos de cliente em docs/API_EXAMPLES.md.

Important

Nem toda rota exige JWT. O middleware só protege /api/v1/*, /v2/api/crypto* e /v2/api/models*. Ficam públicas — inclusive POST /v2/api/ollama/install, que baixa e executa o instalador do Ollama — /health, /v2/health, /v2/api/ollama/*, /docs e os WebSockets /v2/ws*. Por padrão o servidor escuta só em 127.0.0.1; defina JWT_SECRET com um valor próprio (o padrão é changeme-dev-secret) e só mude HOST sabendo disso.

Endpoints

Base URL padrão: http://127.0.0.1:8080. Swagger UI em /docs (OpenAPI em /api-doc/openapi.json).

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: no PATH, versão, API alcançável (reachable / unreachable / degraded), problemas encontrados
POST /v2/api/ollama/install não 202 com operation_id; instala em background e espera a API responder (até 60 s)
GET /v2/api/models sim Lista de modelos lida do modelList.json
POST /v2/api/models/install sim 202; baixa o modelo ({"name": "..."}) em background via /api/pull do Ollama
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 / cria usuário (nome ≥ 2 caracteres, e-mail válido)
GET/PUT/DELETE /api/v1/users/{id} sim Lê / atualiza / remove usuário
WS /v2/ws não Eco de mensagens e pong; veja Limitações
WS /v2/ws/chat não Chat com um modelo do Ollama (abaixo)

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 (o .env.example indica o frontend).

Chat por WebSocket (/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 mensagens de status — {"status":"checking"}, ready, installing (com progress), installed — e então as linhas JSON do /api/chat do Ollama. Se o modelo não estiver instalado, ele é baixado antes de responder. Falhas chegam como {"error": "...", "done": true}. Há ping a cada 5 s e a conexão é encerrada após 30 s sem atividade do cliente.

Como funciona

flowchart LR
    C["Cliente<br/>OllaHub · curl"] -- "HTTP + JWT" --> S["Actix Web<br/>CORS · logging · JWT"]
    C -- WebSocket --> S
    S --> V1["/api/v1/users<br/>repositório em memória"]
    S --> V2["/v2/api/*<br/>models · ollama · crypto"]
    S --> WS["/v2/ws · /v2/ws/chat"]
    V2 --> OL["Ollama :11434<br/>/api/tags · /api/pull · /api/chat"]
    WS --> OL
    V2 --> K["crypto_v2.key<br/>AES-256-GCM"]
    S --> D["/docs<br/>Swagger UI"]
Módulos e detalhes técnicos
Módulo Papel
src/main.rs, src/config.rs, src/state.rs Boot do servidor, configuração por variáveis de ambiente e AppContext (broker de eventos, criptografia, URL do Ollama, caminho do modelList.json, segredo JWT)
src/routes/, src/controllers/, src/services/user_service.rs, src/repositories/, src/models/ CRUD de usuários (/api/v1) com documentação OpenAPI (utoipa)
src/api/ Rotas v2: saúde, modelos, Ollama e criptografia
src/core/models.rs Lê o modelList.json (objeto com models ou array), verifica modelos instalados (/api/tags) e baixa modelos (/api/pull)
src/services/ollama_install.rs, src/services/install/ Verificação e instalação do Ollama por sistema: Windows (baixa OllamaSetup.exe e roda /silent), Linux (curl -fsSL https://ollama.com/install.sh | sh), macOS (baixa o zip e extrai em /Applications)
src/crypto/ AES-256-GCM com nonce aleatório de 12 bytes prefixado ao ciphertext; chave em hex em <config do usuário>/OllaHubBackend/crypto_v2.key, carregada na inicialização
src/ws/ WebSocket de eventos (/ws) e de chat (/ws/chat), montados sob o escopo /v2
src/middlewares/ JWT, CORS (origem única de ALLOWED_ORIGINS), logging de requisições e erros padronizados ({"error": "..."})
src/services/windows_permissions.rs Só no Windows: configuração de permissões na inicialização (veja o aviso abaixo)
modelList.json Catálogo com 93 modelos (nome, descrição, capacidades, tamanhos, URL na biblioteca do Ollama); a API expõe name e description

Warning

No Windows, o servidor mexe na configuração da máquina ao iniciar. Se estiver elevado (administrador), ele cria regras de entrada no Firewall para as portas 8080 e 11434 (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 apenas registra os avisos e segue.

Configuração

Copie .env.example para .env (carregado com dotenv na inicialização). Todas 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 — troque; deve ser o mesmo de quem emite os tokens
ALLOWED_ORIGINS http://localhost:3000 Única origem aceita pelo CORS (com credenciais)

Executar localmente

Requisitos: toolchain Rust (edição 2021) e um Ollama acessível — ou use POST /v2/api/ollama/install.

git clone https://git.evandro.dev.br/evandro/OllaHubBackend.git
cd OllaHubBackend
cp .env.example .env      # ajuste JWT_SECRET e 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     # binário em target/release
cargo test                # o repositório tem um teste: ida e volta da criptografia

Limitações conhecidas

  • Usuários só em memória: o CRUD de /api/v1/users usa um repositório em memória; os dados somem ao reiniciar.
  • /v2/ws não envia eventos: o endpoint apenas ecoa mensagens e responde a pings. O envio de eventos ao cliente (PushEvent) existe no código mas nunca é acionado, e o progresso de instalações vai para outro broker.
  • Chat sem streaming incremental: o corpo da resposta do Ollama é lido por inteiro (timeout de 300 s) antes de as linhas serem repassadas, então os chunks chegam juntos ao fim da geração.
  • Downloads sem progresso em tempo real: pull_model também lê a resposta inteira e só depois publica as linhas e o evento final.
  • Instalação do Ollama: roda instaladores baixados da internet no sistema operacional atual (Windows/Linux/macOS); sistemas não suportados retornam erro.
  • Documentação defasada em um ponto: docs/OLLAMA.md cita rotas legadas (/ollama/install-check, /ollama/install) — as rotas atuais são /v2/api/ollama/check e /v2/api/ollama/install.
  • SKIP_ANTIVIRUS_WARNINGS: consta no .env.example, mas nenhum código lê essa variável.
  • Firewall fixo na porta 8080: a regra criada no Windows usa 8080 literal, mesmo com PORT diferente.

Avisos

S
Description
No description provided
Readme GPL-3.0
140 KiB
0 Stars 1 Watchers 0 Forks
Languages
Rust 100%