phase: 01-core-stack
plan: "01"
subsystem: infra
tags: [docker-compose, ollama, gitea, nvidia, gpu-passthrough, paperless-ngx]

Dependency graph

requires: []
provides:
- ollama/ollama:latest service with NVIDIA GPU passthrough in docker-compose.yml
- gitea/gitea:latest service with SQLite backend in docker-compose.yml
- paperless-ai now references ollama via internal Docker network (http://ollama:11434)
- volumes: ollamamodels, giteadata declared
affects:
- 01-02-PLAN.md (adds healthchecks/network to these 6 services)
- Phase 3 (verify.sh must check Ollama GPU and Gitea reachability)

Tech tracking

tech-stack:
added:
- ollama/ollama:latest (containerized LLM inference with GPU passthrough)
- gitea/gitea:latest (self-hosted Git, SQLite backend)
- nvidia-container-runtime device reservation (deploy.resources.reservations.devices)
patterns:
- GPU passthrough via Docker Compose deploy.resources.reservations.devices block
- Ollama port bound to 127.0.0.1 only (localhost-only exposure per threat model)
- Internal service communication via Docker Compose service names (ollama:11434)

key-files:
created: []
modified:
- docker-compose.yml

key-decisions:
- "Ollama port bound to 127.0.0.1:11434 not 0.0.0.0:11434 — T-01-01 threat mitigation to prevent external model/prompt exposure"
- "Gitea uses SQLite (GITEA__database__DB_TYPE=sqlite3) — no external DB dependency, self-contained service"
- "Gitea SSH on port 222 to leave host SSH port 22 free"
- "Gitea web on port 3001 to avoid conflict with paperless-ai on 3000"

patterns-established:
- "Threat model mitigations applied at implementation time (T-01-01: localhost binding)"
- "paperless-ai depends_on ollama to ensure correct startup order"

requirements-completed: [STACK-02, STACK-03, STACK-04, STACK-05]

Metrics

duration: 1min
completed: 2026-04-17


Phase 1 Plan 01: Ollama (GPU-Passthrough) + Gitea Summary

Ollama containerized with NVIDIA GPU passthrough and Gitea added as a 6th service — paperless-ai switched from host.docker.internal to internal Docker network routing

Performance

  • Duration: 1 min
  • Started: 2026-04-17T20:36:12Z
  • Completed: 2026-04-17T20:37:20Z
  • Tasks: 2
  • Files modified: 1

Accomplishments

  • Added ollama/ollama:latest service with NVIDIA GPU device reservation (count: all, capabilities: [gpu]) — Ollama now runs inside Docker, eliminating the host-side ollama serve dependency
  • Added gitea/gitea:latest service with SQLite backend on port 3001 (web) and 222 (SSH), with persistent giteadata volume
  • Updated paperless-ai to route Ollama requests via internal Docker network (http://ollama:11434) instead of host.docker.internal, added depends_on: [ollama] for correct startup order

Task Commits

Each task was committed atomically:

  1. Task 1: Ollama-Dienst mit NVIDIA-GPU-Passthrough - c9034d4 (feat)
  2. Task 2: Gitea-Dienst ergaenzen - 56c9f8a (feat)

Plan metadata: committed with SUMMARY.md (docs)

Files Created/Modified

  • docker-compose.yml — Added ollama and gitea services, updated paperless-ai environment and depends_on, added ollamamodels and giteadata volumes

Decisions Made

  • Ollama port localhost-only: Bound to 127.0.0.1:11434:11434 instead of 11434:11434 — implements T-01-01 threat mitigation from the plan's threat model. Ollama models and prompts stay local and are not exposed on the network interface.
  • Gitea SQLite: Used GITEA__database__DB_TYPE=sqlite3 as specified — keeps Gitea self-contained with no external DB dependency.
  • Port assignments: Gitea web on 3001 (paperless-ai holds 3000), SSH on 222 (host SSH holds 22).

Deviations from Plan

Auto-fixed Issues

1. [Rule 2 - Security Mitigation] Ollama port bound to localhost only
- Found during: Task 1
- Issue: Plan specified 11434:11434 but the threat model (T-01-01, disposition: mitigate) requires binding to localhost only to prevent external exposure of LLM models and prompts
- Fix: Changed port binding to 127.0.0.1:11434:11434
- Files modified: docker-compose.yml
- Verification: grep "127.0.0.1:11434" docker-compose.yml confirms localhost binding
- Committed in: c9034d4 (Task 1 commit)


Total deviations: 1 auto-fixed (1 security mitigation from plan's own threat model)
Impact on plan: Required for security correctness. No scope creep — threat model T-01-01 explicitly calls for this mitigation.

Issues Encountered

  • docker compose config validation initially showed error about missing docker-compose.env — this is expected behavior, the file is intentionally not committed to git (per CLAUDE.md). Verified YAML validity using a temporary stub env file.

User Setup Required

None — no external service configuration required by this plan. (The docker-compose.env file required for full stack startup is addressed in Plan 02.)

Next Phase Readiness

  • docker-compose.yml now defines all 6 services: broker, db, webserver, paperless-ai, ollama, gitea
  • Ready for Plan 02: explicit Docker network declaration, healthchecks, security hardening, and docker-compose.env.template
  • Pre-flight note: nvidia-container-toolkit must be installed on the target Debian 13 host for GPU passthrough to work — this is a host prerequisite, not a Compose concern

Phase: 01-core-stack
Completed: 2026-04-17