Skip to content

Self-hosted Docker stack (embedded Supabase + storage + email) and local Ollama models - #196

Open
thijsdezoete wants to merge 6 commits into
Open-Legal-Products:mainfrom
thijsdezoete:main
Open

Self-hosted Docker stack (embedded Supabase + storage + email) and local Ollama models#196
thijsdezoete wants to merge 6 commits into
Open-Legal-Products:mainfrom
thijsdezoete:main

Conversation

@thijsdezoete

Copy link
Copy Markdown

Summary

A single docker compose up brings up the entire app with no external accounts — a more automated alternative to the CLI-based approach in #44, plus local LLM support.

Self-contained stack

  • Embedded Supabase in compose: Postgres + GoTrue auth + PostgREST + an nginx gateway. Schema auto-loads on first boot; no supabase CLI needed.
  • RustFS for S3-compatible object storage, replacing Cloudflare R2 (the backend already uses path-style S3, so it's drop-in).
  • Mailpit catches auth emails (signup/confirmation) in a local inbox at :8025.
  • Production-style image builds (not bind-mount + npm install on start).

Local models via Ollama

  • New provider speaking Ollama's OpenAI-compatible chat API, with the agentic tool-call loop and a graceful fallback for models that don't support tools.
  • Models detected dynamically (GET /models/ollama) and shown in every picker (chat, title, tabular) under a Local group — no API key. Any ollama/<tag> id is valid by prefix.
  • A Refresh button on the API Keys page re-detects installed models and re-checks key status, live to the pickers.

How this differs from #44

Test plan

  • docker compose up --build brings up all services; schema auto-applies (23 public tables)
  • End-to-end signup → Mailpit confirmation email → confirm → login
  • Chat streams from ollama/qwen3.6; phi3:mini falls back to no-tools
  • GET /models/ollama returns installed models (401 unauthenticated)
  • Ollama models selectable as chat + tabular review models

🤖 Generated with Claude Code

@CLAassistant

CLAassistant commented Jun 29, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

amal66 added a commit to amal66/mike that referenced this pull request Jul 1, 2026
…pen-Legal-Products#196)

The Ollama provider adapter already existed but was dormant — setupOllama() was
only shown in a doc comment (0 real call sites), so using local models meant
editing source. Promote it to a config-only opt-in.

setupOllamaFromEnv() registers the provider iff ENABLE_OLLAMA=true (optional
OLLAMA_MODELS adds custom models to the defaults) and is wired into the LLM
bootstrap. It reads process.env directly rather than the validated env, so it
doesn't force full env validation at module import (this module loads in many
unit tests). Documented ENABLE_OLLAMA/OLLAMA_MODELS in env.ts and the enable
recipe (base URL + OPENAI_ALLOW_LOCAL_BASE_URL) in .env.example.

Gated (default off) on purpose: registering ~20 local model IDs would pollute
the picker on cloud deployments with no Ollama server, and running Ollama also
needs OPENAI_ALLOW_LOCAL_BASE_URL=true — an SSRF-guard relaxation we only want
when a self-hoster opts in. Cloud deployments are unaffected.

Test: ollama.test.ts (3) — no-op unless flag is exactly "true"; registers the
provider + default and custom models when enabled. Full suite: 303 pass / 6 skip.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015bBPsKbPdoK7v1tizu5Qnb
amal66 added a commit to amal66/mike that referenced this pull request Jul 1, 2026
… delta c)

Scoping doc (not implementation) for standing up the whole product on a
disconnected host with no external dependencies, including a local LLM.

Central finding, verified against the code: the app uses only 4 of Supabase's
~13 self-hosted services — Postgres, Auth (GoTrue), PostgREST, and Kong. It does
NOT use Realtime, Supabase Storage (it uses MinIO via r2.ts), imgproxy, Edge
Functions, Studio, analytics, or the pooler. So the embedded stack owns 4
services, not 13 — cutting the CVE surface, version matrix, and config glue by
~70%, which is the direct answer to the maintenance-burden concern.

Covers: air-gap implications (offline image supply, local Ollama, egress removal),
minimal embedded topology (PG15 pin to match migrations; PG17 upgrade out of
scope), secret generation + boot guard + internal TLS, loud attributed degradation
of external features, the stack-E2E harness gating every image bump, a 5-phase
delivery plan (~2-3 weeks), and falsifiable acceptance criteria on a
network-disabled host.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015bBPsKbPdoK7v1tizu5Qnb
thijsdezoete and others added 6 commits July 30, 2026 10:01
… Ollama

Bring the whole app up with a single `docker compose up` and no external
accounts.

Self-contained stack:
- Embedded Supabase (Postgres + GoTrue auth + PostgREST + an nginx gateway),
  with the schema auto-loaded on first boot and auth emails auto-confirmable.
- RustFS for S3-compatible object storage, replacing Cloudflare R2.
- Mailpit catches auth emails (signup/confirmation) in a local inbox.
- Production-style image builds for the frontend and backend.

Local models via Ollama:
- New provider speaking Ollama's OpenAI-compatible chat API, including the
  agentic tool-call loop and a graceful fallback for models that don't
  support tools.
- Models are detected dynamically (GET /models/ollama) and appear in every
  model picker (chat, title, tabular review) under a "Local" group, with no
  API key required. Any `ollama/<tag>` id is valid by prefix.
- Manual "Refresh" button on the API Keys page re-detects installed models
  and re-checks key status, pushing updates live to the pickers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…review)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
env_file: ./backend/.env was a hard failure when the file is absent, which
is always the case on Dokploy and similar platforms that inject env vars
rather than committing a .env.

Both backend/.env and the compose-root .env are now optional sources, root
last so hosted values win. Secrets deliberately stay out of environment:,
which overrides env_file — a bare name unset on the host silently blanks
out the value the file supplied.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fixed host ports assume a dev machine. On Dokploy, 3000 is the dashboard's,
so the frontend fails with 'port is already allocated'. Each published port
now takes an env override with the current value as default, so local dev is
unchanged.

Infra ports (postgres, mailpit, storage) now bind 127.0.0.1 instead of
0.0.0.0. They were reachable from the internet on a public host while still
carrying default credentials, and the mailpit inbox exposes password-reset
links. Compose service-to-service networking is unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GoTrue's API_EXTERNAL_URL and SITE_URL were hardcoded to localhost, so
confirmation links pointed at the user's own machine and signup could never
be completed on a hosted deploy. Both now derive from the public URLs.

MAILER_AUTOCONFIRM and DISABLE_SIGNUP are configurable too: a host with no
real SMTP needs autoconfirm on to register at all, and open registration
should be closable once the operator has an account. Defaults unchanged, so
local dev still exercises the real email flow via Mailpit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bare Ollama needs no auth, but OpenAI-compatible servers behind a gateway
(vLLM --api-key, Open WebUI, LiteLLM) require a bearer token. OLLAMA_API_KEY,
when set, is sent on both model discovery and chat completions; absent, the
provider behaves exactly as before.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@amal66

amal66 commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Good idea. For future reference, we should keep PRs atomic to just one change so that we can better review and merge each change.

Before reviewing, we should fix all e2e tests before marketing it ready for review. Helped with that here, could you please take a look and merge if ready? thijsdezoete#1

I'll review this once that's merged and e2e passes here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants