second-brain/deploy/web/compose.yml
Travis Herbranson 597c83649c deploy/web: containerized FastAPI UI on the homelab docker network
Dockerfile, compose.yml, env template, and runbook for the second-brain
web container. Targets herbys-dev (10.0.21.207); Traefik (file-provider
on 10.0.11.20) reaches the published host port at 10.0.21.207:8080.

Image:
- python:3.12-slim + the official uv binary copied from the upstream
  image, plus apt-installed git + ca-certificates so the Gitea VCS pin
  for embedding-chunking resolves at build time.
- uv sync --frozen --no-dev --no-install-project, source copy, then a
  second uv sync to install the project itself. Two-step so the lock
  install layer caches independently of source edits.
- No ffmpeg / claude CLI / faster-whisper — web role doesn't need any
  of them. Extraction runs on the dev host's CLI; transcription on the
  tower.
- Drops to uid 1000 (`app`) before CMD. Uvicorn binds 0.0.0.0:8000
  inside the container, with --proxy-headers + --forwarded-allow-ips=*
  so Traefik's X-Forwarded-* survive.

compose.yml:
- Joins the existing external `homelab` bridge network so the container
  reaches homelab-postgres:5432 and ollama:11434 by service DNS.
- Publishes the uvicorn port at 10.0.21.207:8080 (LAN IP bound, not
  0.0.0.0) for Traefik on the separate VM to reach. NO traefik.* labels
  — file-provider Traefik can't read them.
- env_file: .env (0600, gitignored) — SECOND_BRAIN_DATABASE_URL points
  at homelab-postgres:5432 (containerised), NOT the host's 127.0.0.1:5433
  port-map.
- restart: unless-stopped.

README.md:
- Build + bring-up commands.
- SECURITY note: no SSO / no CSRF / mutating endpoints — Traefik route
  must be LAN-only for now (Travis's call).
- The two infra steps Travis applies himself, with ready-to-paste
  snippets:
  - Knot DNS: brain.herbylab.dev → 10.0.11.20.
  - Traefik dynamic config: file-provider router + service block.
- Verification checklist for both before-and-after-DNS states.

Live-verified on herbys-dev: container Up, dashboard returns 200 with
real status counts from petalbrain, settings save round-trip works,
no tracebacks in logs.
2026-05-25 11:48:37 -04:00

42 lines
1.4 KiB
YAML

# second-brain web — compose file for herbys-dev (10.0.21.207).
#
# House style: file is named `compose.yml`, no bare `docker run`.
# Bring up with: docker compose up -d --build
# Tear down with: docker compose down
#
# The Traefik VM lives on a different host (10.0.11.20) and uses the
# file provider, NOT docker label discovery. We therefore publish the
# uvicorn port back to a fixed host:port that Traefik's static service
# definition can point at. There are deliberately NO traefik.* labels
# in this file — they'd be silently ignored.
#
# The DB connection is the **containerised** one: `homelab-postgres:5432`
# on the homelab bridge network. Do NOT switch this to 127.0.0.1:5433
# from the container — that loops back inside the container, not the host.
services:
second-brain-web:
build:
context: ../..
dockerfile: deploy/web/Dockerfile
image: second-brain-web:latest
container_name: second-brain-web
restart: unless-stopped
env_file:
- .env
environment:
SECOND_BRAIN_CONFIG: /app/config/settings.toml
volumes:
- ../../config/settings.toml:/app/config/settings.toml:ro
networks:
- homelab
# Bind to the herbys-dev LAN IP only so this isn't accidentally
# exposed on other interfaces. Traefik (10.0.11.20) reaches the
# service at http://10.0.21.207:8080 via the LAN.
ports:
- "10.0.21.207:8080:8000"
networks:
homelab:
external: true