Replaces the minimal project description with a comprehensive README including a component overview table, quick start instructions, common Ansible operations, and links to detailed documentation. Aligns with Red Panda Approval™ standards.
331 lines
11 KiB
Markdown
331 lines
11 KiB
Markdown
# Open WebUI
|
|
|
|
Open WebUI is an extensible, self-hosted AI interface that provides a web-based chat experience for interacting with LLMs. This document covers deployment, Casdoor SSO integration, and configuration.
|
|
|
|
## Architecture
|
|
|
|
### Components
|
|
|
|
| Component | Location | Purpose |
|
|
|-----------|----------|---------|
|
|
| Open WebUI | Native on Oberon | AI chat interface |
|
|
| PostgreSQL | Portia | Database with pgvector extension |
|
|
| Casdoor | Titania | SSO identity provider |
|
|
| HAProxy | Ariel | TLS termination, routing |
|
|
|
|
### Network Diagram
|
|
|
|
```
|
|
┌────────────────────────────────────────────────────────────────────┐
|
|
│ External Access │
|
|
│ https://openwebui.ouranos.helu.ca │
|
|
└───────────────────────────────┬────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌────────────────────────────────────────────────────────────────────┐
|
|
│ ariel.incus (HAProxy) │
|
|
│ TLS termination → proxy to oberon.incus:25588 │
|
|
└───────────────────────────────┬────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌────────────────────────────────────────────────────────────────────┐
|
|
│ oberon.incus │
|
|
│ │
|
|
│ ┌────────────────────────────────────────────────────────────────┐ │
|
|
│ │ Open WebUI (systemd) │ │
|
|
│ │ - Python 3.12 virtual environment │ │
|
|
│ │ - Port 25588 │ │
|
|
│ │ - OAuth/OIDC via Casdoor │ │
|
|
│ └────────────────────────────────────────────────────────────────┘ │
|
|
│ │ │ │
|
|
│ │ PostgreSQL │ OIDC │
|
|
│ ▼ ▼ │
|
|
│ portia.incus:5432 titania.incus:22081 │
|
|
│ (openwebui database) (Casdoor SSO) │
|
|
└────────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### Network Ports
|
|
|
|
| Port | Service | Access |
|
|
|------|---------|--------|
|
|
| 25588 | Open WebUI HTTP | Via HAProxy |
|
|
| 5432 | PostgreSQL | Internal (Portia) |
|
|
| 22081 | Casdoor | Internal (Titania) |
|
|
|
|
## Casdoor SSO Integration
|
|
|
|
Open WebUI uses native OAuth/OIDC to authenticate against Casdoor. Local signup is disabled—all users must authenticate through Casdoor.
|
|
|
|
### How It Works
|
|
|
|
1. User visits `https://openwebui.ouranos.helu.ca`
|
|
2. Open WebUI redirects to Casdoor login page
|
|
3. User authenticates with Casdoor credentials
|
|
4. Casdoor redirects back with authorization code
|
|
5. Open WebUI exchanges code for tokens and creates/updates user session
|
|
6. User email from Casdoor becomes their Open WebUI identity
|
|
|
|
### Configuration
|
|
|
|
OAuth settings are defined in host variables and rendered into the environment file:
|
|
|
|
**Host Variables** (`inventory/host_vars/oberon.incus.yml`):
|
|
```yaml
|
|
# OAuth/OIDC Configuration (Casdoor SSO)
|
|
openwebui_oauth_client_id: "{{ vault_openwebui_oauth_client_id }}"
|
|
openwebui_oauth_client_secret: "{{ vault_openwebui_oauth_client_secret }}"
|
|
openwebui_oauth_provider_name: "Casdoor"
|
|
openwebui_oauth_provider_url: "https://id.ouranos.helu.ca/.well-known/openid-configuration"
|
|
|
|
# Disable local authentication
|
|
openwebui_enable_signup: false
|
|
openwebui_enable_email_login: false
|
|
```
|
|
|
|
**Environment Variables** (rendered from `openwebui.env.j2`):
|
|
```bash
|
|
ENABLE_SIGNUP=false
|
|
ENABLE_EMAIL_LOGIN=false
|
|
ENABLE_OAUTH_SIGNUP=true
|
|
OAUTH_CLIENT_ID=<client-id>
|
|
OAUTH_CLIENT_SECRET=<client-secret>
|
|
OAUTH_PROVIDER_NAME=Casdoor
|
|
OPENID_PROVIDER_URL=https://id.ouranos.helu.ca/.well-known/openid-configuration
|
|
```
|
|
|
|
### Casdoor Application
|
|
|
|
The `app-openwebui` application is defined in `ansible/casdoor/init_data.json.j2`:
|
|
|
|
| Setting | Value |
|
|
|---------|-------|
|
|
| Name | `app-openwebui` |
|
|
| Display Name | Open WebUI |
|
|
| Redirect URI | `https://openwebui.ouranos.helu.ca/oauth/oidc/callback` |
|
|
| Grant Types | `authorization_code`, `refresh_token` |
|
|
| Token Format | JWT |
|
|
| Token Expiry | 168 hours (7 days) |
|
|
|
|
## Prerequisites
|
|
|
|
### 1. PostgreSQL Database
|
|
|
|
The `openwebui` database must exist on Portia with the `pgvector` extension:
|
|
|
|
```bash
|
|
ansible-playbook postgresql/deploy.yml
|
|
```
|
|
|
|
### 2. Casdoor SSO
|
|
|
|
Casdoor must be deployed and the `app-openwebui` application configured:
|
|
|
|
```bash
|
|
ansible-playbook casdoor/deploy.yml
|
|
```
|
|
|
|
### 3. Vault Secrets
|
|
|
|
Add to `ansible/inventory/group_vars/all/vault.yml`:
|
|
|
|
```yaml
|
|
# OpenWebUI
|
|
vault_openwebui_secret_key: "<random-secret>"
|
|
vault_openwebui_db_password: "<database-password>"
|
|
vault_openwebui_oauth_client_id: "<from-casdoor>"
|
|
vault_openwebui_oauth_client_secret: "<from-casdoor>"
|
|
|
|
# API Keys (optional)
|
|
vault_openwebui_openai_api_key: "<openai-key>"
|
|
vault_openwebui_anthropic_api_key: "<anthropic-key>"
|
|
vault_openwebui_groq_api_key: "<groq-key>"
|
|
vault_openwebui_mistral_api_key: "<mistral-key>"
|
|
```
|
|
|
|
Generate secrets:
|
|
```bash
|
|
# Secret key
|
|
openssl rand -hex 32
|
|
|
|
# Database password
|
|
openssl rand -base64 24
|
|
```
|
|
|
|
## Deployment
|
|
|
|
### Fresh Installation
|
|
|
|
```bash
|
|
cd ansible
|
|
|
|
# 1. Ensure PostgreSQL is deployed
|
|
ansible-playbook postgresql/deploy.yml
|
|
|
|
# 2. Deploy Casdoor (if not already deployed)
|
|
ansible-playbook casdoor/deploy.yml
|
|
|
|
# 3. Get OAuth credentials from Casdoor admin UI
|
|
# - Navigate to https://id.ouranos.helu.ca
|
|
# - Go to Applications → app-openwebui
|
|
# - Copy Client ID and Client Secret
|
|
# - Update vault.yml with these values
|
|
|
|
# 4. Deploy Open WebUI
|
|
ansible-playbook openwebui/deploy.yml
|
|
```
|
|
|
|
### Verify Deployment
|
|
|
|
```bash
|
|
# Check service status
|
|
ssh oberon.incus "sudo systemctl status openwebui"
|
|
|
|
# View logs
|
|
ssh oberon.incus "sudo journalctl -u openwebui -f"
|
|
|
|
# Test health endpoint
|
|
curl -s http://oberon.incus:25588/health
|
|
|
|
# Test via HAProxy
|
|
curl -s https://openwebui.ouranos.helu.ca/health
|
|
```
|
|
|
|
### Redeployment
|
|
|
|
To redeploy Open WebUI (preserves database):
|
|
|
|
```bash
|
|
ansible-playbook openwebui/deploy.yml
|
|
```
|
|
|
|
## Configuration Reference
|
|
|
|
### Host Variables
|
|
|
|
Located in `ansible/inventory/host_vars/oberon.incus.yml`:
|
|
|
|
```yaml
|
|
# Service account
|
|
openwebui_user: openwebui
|
|
openwebui_group: openwebui
|
|
openwebui_directory: /srv/openwebui
|
|
openwebui_port: 25588
|
|
openwebui_host: puck.incus
|
|
|
|
# Database
|
|
openwebui_db_host: portia.incus
|
|
openwebui_db_port: 5432
|
|
openwebui_db_name: openwebui
|
|
openwebui_db_user: openwebui
|
|
openwebui_db_password: "{{ vault_openwebui_db_password }}"
|
|
|
|
# Authentication (SSO only)
|
|
openwebui_enable_signup: false
|
|
openwebui_enable_email_login: false
|
|
|
|
# OAuth/OIDC (Casdoor)
|
|
openwebui_oauth_client_id: "{{ vault_openwebui_oauth_client_id }}"
|
|
openwebui_oauth_client_secret: "{{ vault_openwebui_oauth_client_secret }}"
|
|
openwebui_oauth_provider_name: "Casdoor"
|
|
openwebui_oauth_provider_url: "https://id.ouranos.helu.ca/.well-known/openid-configuration"
|
|
|
|
# API Keys
|
|
openwebui_openai_api_key: "{{ vault_openwebui_openai_api_key }}"
|
|
openwebui_anthropic_api_key: "{{ vault_openwebui_anthropic_api_key }}"
|
|
openwebui_groq_api_key: "{{ vault_openwebui_groq_api_key }}"
|
|
openwebui_mistral_api_key: "{{ vault_openwebui_mistral_api_key }}"
|
|
```
|
|
|
|
### Data Persistence
|
|
|
|
Open WebUI data locations:
|
|
```
|
|
/srv/openwebui/
|
|
├── .venv/ # Python virtual environment
|
|
├── .env # Environment configuration
|
|
└── data/ # User uploads, cache
|
|
```
|
|
|
|
Database (on Portia):
|
|
```
|
|
PostgreSQL: openwebui database with pgvector extension
|
|
```
|
|
|
|
## User Management
|
|
|
|
### First-Time Setup
|
|
|
|
After deployment, the first user to authenticate via Casdoor becomes an admin. Subsequent users get standard user roles.
|
|
|
|
### Promoting Users to Admin
|
|
|
|
1. Log in as an existing admin
|
|
2. Navigate to Admin Panel → Users
|
|
3. Select the user and change their role to Admin
|
|
|
|
### Existing Users Migration
|
|
|
|
If users were created before SSO was enabled:
|
|
- Users with matching email addresses will be linked automatically
|
|
- Users without matching emails must be recreated through Casdoor
|
|
|
|
## Troubleshooting
|
|
|
|
### Service Issues
|
|
|
|
```bash
|
|
# Check service status
|
|
ssh oberon.incus "sudo systemctl status openwebui"
|
|
|
|
# View logs
|
|
ssh oberon.incus "sudo journalctl -u openwebui -n 100"
|
|
|
|
# Restart service
|
|
ssh oberon.incus "sudo systemctl restart openwebui"
|
|
```
|
|
|
|
### OAuth/OIDC Issues
|
|
|
|
```bash
|
|
# Verify Casdoor is accessible
|
|
curl -s https://id.ouranos.helu.ca/.well-known/openid-configuration | jq
|
|
|
|
# Check redirect URI matches
|
|
# Must be: https://openwebui.ouranos.helu.ca/oauth/oidc/callback
|
|
|
|
# Verify client credentials in environment
|
|
ssh oberon.incus "sudo grep OAUTH /srv/openwebui/.env"
|
|
```
|
|
|
|
### Database Issues
|
|
|
|
```bash
|
|
# Test database connection
|
|
ssh oberon.incus "PGPASSWORD=<password> psql -h portia.incus -U openwebui -d openwebui -c '\dt'"
|
|
|
|
# Check pgvector extension
|
|
ssh portia.incus "sudo -u postgres psql -d openwebui -c '\dx'"
|
|
```
|
|
|
|
### Common Errors
|
|
|
|
| Error | Cause | Solution |
|
|
|-------|-------|----------|
|
|
| "Invalid redirect_uri" | Mismatch between Casdoor config and Open WebUI | Verify redirect URI in Casdoor matches exactly |
|
|
| "Invalid client credentials" | Wrong client ID/secret | Update vault with correct values from Casdoor |
|
|
| "OIDC discovery failed" | Casdoor unreachable | Check Casdoor is running on Titania |
|
|
| "Database connection failed" | PostgreSQL unreachable | Verify PostgreSQL on Portia, check network |
|
|
|
|
## Security Considerations
|
|
|
|
1. **SSO-only authentication** - Local signup disabled, all users authenticate through Casdoor
|
|
2. **API keys in vault** - All API keys stored encrypted in Ansible vault
|
|
3. **Database credentials** - Stored in vault, rendered to environment file with restrictive permissions (0600)
|
|
4. **Session security** - JWT tokens with 7-day expiry, managed by Casdoor
|
|
|
|
## Related Documentation
|
|
|
|
- [Casdoor SSO](services/casdoor.md) - Identity provider configuration
|
|
- [PostgreSQL](../ansible.md) - Database deployment
|
|
- [HAProxy](../terraform.md) - TLS termination and routing |