Commit graph

24 commits

Author SHA1 Message Date
Léo
b19d327f03
fix(auth): derive the session cookie Secure flag from the request scheme (#6048)
* 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>
2026-08-16 22:56:36 +01:00
Léo
2e2bb5231e
fix(mcp): stop assuming http://localhost:7000 for the OAuth callback (#6032)
* fix(mcp): stop assuming http://localhost:7000 for the OAuth callback

The MCP OAuth callback origin is wrong on any install not reached at
http://localhost:7000, and on Docker it cannot be corrected at all.
Three sites, one assumption:

- The redirect base fell back to a fixed port 7000. The app binds APP_PORT
  natively (app.py, launcher.py) and the macOS launcher defaults to 7860,
  where 7000 is AirPlay Receiver, so the callback lands on another service
  entirely. The fallback now follows APP_PORT. The hostname stays localhost
  rather than internal_api_base()'s 127.0.0.1: this URI is registered with
  the authorization server, so changing the host would invalidate the
  registrations that already exist.

- The paste-back form hardcoded an http:// action. Serving the page over
  HTTPS, Chrome raises its insecure-form interstitial, and overriding that
  posts plain HTTP at a TLS port, which fails too. Either way the
  authorization code never reaches Odysseus. The action now carries the
  scheme the request arrived on.

- OAUTH_REDIRECT_BASE_URL is the only fix available to a Docker install,
  because the container listens on 7000 and cannot see the host port map,
  but compose never forwarded it and nothing documented it. Both fixed.

* fix(mcp): make the paste-back form action relative and export APP_PORT

Answers the review on #6032. Three of the fixes did not survive contact with
the deployments they targeted.

- The form action derived its scheme from request.url.scheme. uvicorn only
  honours X-Forwarded-Proto from a peer inside --forwarded-allow-ips, which
  defaults to 127.0.0.1; the Dockerfile CMD sets no override, so a proxy
  arriving over the Docker bridge is untrusted and the scheme stays http.
  That is mixed content on exactly the HTTPS installs paste-back exists for.
  A relative action is resolved by the browser against the origin the page
  came from, which is right under every proxy setup, and it drops the Host
  header from the page entirely.

- The APP_PORT fallback never fired for the shipped launchers. start-macos.sh,
  the generated .app launcher and launch-windows.ps1 all pass --port to
  uvicorn without putting the value in the environment, so the motivating
  case, macOS on 7860, still registered localhost:7000. Each now exports it.
  internal_api_base() and companion pairing read APP_PORT too and were wrong
  in the same way.

- .env.example pointed Google MCP servers at OAUTH_REDIRECT_BASE_URL.
  add_server writes Desktop App credentials, and Google only accepts loopback
  redirects for that client type, so a public origin comes back as
  redirect_uri_mismatch. The variable is for the DCR flow; Google stays on the
  loopback default and finishes remotely through paste-back.

The Host header is no longer reflected into the page, so the escaping
regression test asserts its absence instead of its escaping.
2026-08-15 23:09:01 -06:00
RaresKeY
f7cbc885c1
fix(docker): migrate retained SearXNG settings (#6055)
Some checks are pending
CI / Focused test guidance (report-only) (push) Waiting to run
CI / Python syntax (compileall) (push) Waiting to run
CI / JS syntax (node --check) (push) Waiting to run
CI / Python tests (pytest) (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
ci / docker publish / build (amd64) (push) Waiting to run
ci / docker publish / build (arm64) (push) Waiting to run
ci / docker publish / merge manifest + tag (push) Blocked by required conditions
* fix(docker): migrate retained SearXNG settings

Retained nonempty SearXNG settings can miss defaults required by newer pinned images while bypassing the entrypoint's narrow regeneration checks.

Add an atomic PyYAML-aware migration to all Compose variants. Preserve existing inheritance choices, custom content, secrets, ownership, and mode while inserting only the missing top-level default-inheritance key.

Validated with 39 focused and adjacent tests, compile checks, and fresh and retained pinned-image HTTP 200 gates. Full repository CI remains for the PR.

* fix(docker): chmod the settings temp file before chowning it

The Compose cap set is `cap_drop: ALL` plus CHOWN/SETGID/SETUID/DAC_OVERRIDE
and carries no FOWNER, and searxng's own entrypoint chowns /etc/searxng to
searxng:searxng, so every retained settings file belongs to that user by the
second boot. Chowning the temporary file first left root unable to chmod it,
so the migration exited 1 and `set -eu` killed the container before
`exec /usr/local/searxng/entrypoint.sh` — SearXNG never started and odysseus
blocked on its healthcheck.

Swap the two calls so the chmod lands while the temporary file is still
root-owned, and cover the ordering with a test that refuses the chmod once
the chown has happened, the way the kernel does.

* fix(docker): let searxng boot when the settings migration fails

The migration runs under `set -eu`, so any settings file it cannot parse or
rewrite took the container down instead of merely going unmigrated. A symlinked
/etc/searxng/settings.yml is enough: the migration refuses a non-regular file
and searxng, which reads through the symlink perfectly well, never got to start.

Guard the call with `|| true` in all three Compose variants. The failure still
prints its reason on stderr, and searxng is left to report anything genuinely
wrong with the file.

---------

Co-authored-by: Léo <leograndcontact@gmail.com>
2026-08-16 04:17:58 +02:00
Alexandre Teixeira
9c71948376
fix(companion): honor configured pairing address (#6060)
* fix(companion): honor configured pairing origin

* fix(companion): keep configured pairing on v1 LAN contract

* fix(companion): reject numeric pairing hosts

---------

Co-authored-by: RaresKeY <158580472+RaresKeY@users.noreply.github.com>
2026-08-15 21:11:10 +02:00
Boody
9297bed5b9 add ODYSSEUS_TTS_CACHE_MAX_BYTES environment variable to docker-compose 2026-07-29 12:54:55 +03:00
RaresKeY
dcc7e52a86 fix(config): forward Google email OAuth settings through Compose (#5650)
* fix(config): forward Google OAuth env vars into Docker container and document setup

GOOGLE_OAUTH_CLIENT_ID, GOOGLE_OAUTH_CLIENT_SECRET, and GOOGLE_OAUTH_REDIRECT_URI
were read by the app but never forwarded through docker-compose.yml's explicit
environment allowlist, causing the "not set" error even when the vars existed in .env.

Also adds a documented section to .env.example with step-by-step GCP setup instructions
so users know where to get the credentials.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(config): cover OAuth in standalone compose files

* test(config): parse OAuth compose service env

* test(config): keep checkout skip wording neutral

---------

Co-authored-by: TNTBA <trynottobreakanything@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-22 12:59:22 +02:00
Alexandre Teixeira
e86ccae0db fix(docker): make host Docker socket opt-in (#4902)
* fix(docker): make host socket compose opt-in

* fix(cookbook): gate container Docker access

* fix(docker): gate socket group setup on opt-in

* fix(cookbook): gate generated docker exec serve commands

* fix(cookbook): narrow generated docker exec forms
2026-06-30 19:54:51 +02:00
pewdiepie-archdaemon
324b1d9eaf Merge origin/dev into main 2026-06-21 11:08:50 +00:00
pewdiepie-archdaemon
848828829d Docker compose: mount docker.sock + install Docker CLI so Cookbook can reach sibling containers
Cookbook now needs to docker-exec into ollama-rocm (and any other sibling
container holding a model server) from inside its own container, so:

- Dockerfile installs the Docker CLI from the static binary tarball
  (the Debian docker.io package ships dockerd but not the client on slim)
- docker-compose.yml bind-mounts /var/run/docker.sock and adds group_add
  for the host docker group (default GID 963)
- entrypoint.sh detects the socket GID, creates a local group with that
  GID, and runs usermod -aG before gosu-dropping to the app user so the
  supplementary group propagates through (gosu strips by default)
2026-06-19 00:32:47 +00:00
RaresKeY
2007e92a25 fix(devops): harden docker config defaults (#4349) 2026-06-16 04:03:43 +01:00
Daniel
1227393d0e Parameterize Docker Compose volume host paths (#3907) 2026-06-15 20:30:18 +09:00
nubs
4f9300fbf4 fix(upload): configure chat attachment size limit (#2439) 2026-06-07 22:42:24 +02:00
Yiğit Egemen
61f3001b52 Add support for EMBEDDING_API_KEY (#2691)
* feat: support for embedding API key

* feat: encrypt and decrypt embedding API key

* test: add unit tests for EmbeddingClient authorization header behavior
2026-06-05 14:47:24 +02:00
lekt8
cffc4a48e9 Pin the SearXNG image so a broken :latest can't block startup (#1419)
odysseus waits on searxng's healthcheck (depends_on: condition: service_healthy),
so when the upstream `searxng:latest` tag is broken the whole app never starts.
The 2026.6.2 image crashes on boot with `KeyError: 'default_doi_resolver'`,
failing the healthcheck and blocking fresh Docker installs (issue #1414).

Pin to the last known-good tag (2026.5.31-7159b8aed) instead of :latest, with a
comment to bump it deliberately after verifying a newer tag boots clean.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 03:56:54 +09:00
pewdiepie-archdaemon
028f00f81b Label Docker bind mounts for SELinux 2026-06-02 09:50:35 +09:00
pewdiepie-archdaemon
05432e7418 Allow Docker startup without env file 2026-06-02 09:49:35 +09:00
tanmayraut45
a113ee4f6f Fix searxng container permission errors during setup
A fresh `docker compose up -d` shows the searxng container failing its
healthcheck with permission errors at setup (reported in #721 — the
service comes up under names like `odysseus_searxng_1` and never goes
ready, which then blocks the main odysseus container because of the
`depends_on: searxng: condition: service_healthy` gate).

Root cause: the official `searxng/searxng:latest` image runs as the
non-root `searxng` user but its entrypoint still needs to

1. chown /etc/searxng on first boot so the persisted named volume is
   owned by the searxng user inside the container,
2. su-exec to drop / re-assert privileges before launching uwsgi, and
3. let our wrapper entrypoint (which seeds settings.yml into the named
   volume on first boot) write the file through the volume mount.

Without explicit `cap_add`, the container has neither CHOWN nor
DAC_OVERRIDE nor SETUID/SETGID, so the entrypoint aborts at the first
chown / su-exec / redirection with EACCES. The upstream searxng-docker
compose file solves this with the standard "drop everything, grant only
what's needed" capability pattern.

Fix: mirror the upstream cap_drop ALL / cap_add CHOWN, SETGID, SETUID,
DAC_OVERRIDE on the searxng service. This grants only the four caps the
entrypoint actually needs, matches what searxng-docker ships with, and
leaves ports, volumes, env, healthcheck, and the wrapper entrypoint
unchanged.

Closes #721.
2026-06-02 02:47:30 +05:30
Alexander Kenley
1583dab793 Secure by default uplift (#511)
Co-authored-by: Alex Kenley <Alex.Kenley@threatvectorsecurity.com>
2026-06-01 22:30:07 +09:00
Jasper Stubbe
89ef746816 Add explcit docker image source for the podman users (#224)
Co-authored-by: Jasper Stubbe <jasper.stubbe.b@gmail.com>
2026-06-01 02:47:59 +00:00
pewdiepie-archdaemon
2670f28829 Improve Cookbook serve reliability 2026-06-01 11:43:08 +09:00
pewdiepie-archdaemon
464436ea06 Make Docker web port configurable 2026-06-01 11:20:25 +09:00
pewdiepie-archdaemon
71d74290f0 Generate SearXNG secret on first boot 2026-06-01 11:03:02 +09:00
pewdiepie-archdaemon
fc7f107b22 Improve Ollama setup and model endpoint handling 2026-06-01 10:00:15 +09:00
pewdiepie-archdaemon
e5c99a5eee Odysseus v1.0 2026-05-31 23:58:26 +09:00