phase: 01-core-stack
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- docker-compose.yml
autonomous: true
requirements:
- STACK-02
- STACK-03
- STACK-04
- STACK-05
must_haves:
truths:
- "Ollama laeuft als Container mit NVIDIA-GPU-Zugriff (nvidia-smi sichtbar im Container)"
- "paperless-ai erreicht Ollama unter http://ollama:11434 — kein host.docker.internal mehr"
- "Gitea laeuft als Container und ist im Docker-Netz erreichbar"
- "Alle 6 Dienste sind in docker-compose.yml definiert"
- "Bestehende Dienste (webserver, db, broker, paperless-ai) sind unveraendert erhalten"
artifacts:
- path: "docker-compose.yml"
provides: "6-Dienste-Compose-Stack: broker, db, webserver, paperless-ai, ollama, gitea"
contains: "ollama"
- path: "docker-compose.yml"
provides: "Gitea-Service-Definition"
contains: "gitea"
key_links:
- from: "paperless-ai (environment)"
to: "ollama service"
via: "OLLAMA_API_URL=http://ollama:11434"
pattern: "ollama:11434"
- from: "ollama service"
to: "NVIDIA GPU"
via: "nvidia container runtime + device reservation"
pattern: "nvidia"
Zwei neue Dienste in docker-compose.yml ergaenzen: Ollama (containerisiert, NVIDIA-GPU-Passthrough) und Gitea (Self-hosted-Git).
Purpose: Ollama vom Host-Prozess in einen Container verschieben, damit der Stack keine Host-seitigen Abhaengigkeiten mehr hat. Gitea als sechsten Dienst hinzufuegen.
Output: docker-compose.yml mit 6 Diensten. paperless-ai kommuniziert mit Ollama ueber das interne Docker-Netz statt ueber host.docker.internal.
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
@$HOME/.claude/get-shit-done/templates/summary.md
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
Bekannte Image-Namen fuer neue Dienste:
Ollama: ollama/ollama:latest
Gitea: gitea/gitea:latest
Ollama GPU-Passthrough (nvidia-container-toolkit erforderlich auf Debian 13):
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
paperless-ai OLLAMA_API_URL muss von http://host.docker.internal:11434
auf http://ollama:11434 geaendert werden.
- docker-compose.yml — vollstaendige aktuelle Konfiguration lesen, bevor etwas veraendert wird
Den Dienst ollama in docker-compose.yml ergaenzen. Exakt folgende Konfiguration verwenden:
ollama:
image: ollama/ollama:latest
container_name: paperless-ollama-1
restart: unless-stopped
ports:
- "11434:11434"
volumes:
- ollamamodels:/root/.ollama
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
Gleichzeitig im Dienst paperless-ai die Umgebungsvariable OLLAMA_API_URL hinzufuegen bzw. aktualisieren:
- OLLAMA_API_URL=http://ollama:11434
- OLLAMA_MODEL=llama3.2
- AI_PROVIDER=ollama
Den Dienst paperless-ai mit depends_on: [ollama] ergaenzen, damit Ollama zuerst startet.
Im volumes-Block am Ende der Datei ollamamodels: ergaenzen.
WICHTIG: Die bestehenden Dienste (broker, db, webserver, paperless-ai) NICHT veraendern ausser der depends_on- und environment-Ergaenzung bei paperless-ai.
- grep "ollama/ollama:latest" docker-compose.yml gibt mindestens eine Zeile aus
- grep "ollama:11434" docker-compose.yml gibt mindestens zwei Zeilen aus (ports + OLLAMA_API_URL)
- grep "nvidia" docker-compose.yml findet den capabilities-Eintrag
- grep "count: all" docker-compose.yml findet den GPU-Reservierungs-Block
- grep "ollamamodels" docker-compose.yml findet Volume-Deklaration und Volume-Mount
- grep "OLLAMA_API_URL=http://ollama:11434" docker-compose.yml findet den paperless-ai-Eintrag
- grep "depends_on" docker-compose.yml zeigt dass paperless-ai jetzt ollama als Abhaengigkeit hat
- docker-compose.yml — nach Task 1 nochmal lesen um den aktuellen Stand zu kennen
Den Dienst gitea in docker-compose.yml ergaenzen. Exakt folgende Konfiguration verwenden:
gitea:
image: gitea/gitea:latest
container_name: paperless-gitea-1
restart: unless-stopped
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=sqlite3
ports:
- "3001:3000"
- "222:22"
volumes:
- giteadata:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
Im volumes-Block am Ende der Datei giteadata: ergaenzen.
Hinweis: Gitea benutzt SQLite (keine externe DB-Abhaengigkeit). Port 3001 nach aussen, damit kein Konflikt mit paperless-ai auf 3000. SSH auf 222 statt 22 um Host-SSH freizulassen.
- grep "gitea/gitea:latest" docker-compose.yml gibt mindestens eine Zeile aus
- grep "3001:3000" docker-compose.yml bestaetigt Port-Mapping (kein Konflikt mit paperless-ai:3000)
- grep "giteadata" docker-compose.yml findet Volume-Deklaration und Volume-Mount
- grep "USER_UID=1000" docker-compose.yml bestaetigt UID-Konfiguration
- docker compose config 2>&1 | grep -c "^ [a-z]" gibt 6 oder mehr zurueck (6 Dienste)
- docker compose config laeuft ohne Fehler durch (valides YAML)
Vertrauensgrenzen
| Grenze | Beschreibung |
|---|---|
| Host-Netz → Docker-Netz | Ports 8000, 3000, 3001, 11434, 222 oeffentlich exponiert |
| paperless-ai → ollama | Internes Netz, kein TLS — vertrauenswuerdig weil gleiches Compose-Netz |
| Docker → NVIDIA-GPU | nvidia-container-toolkit vermittelt GPU-Zugriff aus Container |
STRIDE Bedrohungsregister
| Threat ID | Kategorie | Komponente | Disposition | Massnahme |
|---|---|---|---|---|
| T-01-01 | Information Disclosure | Ollama Port 11434 (oeffentlich) | mitigate | Ollama-Port nur auf localhost binden: 127.0.0.1:11434:11434 statt 11434:11434 — Modelle und Prompts bleiben lokal |
| T-01-02 | Elevation of Privilege | NVIDIA GPU-Passthrough | accept | nvidia-container-toolkit isoliert GPU-Zugriff; akzeptabel fuer Single-User-Setup |
| T-01-03 | Information Disclosure | Gitea SSH Port 222 | mitigate | In Firewall (ufw) nur auf vertrauenswuerdige IPs beschraenken; wird in Plan 03 (setup.sh) dokumentiert |
| T-01-04 | Tampering | paperless-ai ohne Authentifizierung auf :3000 | accept | Lokales Netz, kein oeffentliches Internet; cap_drop: ALL bereits gesetzt |
| T-01-05 | Information Disclosure | POSTGRES_PASSWORD=paperless (Klartext in Compose) | mitigate | In Plan 02 in docker-compose.env.template verschieben und aus Compose-Datei entfernen |
Nach Ausfuehren beider Tasks:
# YAML-Validierung
docker compose -f /Users/bmt/Documents/OhnePapier-v.0.0/docker-compose.yml config
# Alle 6 Dienste vorhanden
docker compose -f /Users/bmt/Documents/OhnePapier-v.0.0/docker-compose.yml config --services
# Erwartete Ausgabe: broker, db, gitea, ollama, paperless-ai, webserver
# GPU-Konfiguration korrekt
grep -A8 "deploy:" /Users/bmt/Documents/OhnePapier-v.0.0/docker-compose.yml
# Ollama-URL korrekt fuer internes Netz
grep "OLLAMA_API_URL" /Users/bmt/Documents/OhnePapier-v.0.0/docker-compose.yml
# Muss ausgeben: OLLAMA_API_URL=http://ollama:11434
- docker-compose.yml enthaelt exakt 6 Dienste: broker, db, webserver, paperless-ai, ollama, gitea
- docker compose config laeuft ohne Fehler (valides YAML)
- paperless-ai zeigt auf http://ollama:11434 (nicht auf host.docker.internal)
- Ollama hat nvidia GPU-Reservierung mit count: all und capabilities: [gpu]
- Gitea-Port 3001 kein Konflikt mit paperless-ai auf 3000
- Volumes: ollamamodels und giteadata deklariert