docs: rewrite README with structured overview and quick start guide
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.
This commit is contained in:
331
docs/openwebui.md
Normal file
331
docs/openwebui.md
Normal file
@@ -0,0 +1,331 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user