EZRag is a local-first RAG app scaffold designed to make it easy to:
- ingest files from mounted directories,
- embed and store them in a vector database,
- query an LLM with source-backed answers.
The project is in active development.
- Frontend app, router, chat view, and file management view are implemented.
- Backend ingestion, query, and file-watch pipelines are implemented.
- Development compose file is ready.
- Vue 3
- Vite
- TypeScript
- Bun
- Python 3.11+
- FastAPI
- Uvicorn
- LangChain
- Sentence-Transformers
- ChromaDB
- Ollama (local LLM inference)
- websockets
- watchdog
- Apache Tika (remote service for document extraction)
- Docker Compose
- Ollama (qwen3:1.7b, auto-pulled on first start, can be changed)
- ChromaDB 0.4.14 (vector store)
- Apache Tika (document parsing — PDFs, DOCX, etc.)
- Redis
FE/— Vue frontendBE/— Python backendmcp/— MCP server exposing semantic search as a Claude Code tooldata/— Drop files here for ingestion (mounted at/datain BE container)docker-compose.dev.template.yml— dev template; copy todocker-compose.dev.ymlto use (gitignored so personal mounts stay local)docker-compose.template.yml— non-dev template (no hot reload, no host bind-mounts, internal-only ports)
- Docker Desktop (with Compose v2, supports
compose develop watch) - Bun (for local FE workflows if needed)
- Python 3.11+ (for local BE workflows if needed)
For users who just want to run EzRag without modifying the source:
docker compose up- Frontend: http://localhost:80
- Backend API: http://localhost:8000
- Drop files in
./data/to ingest them.
On first start, images are built and the Ollama model is pulled automatically. Subsequent starts are fast.
- Copy the template:
cp docker-compose.dev.template.yml docker-compose.dev.yml - (Optional) Add personal RAG source mounts to the
beservice in your newdocker-compose.dev.yml. - From repo root, run:
docker compose -f docker-compose.dev.yml up --watch - Frontend is available at: http://localhost:5173
- Backend API is available at: http://localhost:8000
- Place files in
./data/— they are mounted into the BE container at/dataand ingested automatically.
cp docker-compose.dev.example.yml docker-compose.dev.ymlThen create docker-compose.local.yml (gitignored) to mount extra directories or override env vars without touching tracked files:
# docker-compose.local.yml
services:
be:
volumes:
- /absolute/path/to/your/notes:/notes:ro
environment:
RAG_DIRS: /data,/notesdocker compose -f docker-compose.dev.yml -f docker-compose.local.yml up --watchOmit -f docker-compose.local.yml if you have not created that file.
- Frontend: http://localhost:5173
- Backend API: http://localhost:8000
Notes:
- FE changes in
FE/sync into the FE container and hot-reload. - BE changes in
BE/sync into the BE container; Uvicorn reload is enabled. - Changes to
FE/package.json,FE/bun.lock, orBE/requirements.txttrigger service rebuilds. - Tika runs as a separate container — no Java needed in the BE image.
docker-compose.template.yml is a stripped-down version intended as a starting
point for a real deployment. Compared to the dev file it:
- builds the FE for production (
bun run build && bun run preview) instead of running the Vite dev server - bakes BE source into the image rather than bind-mounting from the host
- removes Uvicorn
--reloadand thedevelop: watch:blocks - removes personal volume mounts (e.g.
~/Documents/obsidian-vault) - keeps ChromaDB, Redis, and Tika ports internal-only (not published to the host)
- does not auto-pull the Ollama model — you pull it once yourself
To use it, copy the template, fill in your RAG_DIRS volume mounts, then run:
cp docker-compose.template.yml docker-compose.yml
docker compose up -d
docker compose exec model ollama pull qwen3:1.7b # one-timeThe server is available immediately. All heavy work runs in background threads so the UI is never blocked waiting for startup to finish.
uvicorn ready → HTTP available instantly
│
├─ thread: _run_ingestion()
│ Walk RAG_DIRS → Tika extract → embed → ChromaDB upsert
│ Updates ingestion_status.files_done / files_total as it goes
│
└─ start_watching()
watchdog Observer on all RAG_DIRS
on_created → ingest_file()
on_deleted → mark_deleted() (sets deleted=1 in ChromaDB metadata)
on_moved → mark_deleted() + ingest_file()
Poll GET /status (the FE does this automatically every 2 s while loading):
{
"model": { "state": "idle", "progress": 0.0, "message": "" },
"ingestion": { "state": "running", "progress": 0.45, "files_done": 45, "files_total": 100 }
}model.state values: idle | loading | ready | error
ingestion.state values: idle | running | done
cd BE
pip install -r requirements.txt -r requirements-dev.txt
pytestThe test suite mocks ChromaDB, SentenceTransformer, and watchdog so no external services are required.
-
Stretch goals
- Store approved web-fetched knowledge in vector DB
- Persist conversations for future context in a way that doesn't compromise reference integrity
Add your preferred license file and update this section.