infra: deploy Open WebUI on hf-pdocker-01 with Ollama + Claude backends

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 14:13:16 -05:00
parent cd37bb9858
commit 59f529e3a7
6 changed files with 487 additions and 18 deletions
@@ -0,0 +1,244 @@
# Open WebUI Deployment Plan
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Deploy Open WebUI on hf-pdocker-01 with Ollama + Anthropic Claude backends, publicly accessible at `open.hobbs.farm`.
**Architecture:** Single-container Compose service on hf-pdocker-01. Traefik file-based dynamic config for HTTPS routing. NAS-backed persistent storage. Prometheus blackbox probes for monitoring.
**Tech Stack:** Open WebUI (ghcr.io/open-webui/open-webui:main), Traefik v3.6 (file provider), Prometheus blackbox exporter.
**Spec:** `docs/superpowers/specs/2026-03-11-openwebui-design.md`
---
## Chunk 1: Create Files and Deploy
### Task 1: Create Compose File
**Files:**
- Create: `compose/hf-pdocker-01/openwebui/docker-compose.yml`
- [ ] **Step 1: Create the compose file**
```yaml
services:
open-webui:
image: ghcr.io/open-webui/open-webui:main
container_name: open-webui
restart: unless-stopped
ports:
- "3010:8080"
env_file:
- .env
environment:
- TZ=America/Chicago
- OLLAMA_BASE_URL=http://192.168.86.196:11434
volumes:
- /mnt/docker-data/configs/openwebui:/app/backend/data
mem_limit: 1G
memswap_limit: 1G
labels:
- "com.centurylinklabs.watchtower.enable=false"
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:8080/health || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "3"
```
### Task 2: Create Traefik Dynamic Config
**Files:**
- Create: `stacks/traefik/dynamic/openwebui.yml`
- [ ] **Step 1: Create the Traefik dynamic route file**
```yaml
http:
routers:
openwebui:
rule: "Host(`open.hobbs.farm`)"
entryPoints:
- websecure
service: openwebui
tls:
certResolver: letsencrypt
openwebui-http:
rule: "Host(`open.hobbs.farm`)"
entryPoints:
- web
middlewares:
- openwebui-https-redirect
service: openwebui
middlewares:
openwebui-https-redirect:
redirectScheme:
scheme: https
permanent: true
services:
openwebui:
loadBalancer:
servers:
- url: "http://192.168.86.192:3010"
```
### Task 3: Deploy to hf-pdocker-01
Uses `docker-swarm-ops` agent. All steps run on hf-pdocker-01 via SSH.
- [ ] **Step 1: Create data directory on NAS**
```bash
ssh glyptic@192.168.86.192 "sudo mkdir -p /mnt/docker-data/configs/openwebui"
```
- [ ] **Step 2: Create compose directory on NAS**
```bash
ssh glyptic@192.168.86.192 "sudo mkdir -p /mnt/docker-data/compose/hf-pdocker-01/openwebui"
```
- [ ] **Step 3: Generate WEBUI_SECRET_KEY and create .env file**
```bash
SECRET=$(openssl rand -hex 32)
# Get ANTHROPIC_API_KEY from existing ai-agents .env on NAS
API_KEY=$(ssh glyptic@192.168.86.192 "grep ANTHROPIC_API_KEY /mnt/docker-data/compose/hf-pdocker-01/ai-agents/.env | cut -d= -f2")
ssh glyptic@192.168.86.192 "cat > /mnt/docker-data/compose/hf-pdocker-01/openwebui/.env << EOF
ANTHROPIC_API_KEY=$API_KEY
WEBUI_SECRET_KEY=$SECRET
EOF"
```
- [ ] **Step 4: SCP compose file to NAS**
```bash
scp compose/hf-pdocker-01/openwebui/docker-compose.yml glyptic@192.168.86.192:/mnt/docker-data/compose/hf-pdocker-01/openwebui/docker-compose.yml
```
- [ ] **Step 5: SCP Traefik dynamic config to NAS**
```bash
scp stacks/traefik/dynamic/openwebui.yml glyptic@192.168.86.192:/mnt/docker-data/traefik/dynamic/openwebui.yml
```
- [ ] **Step 6: Pull image and start container**
```bash
ssh glyptic@192.168.86.192 "cd /mnt/docker-data/compose/hf-pdocker-01/openwebui && docker compose pull && docker compose up -d"
```
- [ ] **Step 7: Verify container health**
```bash
ssh glyptic@192.168.86.192 "docker ps --filter name=open-webui --format 'table {{.Names}}\t{{.Status}}'"
```
Expected: `open-webui Up ... (healthy)` (may take up to 60s for healthcheck)
- [ ] **Step 8: Verify internal access**
```bash
ssh glyptic@192.168.86.192 "curl -sf -o /dev/null -w '%{http_code}' http://localhost:3010"
```
Expected: `200`
- [ ] **Step 9: Verify Traefik picked up the route**
```bash
curl -sf -o /dev/null -w '%{http_code}' https://open.hobbs.farm
```
Expected: `200` (Traefik auto-reloads file-based config)
- [ ] **Step 10: Verify Ollama connectivity from container**
```bash
ssh glyptic@192.168.86.192 "docker exec open-webui curl -sf http://192.168.86.196:11434/api/tags | head -c 200"
```
Expected: JSON response listing available Ollama models (llava:13b)
## Chunk 2: Monitoring and Documentation
### Task 4: Add Prometheus Blackbox Probes
**Files:**
- Modify: `stacks/monitoring/prometheus.yml`
- [ ] **Step 1: Add internal probe to http-pdocker01 job**
Add `- http://192.168.86.192:3010 # Open WebUI` to the `http-pdocker01` targets list (after the Alertmanager line, line 70).
- [ ] **Step 2: Add external probe to http-external job**
Add `- https://open.hobbs.farm # Open WebUI` to the `http-external` targets list (after the Gitea line, line 158).
- [ ] **Step 3: SCP updated prometheus.yml to NAS**
```bash
scp stacks/monitoring/prometheus.yml glyptic@192.168.86.192:/mnt/docker-data/configs/prometheus/prometheus.yml
```
- [ ] **Step 4: Hot-reload Prometheus**
```bash
ssh glyptic@192.168.86.192 "curl -X POST http://localhost:9095/-/reload"
```
- [ ] **Step 5: Verify probes are up**
```bash
ssh glyptic@192.168.86.192 "curl -s 'http://localhost:9095/api/v1/targets?state=active' | python3 -c \"import sys,json; targets=json.load(sys.stdin)['data']['activeTargets']; [print(t['labels'].get('instance','')) for t in targets if 'open' in t['labels'].get('instance','').lower()]\""
```
Expected: Two lines showing `http://192.168.86.192:3010` and `https://open.hobbs.farm`
### Task 5: Update CLAUDE.md
**Files:**
- Modify: `CLAUDE.md`
- [ ] **Step 1: Add Open WebUI to hf-pdocker-01 service list**
Add `├── [COMPOSE] Open WebUI (:3010) -- LLM chat UI (Ollama + Claude)` to the hf-pdocker-01 section.
- [ ] **Step 2: Add to internal services list**
Add `- Open WebUI: :3010` under hf-pdocker-01 internal services.
- [ ] **Step 3: Add to public services list**
Add `- Open WebUI: \`open.hobbs.farm\`` under Public Services.
### Task 6: Update MEMORY.md
**Files:**
- Modify: `/home/glyptic/.claude/projects/-mnt-c-Users-Jeremy-projects-docker/memory/MEMORY.md`
- [ ] **Step 1: Add Open WebUI memory entry**
Add section with deployment details: node, port, compose path, LLM backends, Traefik route, data path.
### Task 7: Update Wiki
- [ ] **Step 1: Launch documentation-keeper agent (background)**
Update wiki with new Open WebUI service documentation.
### Task 8: Commit
- [ ] **Step 1: Commit all new/modified files**
```bash
git add compose/hf-pdocker-01/openwebui/docker-compose.yml stacks/traefik/dynamic/openwebui.yml stacks/monitoring/prometheus.yml CLAUDE.md
git commit -m "infra: deploy Open WebUI on hf-pdocker-01 with Ollama + Claude backends"
```