Opti-Oignon:面向 Ollama 的本地优先 AI 推理平台
AntsAreRad/opti-oignon
Opti-Oignon 是一个面向 Ollama 的本地优先 AI 推理平台,支持对本地模型进行私密聊天、带 RAG 上下文的项目,并提供 Daily/Bulbe 两种安全模式、静态加密与 2FA,全部运行在自有硬件上。项目基于 SvelteKit 和 FastAPI 构建,已开源,目前处于活跃开发中,Veilid 设备间同步等部分功能尚未端到端打通。
A local-first AI inference platform for Ollama. Private chat against your own local models, projects with RAG context, and a defense-in-depth security model -- two security modes (Daily/Bulbe), encryption at rest, and 2FA -- all running on your own hardware, with nothing leaving the machine. Built with SvelteKit and FastAPI.
The project is open source, and its security follows Kerckhoffs's principle: it derives from keys and correct implementation, never from secrecy of the code.
Status
Opti-Oignon is in active development. The list below is an honest picture of what is wired end to end today versus what exists in the codebase but is still maturing -- read it before you rely on a feature.
Working today (used daily on the developer's machine):
- Streamed chat from local Ollama models over WebSocket.
- Accounts: registration, login, and optional 2FA (TOTP and WebAuthn).
- Two security modes. Daily is the normal mode; Bulbe is a hardened mode enforced at the socket layer (the backend binds to
127.0.0.1only and accepts cookie-based auth only), with a guarded, human-confirmed downgrade ceremony and fail-secure behavior when the mode cannot be determined. - Encryption at rest via SQLCipher.
- Projects with RAG context (ChromaDB).
Implemented and unit-tested, still maturing: the wider intelligence surface (smart routing, multi-model consensus, cascading inference, semantic cache), the sandboxed agent loop, the benchmark and performance dashboards, the resource governor, the red team engine, RBAC and multi-user isolation, and the encrypted Notes tab. The code is present and covered by the test suite, but a fresh install is not guaranteed to exercise every one of these paths end to end yet.
In progress, not wired end to end: Veilid device-to-device sync. The producer side is not complete, so nothing currently moves between paired devices. Everything that depends on it -- remote inference, collaborative Notes sync, and the mobile client -- is therefore experimental.
Quick start
Prerequisites: Python 3.10 or newer (developed on 3.12 and 3.13), Node.js 18 or newer, and a running Ollama with at least one model pulled.
git clone https://github.com/AntsAreRad/opti-oignon.git cd opti-oignon # Backend: core deps plus 2FA and encrypted-database support pip install -e ".[auth,sqlcipher]" # Frontend cd frontend && npm install && cd ..
Then run the two dev servers in separate terminals:
# Terminal 1 -- backend on http://127.0.0.1:8001 scripts/dev_backend.sh --reload # Terminal 2 -- frontend on http://localhost:5173 (proxies /api to the backend) scripts/dev_frontend.sh
Open http://localhost:5173, create an account, and start chatting. The first run shows an onboarding overlay that scans your Ollama models and suggests a preset.
Optional capabilities install through their own extras and are off by default: llama (llama.cpp backend), veilid (peer-to-peer sync), transcribe (voice-note transcription), and vision (image OCR for notes). For example, pip install -e ".[veilid]". These are kept out of the core install because they are platform-specific or experimental.
Docker
# Backend on 127.0.0.1:8001 plus a GPU-enabled Ollama
docker compose up --buildThe Compose stack ships the backend and Ollama; the frontend container is disabled by default, so run the frontend with scripts/dev_frontend.sh pointed at the Dockerized backend. All ports bind to 127.0.0.1. GPU passthrough requires the NVIDIA Container Toolkit; without it, Ollama runs on CPU.
Security model
Security is the project's first design priority. The core posture, as wired today:
- Two modes. Daily is the normal working mode. Bulbe is a physical network constraint, not a policy: the server binds to
127.0.0.1at the socket level and accepts cookie-only authentication, so even a misconfiguration cannot expose it on the network. Switching from Bulbe back to Daily runs a guarded, human-confirmed downgrade ceremony, and an undeterminable mode fails secure (stays Bulbe). - Encryption at rest. Application data lives in SQLCipher-encrypted databases.
- Authentication. Deny-by-default middleware, password hashing with Argon2/bcrypt, and optional 2FA via TOTP and WebAuthn.
- Isolation. Per-user data isolation and role-based access control.
- Sandboxing. Any LLM-driven filesystem, shell, or code tool is designed to run only inside a disposable bubblewrap sandbox with no host filesystem or network access; results are copied out only after explicit human approval.
- Post-quantum signatures. Records intended for device-to-device sync carry ML-DSA-65 signatures (note: the sync transport itself is still in progress -- see Status).
- Signed audit chain. Security-relevant events append to a hash-chained audit log.
See SECURITY.md for the threat model and how to report a vulnerability.
Architecture
graph TB
subgraph Frontend["Frontend -- SvelteKit + Tailwind"]
UI[Chats / Projects / Preferences / Workshop]
WS[WebSocket client]
end
subgraph Backend["Backend -- FastAPI"]
API[REST + WebSocket API]
SEC[Security layer -- auth, RBAC, Daily/Bulbe, encryption at rest]
RAGB[Projects + RAG -- ChromaDB]
ROUTE[Routing + pipelines]
end
OLL[Ollama -- local models]
UI -->|HTTP / SSE| API
WS -->|WebSocket| API
API --> SEC
API --> ROUTE
API --> RAGB
ROUTE -->|inference| OLL
RAGB -->|embeddings| OLL
Loading
The diagram shows the core request path. The broader surface (sandboxed agent, benchmark, resource governor, red team engine, device sync) sits behind the same API and backend; consult the Status section for how mature each part is.
What's included
The core, working today, is private local chat with accounts and the two-mode security model described above, plus projects with RAG context. Beyond that, the codebase also implements -- at varying maturity (see Status) -- intelligent model routing with capability profiles and health-aware failover, multiple inference pipelines (chain-of-thought, multi-model consensus, self-correction, speculative and cascading inference), a semantic response cache, dynamic context budgeting and conversation compression, a sandboxed autonomous coding agent, a benchmark and performance dashboard, a resource governor that fits context to available VRAM, an LLM-powered red team engine, an encrypted Notes tab, and a Veilid-based device-to-device sync layer.
Project structure
frontend/ SvelteKit + Tailwind UI (components, typed API clients, stores, routes)
opti_oignon/ FastAPI backend
api/ Route modules and the FastAPI application (app.py, deps.py, schemas.py)
config/ YAML configuration files
redteam/ LLM-powered red team engine
veilid/ Device-to-device sync (experimental)
notes/ Encrypted Notes feature
data/ System presets and seed data
tests/ Unit and integration test suite
tests/e2e/ Playwright end-to-end specs
scripts/ dev_backend.sh, dev_frontend.sh, run_tests.sh, run_coverage.sh,
run_e2e.sh, run_typecheck.sh, smoke_test.sh, sign_release.sh, ...
docs/ API reference and guides
Configuration
All tunable behavior lives in opti_oignon/config/ as YAML files (model-to-task mapping, routing weights, reasoning and consensus thresholds, cache settings, sandbox blocklists, and so on). System presets in data/system_presets.yaml can configure most of them at once, and the first-run onboarding applies a preset based on your installed models.
API
The backend exposes a REST and WebSocket API covering health, chat and conversations, models and routing, projects and RAG, security and audit, and more. Interactive OpenAPI docs are served at http://localhost:8001/docs while the backend is running. See docs/API_REFERENCE.md for endpoint documentation.
Testing
# Unit and integration tests pytest tests/ --ignore=tests/test_live_v130.py -q # With coverage gates bash scripts/run_coverage.sh # API smoke test (starts a throwaway backend) bash scripts/smoke_test.sh # Type checking against the mypy baseline bash scripts/run_typecheck.sh # Frontend end-to-end tests (Playwright, against a running backend) bash scripts/run_e2e.sh
The suite covers the backend modules. Three Playwright specs (auth-refusal, health, security-mode) drive a real browser against the served frontend and a running backend on port 8001, which they do not start. Each runs in a desktop and a phone-sized browser project, and none tests a mobile layout or reaches a model (see frontend/tests/e2e/README.md). Security-critical modules have individual minimum coverage thresholds; see .coveragerc and coverage_baseline.json.
Development
Conventions enforced across the codebase:
- English comments, docstrings, and UI text throughout; no emojis in code.
- All CSS uses
--oo-*custom properties exclusively, never hardcoded colors. - Conditional imports guarded by
FEATURE_AVAILABLEflags, with graceful fallbacks. - YAML-driven configuration for tunable values.
- Separate SQLite databases per feature domain, all opened through a single safe-connect helper.
- Type annotations on public API functions, checked against a mypy baseline.
- A test suite per change, with a zero-regressions policy.
See CONTRIBUTING.md for the full guidelines.
Roadmap
The near-term focus is finishing the Veilid sync layer so device-to-device sync moves real data end to end, which in turn unblocks remote inference, collaborative Notes sync, and the mobile client. Alongside that: hardening the supply chain (code signing, runtime guards, audit-chain external anchoring) and exercising the broader feature surface end to end on fresh installs.
Contributing
- Fork the repository.
- Create a feature branch.
- Follow the coding conventions above and in CONTRIBUTING.md.
- Add tests for new functionality.
- Run
pytest tests/ --ignore=tests/test_live_v130.pyandbash scripts/run_typecheck.sh. - Open a pull request.
License
Copyright (C) 2026 Leon Brouille
Opti-Oignon is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License only (AGPL-3.0-only). It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE for the full text.
What was published before this licence, releases 2.1.0 and earlier included, was published under the MIT License, which still applies to it.
Acknowledgments
来源:GitHub · github.com