Skip to content

Commit f97fa0a

Browse files
jeremyederclaude
andauthored
Feature/openwebui litellm deployment (#342)
this is a prototype UX for using openwebui to interact with the new amber codebase agent added in #337 --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 6b33b78 commit f97fa0a

File tree

20 files changed

+1488
-0
lines changed

20 files changed

+1488
-0
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Environment files with secrets
2+
.env
3+
*.env
4+
!.env.example
5+
6+
# Backup files
7+
*.bak
8+
backup*.tar.gz
9+
10+
# IDE files
11+
.vscode/
12+
.idea/
13+
*.swp
14+
*.swo
15+
16+
# OS files
17+
.DS_Store
18+
Thumbs.db

components/open-webui-llm/Makefile

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
.PHONY: help phase1-deploy phase1-clean phase1-logs phase1-test phase1-status
2+
3+
KUSTOMIZE := kubectl kustomize
4+
KUBECTL := kubectl
5+
NAMESPACE := openwebui
6+
7+
help:
8+
@echo "Open WebUI + LiteLLM Deployment"
9+
@echo "================================"
10+
@echo ""
11+
@echo "Phase 1 (Kind) Commands:"
12+
@echo " make phase1-deploy - Deploy Open WebUI + LiteLLM to Kind cluster"
13+
@echo " make phase1-status - Check deployment status"
14+
@echo " make phase1-logs - View Open WebUI logs"
15+
@echo " make phase1-test - Run health checks"
16+
@echo " make phase1-clean - Remove deployment"
17+
@echo ""
18+
@echo "Prerequisites:"
19+
@echo " 1. Kind cluster running (run: make -C ../../e2e setup-kind)"
20+
@echo " 2. API key configured (edit: overlays/phase1-kind/secrets.yaml)"
21+
@echo ""
22+
@echo "Access:"
23+
@echo " Docker: http://vteam.local/chat"
24+
@echo " Podman: http://vteam.local:8080/chat"
25+
26+
phase1-deploy:
27+
@echo "Deploying Phase 1 (Kind)..."
28+
@if ! $(KUBECTL) get namespace $(NAMESPACE) >/dev/null 2>&1; then \
29+
echo "Creating namespace $(NAMESPACE)..."; \
30+
fi
31+
$(KUSTOMIZE) overlays/phase1-kind | $(KUBECTL) apply -f -
32+
@echo ""
33+
@echo "Waiting for deployments to be ready..."
34+
$(KUBECTL) wait --for=condition=available --timeout=300s \
35+
deployment/litellm deployment/openwebui -n $(NAMESPACE) || true
36+
@echo ""
37+
@make phase1-status
38+
@echo ""
39+
@echo "✅ Phase 1 deployed!"
40+
@echo ""
41+
@echo "Access Open WebUI:"
42+
@echo " Docker: http://vteam.local/chat"
43+
@echo " Podman: http://vteam.local:8080/chat"
44+
45+
phase1-clean:
46+
@echo "Removing Phase 1 deployment..."
47+
$(KUSTOMIZE) overlays/phase1-kind | $(KUBECTL) delete -f - --ignore-not-found=true
48+
@echo "✅ Phase 1 cleaned up"
49+
50+
phase1-logs:
51+
@echo "Open WebUI logs (Ctrl+C to exit):"
52+
$(KUBECTL) logs -f -l app=openwebui -n $(NAMESPACE) --tail=50
53+
54+
phase1-logs-litellm:
55+
@echo "LiteLLM logs (Ctrl+C to exit):"
56+
$(KUBECTL) logs -f -l app=litellm -n $(NAMESPACE) --tail=50
57+
58+
phase1-test:
59+
@echo "Testing LiteLLM health..."
60+
@$(KUBECTL) exec -n $(NAMESPACE) deployment/openwebui -- \
61+
curl -s http://litellm-service:4000/health || echo "❌ LiteLLM health check failed"
62+
@echo ""
63+
@echo "Testing Open WebUI connectivity to LiteLLM..."
64+
@$(KUBECTL) exec -n $(NAMESPACE) deployment/openwebui -- \
65+
curl -s http://litellm-service:4000/v1/models -H "Authorization: Bearer sk-litellm-dev-master-key" || echo "❌ Model list failed"
66+
@echo ""
67+
@echo "✅ Health checks complete"
68+
69+
phase1-status:
70+
@echo "Pod Status:"
71+
@$(KUBECTL) get pods -n $(NAMESPACE)
72+
@echo ""
73+
@echo "Services:"
74+
@$(KUBECTL) get svc -n $(NAMESPACE)
75+
@echo ""
76+
@echo "Ingress:"
77+
@$(KUBECTL) get ingress -n $(NAMESPACE) || true
78+
@echo ""
79+
@echo "PVC:"
80+
@$(KUBECTL) get pvc -n $(NAMESPACE)
81+
82+
phase1-shell-webui:
83+
@echo "Opening shell in Open WebUI pod..."
84+
$(KUBECTL) exec -it -n $(NAMESPACE) deployment/openwebui -- /bin/sh
85+
86+
phase1-shell-litellm:
87+
@echo "Opening shell in LiteLLM pod..."
88+
$(KUBECTL) exec -it -n $(NAMESPACE) deployment/litellm -- /bin/sh
89+
90+
phase1-port-forward:
91+
@echo "Port forwarding Open WebUI to localhost:8080..."
92+
@echo "Access at: http://localhost:8080"
93+
$(KUBECTL) port-forward -n $(NAMESPACE) svc/openwebui-service 8080:8080
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
# Open WebUI + LiteLLM Deployment
2+
3+
A phased deployment of Open WebUI with LiteLLM proxy for chatting with Claude models, designed to work with the Ambient Code Platform's Kind cluster.
4+
5+
## Architecture
6+
7+
- **Phase 1**: Open WebUI → LiteLLM → Anthropic Claude API (simple proxy, no auth)
8+
- **Phase 2** (Future): Long-running Claude service for Amber agent integration
9+
10+
## Quick Start (Phase 1)
11+
12+
### Prerequisites
13+
14+
1. **Kind cluster running** with nginx-ingress:
15+
```bash
16+
cd ../../e2e
17+
./scripts/setup-kind.sh
18+
# Or if using Podman: CONTAINER_ENGINE=podman ./scripts/setup-kind.sh
19+
```
20+
21+
2. **Anthropic API key**: Get yours from [console.anthropic.com](https://console.anthropic.com)
22+
23+
### Deploy
24+
25+
1. **Configure API key**:
26+
```bash
27+
cd overlays/phase1-kind
28+
29+
# Edit secrets.yaml and replace sk-ant-YOUR-KEY-HERE with your actual key
30+
# Or use sed:
31+
sed -i.bak 's/sk-ant-YOUR-KEY-HERE/sk-ant-api01-YOUR-ACTUAL-KEY/g' secrets.yaml
32+
```
33+
34+
2. **Deploy to Kind**:
35+
```bash
36+
cd ../.. # Back to components/open-webui-llm/
37+
make phase1-deploy
38+
```
39+
40+
3. **Wait for pods** (automatic, but you can check):
41+
```bash
42+
make phase1-status
43+
```
44+
45+
4. **Access Open WebUI**:
46+
- **Docker**: http://vteam.local/chat
47+
- **Podman**: http://vteam.local:8080/chat
48+
49+
### Usage
50+
51+
1. Open the URL in your browser
52+
2. No login required (Phase 1 has auth disabled)
53+
3. Select a model from the dropdown:
54+
- `claude-sonnet-4-5` (recommended)
55+
- `claude-sonnet-3-7`
56+
- `claude-haiku-3-5`
57+
4. Start chatting!
58+
59+
## Management Commands
60+
61+
```bash
62+
# View logs
63+
make phase1-logs # Open WebUI logs
64+
make phase1-logs-litellm # LiteLLM logs
65+
66+
# Check status
67+
make phase1-status # All resources
68+
69+
# Run health checks
70+
make phase1-test # Verify LiteLLM and Open WebUI connectivity
71+
72+
# Clean up
73+
make phase1-clean # Remove all resources
74+
```
75+
76+
## Troubleshooting
77+
78+
### Pods not starting
79+
80+
```bash
81+
# Check pod status
82+
kubectl get pods -n openwebui
83+
84+
# View pod logs
85+
kubectl logs -n openwebui deployment/openwebui
86+
kubectl logs -n openwebui deployment/litellm
87+
88+
# Describe pod for events
89+
kubectl describe pod -n openwebui -l app=openwebui
90+
```
91+
92+
### LiteLLM errors
93+
94+
**"No API key provided"**:
95+
- Check secrets.yaml has your actual Anthropic API key
96+
- Verify secret was created: `kubectl get secret litellm-secrets -n openwebui -o yaml`
97+
98+
**"Model not found"**:
99+
- Check LiteLLM config: `kubectl get cm litellm-config -n openwebui -o yaml`
100+
- Verify model names match Anthropic's API
101+
102+
### Ingress not working
103+
104+
**Docker** (ports 80/443):
105+
```bash
106+
# Verify vteam.local resolves to 127.0.0.1
107+
grep vteam.local /etc/hosts
108+
109+
# Test ingress
110+
curl http://vteam.local/chat
111+
```
112+
113+
**Podman** (ports 8080/8443):
114+
```bash
115+
# Use port 8080
116+
curl http://vteam.local:8080/chat
117+
```
118+
119+
**Fallback - Port forwarding**:
120+
```bash
121+
# Access via localhost instead
122+
make phase1-port-forward
123+
# Then open: http://localhost:8080
124+
```
125+
126+
### PVC not binding
127+
128+
```bash
129+
# Check PVC status
130+
kubectl get pvc -n openwebui
131+
132+
# If pending, check storage class
133+
kubectl get sc
134+
135+
# Kind should have 'standard' storage class by default
136+
```
137+
138+
## Component Structure
139+
140+
```
141+
.
142+
├── base/ # Shared base manifests
143+
│ ├── namespace.yaml
144+
│ ├── rbac.yaml # ServiceAccounts
145+
│ ├── litellm/ # LiteLLM proxy
146+
│ │ ├── deployment.yaml
147+
│ │ ├── service.yaml
148+
│ │ └── configmap.yaml # Model routing
149+
│ ├── open-webui/ # Web UI
150+
│ │ ├── deployment.yaml
151+
│ │ ├── service.yaml
152+
│ │ └── pvc.yaml # Persistent storage
153+
│ └── kustomization.yaml
154+
155+
├── overlays/
156+
│ ├── phase1-kind/ # Phase 1: Simple deployment
157+
│ │ ├── kustomization.yaml
158+
│ │ ├── secrets.yaml # API keys (edit this!)
159+
│ │ ├── ingress.yaml # Nginx ingress
160+
│ │ └── pvc-patch.yaml # Reduced storage for Kind
161+
│ │
162+
│ └── phase2-production/ # Phase 2: Future (OAuth, Claude service)
163+
│ └── (planned)
164+
165+
├── docs/
166+
│ ├── PHASE1.md # Detailed Phase 1 guide
167+
│ └── PHASE2.md # Phase 2 migration plan
168+
169+
├── Makefile # Deployment automation
170+
└── README.md # This file
171+
```
172+
173+
## Data Flow
174+
175+
```
176+
User Browser → vteam.local/chat → Nginx Ingress → Open WebUI Service
177+
→ Open WebUI Pod → LiteLLM Service → LiteLLM Pod → Anthropic API
178+
```
179+
180+
## Phase 2 (Future)
181+
182+
Phase 2 will add:
183+
- **Authentication**: OAuth2 proxy for production use
184+
- **Claude Service**: Long-running Claude Code sessions
185+
- **Amber Integration**: Direct integration with Amber agent
186+
- **Production deployment**: OpenShift Routes, proper RBAC
187+
188+
See `docs/PHASE2.md` for migration plan (coming soon).
189+
190+
## Files You May Need to Edit
191+
192+
- **`overlays/phase1-kind/secrets.yaml`**: Add your Anthropic API key here (required)
193+
- **`base/litellm/configmap.yaml`**: Add more models or adjust LiteLLM settings
194+
- **`base/open-webui/deployment.yaml`**: Change resource limits or add environment variables
195+
196+
## Clean Up
197+
198+
```bash
199+
# Remove deployment but keep namespace
200+
make phase1-clean
201+
202+
# Remove namespace too
203+
kubectl delete namespace openwebui
204+
```
205+
206+
## Next Steps
207+
208+
1. Try chatting with different Claude models
209+
2. Explore Open WebUI settings (http://vteam.local/chat/settings)
210+
3. Review LiteLLM logs to see API calls: `make phase1-logs-litellm`
211+
4. Plan for Phase 2 migration (see `docs/PHASE2.md`)
212+
213+
## Support
214+
215+
- **Documentation**: See `docs/` directory
216+
- **Issues**: Create an issue in the main repository
217+
- **Logs**: Always check logs first: `make phase1-logs`
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
apiVersion: kustomize.config.k8s.io/v1beta1
2+
kind: Kustomization
3+
4+
metadata:
5+
name: openwebui-base
6+
7+
namespace: openwebui
8+
9+
# Common resources across all environments
10+
resources:
11+
- namespace.yaml
12+
- rbac.yaml
13+
- litellm/deployment.yaml
14+
- litellm/service.yaml
15+
- litellm/configmap.yaml
16+
- open-webui/deployment.yaml
17+
- open-webui/service.yaml
18+
- open-webui/pvc.yaml
19+
20+
# Default images (can be overridden by overlays)
21+
images:
22+
- name: ghcr.io/berriai/litellm
23+
newTag: main-latest
24+
- name: ghcr.io/open-webui/open-webui
25+
newTag: main
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
apiVersion: v1
2+
kind: ConfigMap
3+
metadata:
4+
name: litellm-config
5+
labels:
6+
app: litellm
7+
app.kubernetes.io/name: litellm
8+
app.kubernetes.io/component: proxy
9+
data:
10+
config.yaml: |
11+
model_list:
12+
- model_name: claude-sonnet-4-5
13+
litellm_params:
14+
model: anthropic/claude-sonnet-4-5-20250929
15+
api_key: os.environ/ANTHROPIC_API_KEY
16+
17+
- model_name: claude-sonnet-3-7
18+
litellm_params:
19+
model: anthropic/claude-3-7-sonnet-latest
20+
api_key: os.environ/ANTHROPIC_API_KEY
21+
22+
- model_name: claude-haiku-3-5
23+
litellm_params:
24+
model: anthropic/claude-3-5-haiku-20241022
25+
api_key: os.environ/ANTHROPIC_API_KEY
26+
27+
litellm_settings:
28+
drop_params: true
29+
success_callback: []
30+
failure_callback: []
31+
set_verbose: false
32+
33+
general_settings:
34+
master_key: os.environ/LITELLM_MASTER_KEY

0 commit comments

Comments
 (0)