A self-hosted AI workspace for chat, agents, research, documents, email, notes, calendar, and local model workflows.
Quick Start · Setup Guide · Contributing · Roadmap
devis the default branch and gets the newest changes first. Usemainif you want the more curated branch.
git clone https://github.com/pewdiepie-archdaemon/odysseus.git
cd odysseus
cp .env.example .env
docker compose up -d --buildOpen http://localhost:7000 when the containers are healthy. The first admin password is printed in docker compose logs odysseus.
Native installs, GPU notes, Windows/macOS instructions, HTTPS, and configuration live in the setup guide.
- Chat + Agents — local/API models, tools, MCP, files, shell, skills, and memory.
- Cookbook — hardware-aware model recommendations, downloads, and serving.
- Deep Research — multi-step web research with source reading and report generation.
- Compare — blind side-by-side model testing and synthesis.
- Documents — writing-first editor with AI edits, suggestions, Markdown, HTML, CSV, and syntax highlighting.
- Email — IMAP/SMTP inbox with triage, tags, summaries, reminders, and reply drafts.
- Notes, Tasks + Calendar — reminders, todos, scheduled agent tasks, and CalDAV sync.
- Extras — gallery/image editor, themes, uploads, web search, presets, sessions, and 2FA.
ODYSSEUS_HOST=0.0.0.0 ./start-macos.sh
# then open http://<tailscale-ip>:7860The script also reads .env at startup, so APP_BIND=0.0.0.0 and APP_PORT
set there are picked up automatically without a command-line override each run.
Keep AUTH_ENABLED=true (the default) before binding outside loopback. Do not
expose this port directly to the public internet. To build a clickable app wrapper:
./build-macos-app.shCookbook, GPU, Ollama, and troubleshooting notes
Docker bundled services. Compose starts Odysseus, ChromaDB, SearXNG, and
ntfy. Odysseus and the bundled service ports bind to 127.0.0.1 by default, so
they are reachable from the host but not exposed to your LAN/public internet
unless you opt in.
Cookbook storage in Docker. Downloads live in ./data/huggingface
(~/.cache/huggingface in the container). Cookbook-installed Python CLIs and
serve engines live in ./data/local (~/.local in the container), so they
survive container recreation.
Remote servers. In Cookbook -> Settings -> Servers, generate the
Odysseus SSH key and add the public key to the remote server's
~/.ssh/authorized_keys. From the host you can also run:
ssh-copy-id -i data/ssh/id_ed25519.pub user@serverDocker GPU overlays. CPU-only users can skip this section. Cookbook can only detect GPUs that Docker exposes to the container — if the host runtime or device passthrough is not configured, Cookbook sees the iGPU, another card, or CPU instead of your intended GPU.
For NVIDIA, scripts/check-docker-gpu.sh diagnoses GPU passthrough and can
optionally install the host runtime or update .env.
# Read-only diagnostic (default — installs nothing, never edits .env):
scripts/check-docker-gpu.sh
# Print OS-specific install commands without running them:
scripts/check-docker-gpu.sh --print-install-commands
# Install NVIDIA Container Toolkit on Ubuntu/Debian (requires sudo):
scripts/check-docker-gpu.sh --install-nvidia-toolkit
# Write COMPOSE_FILE to .env (only when GPU passthrough is confirmed working):
scripts/check-docker-gpu.sh --enable-nvidia-overlay
# Full assisted setup — install toolkit, then enable overlay if passthrough works:
scripts/check-docker-gpu.sh --install-nvidia-toolkit --enable-nvidia-overlaySafety notes:
- The app never installs host GPU runtime automatically.
- The app never edits
.envautomatically. .envis only modified when--enable-nvidia-overlayis explicitly passed, and only after GPU passthrough succeeds.--yesskips prompts but does not bypass the passthrough gate..env.bak.*backups created by--enable-nvidia-overlayare ignored by Git and the Docker build context.
To enable manually without the script, add this to .env:
COMPOSE_FILE=docker-compose.yml:docker/gpu.nvidia.ymlAMD / ROCm. AMD setup is read-only diagnostic plus manual .env edit. Run:
scripts/check-docker-amd-gpu.shWindows has two known incompatibilities with the standard Docker setup:
- CRLF line endings — git on Windows (core.autocrlf=true) converts
entrypoint.shto CRLF on checkout, breaking the#!/bin/shshebang inside the Linux container ("no such file or directory"). - Reserved ports — Hyper-V (used by Docker Desktop) reserves port ranges that commonly include 8080, 8091, and 8100. Binding those ports fails with "access permissions" even if nothing is visibly using them.
Both are handled by Dockerfile.windows and docker-compose.windows.yml. Use launch-docker.ps1 which wires everything up automatically:
git clone <your-odysseus-repo-url>
cd odysseus
.\launch-windows-docker.ps1The script creates .env on first run, pulls images, builds with Dockerfile.windows, and opens the browser when the app is ready.
Windows port layout (all in the 7400–7699 range to avoid Hyper-V conflicts):
| Service | Windows host port | Internal port |
|---|---|---|
| Odysseus | 7400 | 7000 |
| ChromaDB | 7401 | 8000 |
| SearXNG | 7402 | 8080 |
| ntfy | 7403 | 80 |
Open http://localhost:7400 after startup.
If you prefer to run the commands manually:
docker compose -f docker-compose.windows.yml up -d --buildUseful checks:
docker compose -f docker-compose.windows.yml ps
docker compose -f docker-compose.windows.yml logs --tail=120 odysseusLLM on localhost? If your LLM server is running on the Windows host (e.g.
http://127.0.0.1:8090/v1), setLLM_HOST=host.docker.internalwithin.env—127.0.0.1inside a Docker container this refers to the container itself, not your local machine.launch-docker.ps1sets this automatically on first run.
Requirements: Python 3.11+. On Linux/Termux, Cookbook also requires tmux
for background model downloads and serves.
COMPOSE_FILE=docker-compose.yml:docker/gpu.amd.yml
RENDER_GID=989For NVIDIA/AMD GPU support, also read the comments in the selected overlay file: docker/gpu.nvidia.yml or docker/gpu.amd.yml.
Stack-management UIs (Portainer, Coolify, Dockhand, etc.). These tools
often accept only a single Compose file and do not reliably honor COMPOSE_FILE
or multiple -f overlays. CLI users should keep using the COMPOSE_FILE
overlay workflow above. For stack UIs, point the stack at one of the standalone
files instead, which bundle the base stack plus the GPU settings:
docker-compose.gpu-nvidia.yml— still requires the NVIDIA Container Toolkit on the host.docker-compose.gpu-amd.yml— still requires host ROCm/kfd/DRI setup, thevideo/rendergroup membership, andRENDER_GIDwhen needed.
The base docker-compose.yml plus the docker/gpu.*.yml overlays remain the
source of truth; the standalone files mirror them for single-file deployments.
Verify after enabling either overlay:
docker compose exec odysseus nvidia-smi -L # NVIDIA
docker compose exec odysseus sh -lc 'test -e /dev/kfd && test -d /dev/dri && ls -l /dev/kfd /dev/dri/renderD*' # AMDGPU passthrough ≠ llama.cpp CUDA.
nvidia-smipassing inside the container confirms Docker GPU access, but llama.cpp also needscudartand the CUDA Toolkit at runtime. If Cookbook logs showUnable to find cudart library,Could NOT find CUDAToolkit,CUDA Toolkit not found, or tensors/layers assigned to CPU, that is a Cookbook/llama.cpp build issue — not a Docker passthrough failure. Re-install the serve engine via Cookbook → Dependencies to get a CUDA-enabled build.The same split applies to AMD/ROCm: seeing
/dev/kfdand/dev/driinside the container confirms device passthrough, not ROCm userspace or a ROCm-enabled vLLM/llama.cpp build.rocm-smiandrocminfoare not expected inside the slim Odysseus image.
Ollama with Docker. If Ollama runs on the host, add this endpoint in Settings:
http://host.docker.internal:11434/v1
Ollama must listen outside its own loopback interface:
OLLAMA_HOST=0.0.0.0:11434 ollama serveThis connects Odysseus in Docker to an Ollama server that is already running on
your host machine; it does not start Ollama inside the container.
host.docker.internal is Docker's hostname for the host machine from inside the
container. Cookbook Serve is a separate workflow for serving downloaded
models through Odysseus/llama.cpp, so Windows users with an existing Ollama
install usually only need to add the endpoint in Settings.
Useful checks.
docker compose ps
docker compose logs --tail=120 odysseus
docker compose logs odysseus | grep -E 'ChromaDB|MemoryVectorStore|DEGRADED'macOS details. start-macos.sh installs Homebrew deps, creates the venv,
runs setup, and starts uvicorn on port 7860 because AirPlay often holds
7000. It uses llama.cpp/Ollama for Metal. vLLM/SGLang are CUDA/ROCm-only and
do not run on macOS. MLX-only models are not served by Odysseus.
One-command launcher (creates the venv, installs deps, runs setup, starts the server; safe to re-run):
git clone https://github.com/pewdiepie-archdaemon/odysseus.git
cd odysseus
powershell -ExecutionPolicy Bypass -File .\launch-windows.ps1Or do it by hand:
git clone https://github.com/pewdiepie-archdaemon/odysseus.git
cd odysseus
py -3.11 -m venv venv
venv\Scripts\Activate.ps1
pip install -r requirements.txt
python setup.py
python -m uvicorn app:app --host 127.0.0.1 --port 7000If python points at an older interpreter, use py -3.12 (or another installed
3.11+ version) for the venv step.
Requirements: Python 3.11+. The core app (chat, agent, memory, documents,
email, calendar, deep research) runs fully native. For full Cookbook background
model downloads and the agent shell tool, also install
Git for Windows (provides bash.exe).
Local GPU serving of vLLM/SGLang needs Linux/WSL2; for a local model on Windows,
Ollama is the easiest path — point Odysseus at
http://localhost:11434/v1 in Settings.
Open http://localhost:7000, log in with the generated admin password,
and configure everything else inside Settings.
If chromadb-client (the lightweight HTTP-only package) is installed alongside the full chromadb package, Odysseus starts but ChromaDB silently falls back to HTTP-only mode and fails.
Fix: uninstall chromadb-client and force-reinstall the full package:
./venv/bin/pip uninstall chromadb-client -y
./venv/bin/pip install --force-reinstall chromadbTo expose Odysseus on a local network or Tailscale with HTTPS:
- Change the bind address to
0.0.0.0in.env(APP_BIND=0.0.0.0orODYSSEUS_HOST=0.0.0.0). - Generate a locally-trusted cert for your LAN/Tailscale IPs using mkcert:
mkcert -install mkcert -cert-file cert.pem -key-file key.pem 192.168.1.100 tailscale-ip
- Run
uvicornwith the generated certs:python -m uvicorn app:app --host 0.0.0.0 --port 7000 --ssl-certfile=cert.pem --ssl-keyfile=key.pem
- Install the
mkcertCA on any other device you want to access Odysseus from (e.g., for iOS, email therootCA.pemto yourself, install the profile, and trust it in Certificate Trust Settings).
requirements-optional.txt contains packages that unlock extra features. It is not installed by default.
| Package | Feature unlocked |
|---|---|
faster-whisper |
Local speech-to-text (microphone -> text) via the "local" STT provider. |
duckduckgo-search |
DuckDuckGo as a search provider option. |
PyMuPDF |
PDF page rendering in the side viewer panel and form-filling. (Note: AGPL-3.0) |
markitdown |
Office/EPUB document text extraction (converts .docx/.xlsx/.pptx/.xls/.epub to Markdown). |
Odysseus email accounts currently use IMAP/SMTP username-password auth. Outlook and Microsoft 365 generally require OAuth instead, so normal Microsoft mailbox passwords will fail. See docs/email-outlook.md for the current limitation and the planned integration direction.
Odysseus is a self-hosted workspace with powerful local tools: shell access, file uploads, model downloads, web research, email/calendar integrations, and API tokens. Treat it like an admin console.
- Keep
AUTH_ENABLED=truefor any network-accessible deployment. - Keep
LOCALHOST_BYPASS=falseoutside local development. - Use
SECURE_COOKIES=truewhen Odysseus is served through HTTPS by a trusted reverse proxy or private access gateway. - Do not expose it directly to the public internet without HTTPS and a trusted reverse proxy or private access layer.
- Keep
.env,data/,logs/, databases, uploads, generated media, backups, auth/session files, API keys, and model/provider tokens out of Git and private shares. They are ignored by default. - Review
data/auth.jsonafter first boot: disable open signup unless you intentionally want it, make only your own account admin, and keep demo/test accounts non-admin. - Non-admin users do not get shell/Python/file read/write by default, and admin-only routes/tools such as MCP management, API tokens, webhooks, model/cookbook serving, backup/vault, and app settings are admin-gated. Other features are controlled by per-user privileges, so review each user's privileges before exposing a deployment.
- Rotate any API keys or tokens that were ever pasted into a shared chat, demo, screenshot, or log.
- If you enable API tokens or webhooks, create separate tokens per integration and delete unused ones.
- Prefer binding manual development runs to
127.0.0.1; bind to0.0.0.0only when you intentionally want LAN/reverse-proxy access. - Keep ChromaDB, SearXNG, ntfy, Ollama, vLLM, llama.cpp, databases, and raw model/provider APIs internal-only. Expose only the authenticated Odysseus web/API entrypoint through your trusted proxy or private access layer.
- Before publishing a fork, run
git status --shortand confirm no private files from.env,data/,logs/, uploads, backups, or local databases are staged.
Odysseus serves plain HTTP on its app port. Docker Compose binds Odysseus and the bundled services to 127.0.0.1 by default, so a typical production/private setup is:
- Keep Odysseus on localhost, for example
127.0.0.1:7000. - Terminate HTTPS at a trusted reverse proxy or private access gateway.
- Put the authenticated Odysseus web/API entrypoint behind that layer.
- Keep raw service and model ports internal-only.
Cloudflare Access, Tailscale, Caddy, nginx, and Traefik can all fit this pattern; none are required by Odysseus. If your access layer reaches Odysseus on the same host, proxy to http://127.0.0.1:7000 and keep AUTH_ENABLED=true, LOCALHOST_BYPASS=false, and SECURE_COOKIES=true.
Common internal-only ports from the default docs/compose setup:
| Port | Service |
|---|---|
7000 |
Odysseus raw app port |
8080 |
SearXNG |
8091 |
ntfy |
8100 |
ChromaDB host port for manual/compose access |
11434 |
Ollama |
8000-8020 |
Common local model/provider APIs |
A full hover-to-play tour lives on the landing page: docs/index.html.
Help is welcome. The best entry points are fresh-install testing, provider setup bugs, mobile/editor polish, docs, and small focused refactors. See CONTRIBUTING.md and ROADMAP.md.
All upload-limit vars are validated (must be a positive integer) and optional; an invalid value fails fast at startup.
Odysseus auto-registers a few built-in MCP servers at startup. The npx-based ones (currently the browser server, @playwright/mcp) only start when their npm package is already in the local npx cache. If a package isn't cached, that server is skipped with a startup log message explaining what to do, so a fresh install does not block on a multi-minute npm download or hang if Playwright system deps are missing.
| Service | Linux host port | Windows host port | What it does |
|---|---|---|---|
| Odysseus | 7000 |
7400 |
The app itself |
| ChromaDB | 8100 |
7401 |
Vector store for semantic memory |
| SearXNG | 8080 (localhost only) |
7402 |
Meta search for web search |
| ntfy | 8091 |
7403 |
Local push notifications |
Container-to-container networking is the same on both platforms (containers always talk on internal ports: chromadb:8000, searxng:8080). Only the host-side bindings differ.
npx -y @playwright/mcp@latest --versionThat installs @playwright/mcp plus Playwright (~300MB total). Restart Odysseus and the server will register at startup.
app.py # FastAPI entry point
core/ auth, database, middleware, constants
src/ llm_core, agent_loop, agent_tools, chat_processor, search/
routes/ chat, session, document, memory, model … endpoints
services/ docs, memory, search, hwfit (Cookbook) …
static/ index.html + app.js + style.css + js/ (modular front-end)
docs/ landing page (index.html) + preview clips
All user data lives in data/ (gitignored): app.db (sessions, messages, documents),
memory.json, presets.json, uploads/, personal_docs/, chroma/, settings.json.
Odysseus is a self-hosted workspace with powerful local tools. Keep auth enabled, keep private data out of Git, and do not expose raw model/service ports publicly. Deployment details are in the setup guide.
AGPL-3.0-or-later -- see LICENSE and ACKNOWLEDGMENTS.md.

