mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-08-26 19:04:18 +02:00
* fix(auth): derive the session cookie Secure flag from the request scheme SECURE_COOKIES only marked the login cookie Secure when it was explicitly set to true, so an HTTPS login on an install that never set it handed out a session cookie the browser is happy to send back in cleartext. Unset now derives the flag from the request: the connection scheme, which uvicorn's proxy-headers middleware rewrites for the proxies it trusts, or X-Forwarded-Proto for a terminator that is not on a trusted address. That is the same test core/middleware.py already applies before sending HSTS, so the two stop disagreeing about whether a request arrived over TLS. An explicit true still forces the flag on and an explicit false turns it off for an install still answering on both HTTP and HTTPS. Strictly more Secure flags than before and never fewer. Empty counts as unset, because docker-compose pinned SECURE_COOKIES=false for every container; the compose files now pass the variable through unset, the way FASTEMBED_CACHE_PATH already does. The helper and its decision order come from #3799, which was closed for being too large to review and whose six replacement PRs dropped this fix. Part of #3803. * docs(setup): flag the leftover SECURE_COOKIES=false on upgrades The old default was false, so an install set up before scheme derivation can still carry an explicit SECURE_COOKIES=false in its own .env. That value stays authoritative, so HTTPS logins keep getting a non-Secure session cookie even after the tracked compose defaults are updated by a pull. Say so where people look: the security notes and the variable's own comment in .env.example. * docs(setup): align TLS guidance with scheme-derived cookies --------- Co-authored-by: Alexandre Teixeira <alexandremagteixeira@gmail.com>
188 lines
8.5 KiB
YAML
188 lines
8.5 KiB
YAML
# Standalone AMD ROCm GPU Compose file for stack-management UIs (Portainer,
|
|
# Coolify, Dockhand, etc.) that accept only a single Compose file and do not
|
|
# reliably honor COMPOSE_FILE or multiple `-f` overlays.
|
|
#
|
|
# This is equivalent to: docker-compose.yml + docker/gpu.amd.yml.
|
|
# The base docker-compose.yml plus the docker/gpu.amd.yml overlay remain the
|
|
# source of truth — CLI users should keep using the COMPOSE_FILE overlay
|
|
# workflow. Keep this file in sync with both when either changes.
|
|
#
|
|
# Requires ROCm drivers on the host (kfd + DRI devices) and the host user
|
|
# running Docker in the `video` and `render` groups. Set RENDER_GID to your
|
|
# host's numeric render group id when needed. See docker/gpu.amd.yml for details.
|
|
services:
|
|
odysseus:
|
|
build: .
|
|
ports:
|
|
- "${APP_BIND:-127.0.0.1}:${APP_PORT:-7000}:7000"
|
|
volumes:
|
|
- ${APP_DATA_DIR:-./data}:/app/data:z
|
|
- ${APP_LOGS_DIR:-./logs}:/app/logs:z
|
|
# Cookbook remote-server SSH identity. Odysseus can generate a key here;
|
|
# add the shown public key to each remote server's authorized_keys.
|
|
- ${APP_DATA_DIR:-./data}/ssh:/app/.ssh:z
|
|
# Cookbook local model cache. Inside Docker, "Local" means the Odysseus
|
|
# container, so persist its HuggingFace cache under ./data/huggingface.
|
|
- ${APP_DATA_DIR:-./data}/huggingface:/app/.cache/huggingface:z
|
|
# Cookbook-installed Python CLIs/packages (vLLM, llama-cpp-python, etc.)
|
|
# land under /app/.local for the odysseus user. Persist them so a
|
|
# container recreate does not silently remove installed serve engines.
|
|
- ${APP_DATA_DIR:-./data}/local:/app/.local:z
|
|
extra_hosts:
|
|
# Lets the container reach local services on the Docker host, including
|
|
# Ollama at http://host.docker.internal:11434.
|
|
- "host.docker.internal:host-gateway"
|
|
environment:
|
|
- LLM_HOST=${LLM_HOST:-localhost}
|
|
- LLM_HOSTS=${LLM_HOSTS:-}
|
|
- OPENAI_API_KEY=${OPENAI_API_KEY:-}
|
|
- OLLAMA_BASE_URL=${OLLAMA_BASE_URL:-}
|
|
- RESEARCH_LLM_ENDPOINT=${RESEARCH_LLM_ENDPOINT:-}
|
|
- HF_TOKEN=${HF_TOKEN:-}
|
|
- HUGGING_FACE_HUB_TOKEN=${HUGGING_FACE_HUB_TOKEN:-}
|
|
- SEARXNG_INSTANCE=http://searxng:8080
|
|
- CHROMADB_HOST=chromadb
|
|
- CHROMADB_PORT=8000
|
|
- DATABASE_URL=${DATABASE_URL:-sqlite:///./data/app.db}
|
|
- AUTH_ENABLED=${AUTH_ENABLED:-true}
|
|
- LOCALHOST_BYPASS=${LOCALHOST_BYPASS:-false}
|
|
- COMPANION_BASE_URL=${COMPANION_BASE_URL:-}
|
|
- ODYSSEUS_ADMIN_USER=${ODYSSEUS_ADMIN_USER:-admin}
|
|
- ODYSSEUS_ADMIN_PASSWORD=${ODYSSEUS_ADMIN_PASSWORD:-}
|
|
- ALLOWED_ORIGINS=${ALLOWED_ORIGINS:-http://localhost,http://127.0.0.1}
|
|
- SECURE_COOKIES=${SECURE_COOKIES:-}
|
|
- EMBEDDING_URL=${EMBEDDING_URL:-}
|
|
- EMBEDDING_MODEL=${EMBEDDING_MODEL:-}
|
|
- EMBEDDING_API_KEY=${EMBEDDING_API_KEY:-}
|
|
- FASTEMBED_MODEL=${FASTEMBED_MODEL:-sentence-transformers/all-MiniLM-L6-v2}
|
|
- FASTEMBED_CACHE_PATH=${FASTEMBED_CACHE_PATH:-}
|
|
- CLEANUP_INTERVAL_HOURS=${CLEANUP_INTERVAL_HOURS:-24}
|
|
- ODYSSEUS_INPROCESS_POLLERS=${ODYSSEUS_INPROCESS_POLLERS:-1}
|
|
- ODYSSEUS_INPROCESS_TASKS=${ODYSSEUS_INPROCESS_TASKS:-1}
|
|
- ODYSSEUS_SCRIPT_HOST=${ODYSSEUS_SCRIPT_HOST:-localhost}
|
|
- ODYSSEUS_CHAT_UPLOAD_MAX_BYTES=${ODYSSEUS_CHAT_UPLOAD_MAX_BYTES:-10485760}
|
|
- ODYSSEUS_GALLERY_UPLOAD_MAX_BYTES=${ODYSSEUS_GALLERY_UPLOAD_MAX_BYTES:-104857600}
|
|
- ODYSSEUS_GALLERY_TRANSFORM_UPLOAD_MAX_BYTES=${ODYSSEUS_GALLERY_TRANSFORM_UPLOAD_MAX_BYTES:-26214400}
|
|
- ODYSSEUS_MEMORY_IMPORT_MAX_BYTES=${ODYSSEUS_MEMORY_IMPORT_MAX_BYTES:-10485760}
|
|
- ODYSSEUS_PERSONAL_UPLOAD_MAX_BYTES=${ODYSSEUS_PERSONAL_UPLOAD_MAX_BYTES:-26214400}
|
|
- ODYSSEUS_EMAIL_COMPOSE_UPLOAD_MAX_BYTES=${ODYSSEUS_EMAIL_COMPOSE_UPLOAD_MAX_BYTES:-26214400}
|
|
- ODYSSEUS_STT_MAX_AUDIO_BYTES=${ODYSSEUS_STT_MAX_AUDIO_BYTES:-26214400}
|
|
- ODYSSEUS_ICS_MAX_BYTES=${ODYSSEUS_ICS_MAX_BYTES:-10485760}
|
|
- ODYSSEUS_TTS_CACHE_MAX_BYTES=${ODYSSEUS_TTS_CACHE_MAX_BYTES}
|
|
- DATA_BRAVE_API_KEY=${DATA_BRAVE_API_KEY:-}
|
|
- GOOGLE_API_KEY=${GOOGLE_API_KEY:-}
|
|
- GOOGLE_PSE_CX=${GOOGLE_PSE_CX:-}
|
|
- GOOGLE_OAUTH_CLIENT_ID=${GOOGLE_OAUTH_CLIENT_ID:-}
|
|
- GOOGLE_OAUTH_CLIENT_SECRET=${GOOGLE_OAUTH_CLIENT_SECRET:-}
|
|
- GOOGLE_OAUTH_REDIRECT_URI=${GOOGLE_OAUTH_REDIRECT_URI:-}
|
|
# Externally reachable origin for MCP OAuth callbacks. The container
|
|
# always listens on 7000 and cannot see the host port map above, so
|
|
# remote MCP OAuth needs this set whenever the browser reaches
|
|
# Odysseus on anything other than http://localhost:7000.
|
|
- OAUTH_REDIRECT_BASE_URL=${OAUTH_REDIRECT_BASE_URL:-}
|
|
- TAVILY_API_KEY=${TAVILY_API_KEY:-}
|
|
- SERPER_API_KEY=${SERPER_API_KEY:-}
|
|
# PUID / PGID — the user/group the container drops to before
|
|
# running uvicorn (entrypoint also chowns /app/data + /app/logs
|
|
# to match, so bind-mounted files stay editable from the host).
|
|
# 1000 is the default first user on most Linux installs. If your
|
|
# host user has a different id, override here or via .env, e.g.:
|
|
# PUID=1001
|
|
# PGID=1001
|
|
# Find yours with: id -u / id -g
|
|
- PUID=${PUID:-1000}
|
|
- PGID=${PGID:-1000}
|
|
depends_on:
|
|
searxng:
|
|
condition: service_healthy
|
|
chromadb:
|
|
condition: service_started
|
|
restart: unless-stopped
|
|
# AMD ROCm overlay (from docker/gpu.amd.yml).
|
|
devices:
|
|
- /dev/kfd
|
|
- /dev/dri
|
|
group_add:
|
|
- video
|
|
- ${RENDER_GID:-render}
|
|
|
|
chromadb:
|
|
image: docker.io/chromadb/chroma:latest
|
|
ports:
|
|
- "${CHROMADB_BIND:-127.0.0.1}:8100:8000"
|
|
volumes:
|
|
- chromadb-data:/chroma/chroma
|
|
environment:
|
|
- ANONYMIZED_TELEMETRY=FALSE
|
|
restart: unless-stopped
|
|
|
|
searxng:
|
|
# Pinned, not :latest — odysseus waits on searxng's healthcheck
|
|
# (depends_on: condition: service_healthy), so a broken upstream `latest`
|
|
# tag blocks the whole app from starting. 2026.6.2 crashes on boot with
|
|
# `KeyError: 'default_doi_resolver'`, failing the healthcheck (issue #1414).
|
|
# Bump this deliberately after verifying a newer tag boots clean.
|
|
image: docker.io/searxng/searxng:2026.5.31-7159b8aed
|
|
entrypoint:
|
|
- /bin/sh
|
|
- -c
|
|
- |
|
|
set -eu
|
|
if [ ! -s /etc/searxng/settings.yml ] || grep -q 'odysseus-local-searxng-json-2026-05-30\|__SEARXNG_SECRET__' /etc/searxng/settings.yml; then
|
|
secret="$${SEARXNG_SECRET:-}"
|
|
if [ -z "$$secret" ]; then
|
|
secret="$$(python -c 'import secrets; print(secrets.token_urlsafe(48))')"
|
|
fi
|
|
sed "s|__SEARXNG_SECRET__|$$secret|g" /tmp/searxng-settings.yml.template > /etc/searxng/settings.yml
|
|
fi
|
|
# Advisory: a settings file the migration cannot parse or rewrite must
|
|
# not be what stops searxng from booting. It explains itself on stderr
|
|
# and we carry on, letting searxng report anything genuinely wrong.
|
|
/usr/local/searxng/.venv/bin/python /tmp/migrate-searxng-settings.py /etc/searxng/settings.yml || true
|
|
exec /usr/local/searxng/entrypoint.sh
|
|
ports:
|
|
- "127.0.0.1:8080:8080"
|
|
volumes:
|
|
- searxng-data:/etc/searxng
|
|
- ./config/searxng/settings.yml:/tmp/searxng-settings.yml.template:ro,z
|
|
- ./scripts/migrate_searxng_settings.py:/tmp/migrate-searxng-settings.py:ro,z
|
|
environment:
|
|
- SEARXNG_BASE_URL=http://localhost:8080/
|
|
- SEARXNG_SECRET=${SEARXNG_SECRET:-}
|
|
# The official searxng image runs as the non-root `searxng` user, but its
|
|
# entrypoint still needs to chown /etc/searxng on first boot, drop privs via
|
|
# su-exec, and (with our wrapper above) write settings.yml into the named
|
|
# volume. Without these capabilities the wrapper aborts at the redirection
|
|
# with EACCES and the container fails its healthcheck with permission
|
|
# errors during setup. Mirrors the cap set recommended by the upstream
|
|
# searxng-docker compose file. See issue #721.
|
|
cap_drop:
|
|
- ALL
|
|
cap_add:
|
|
- CHOWN
|
|
- SETGID
|
|
- SETUID
|
|
- DAC_OVERRIDE
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "python -c \"import urllib.request; urllib.request.urlopen('http://localhost:8080/', timeout=5).read(1)\""]
|
|
interval: 5s
|
|
timeout: 6s
|
|
retries: 20
|
|
start_period: 10s
|
|
restart: unless-stopped
|
|
|
|
ntfy:
|
|
image: docker.io/binwiederhier/ntfy
|
|
command: serve
|
|
ports:
|
|
- "${NTFY_BIND:-127.0.0.1}:8091:80"
|
|
volumes:
|
|
- ntfy-cache:/var/cache/ntfy
|
|
environment:
|
|
- NTFY_BASE_URL=${NTFY_BASE_URL:-http://localhost:8091}
|
|
restart: unless-stopped
|
|
|
|
volumes:
|
|
searxng-data:
|
|
chromadb-data:
|
|
ntfy-cache:
|