feat(librechat): install librechat
This commit is contained in:
246
README.md
246
README.md
@@ -62,6 +62,8 @@ A remotely accessible Kubernetes home lab with OIDC authentication. Build a mode
|
|||||||
|
|
||||||
### LLM & AI Applications (Optional)
|
### LLM & AI Applications (Optional)
|
||||||
|
|
||||||
|
- **[Ollama](https://ollama.com/)**: Local LLM inference server with GPU acceleration
|
||||||
|
- **[LibreChat](https://www.librechat.ai/)**: Web-based chat interface with multi-model support and MCP integration
|
||||||
- **[Langfuse](https://langfuse.com/)**: LLM observability and analytics platform for tracking and debugging AI applications
|
- **[Langfuse](https://langfuse.com/)**: LLM observability and analytics platform for tracking and debugging AI applications
|
||||||
|
|
||||||
### Orchestration (Optional)
|
### Orchestration (Optional)
|
||||||
@@ -116,21 +118,13 @@ Lightweight Kubernetes distribution optimized for edge computing:
|
|||||||
- **Production Ready**: Full Kubernetes functionality with minimal overhead
|
- **Production Ready**: Full Kubernetes functionality with minimal overhead
|
||||||
- **Easy Deployment**: Single binary installation with built-in ingress
|
- **Easy Deployment**: Single binary installation with built-in ingress
|
||||||
|
|
||||||
### Longhorn
|
### PostgreSQL
|
||||||
|
|
||||||
Enterprise-grade distributed storage system:
|
Production-ready relational database:
|
||||||
|
|
||||||
- **Highly Available**: Block storage with no single point of failure
|
- **High Availability**: Clustered deployment with CloudNativePG
|
||||||
- **Backup & Recovery**: Built-in disaster recovery capabilities
|
- **pgvector Extension**: Vector similarity search for AI/ML workloads
|
||||||
- **NFS Support**: Persistent volumes with NFS compatibility
|
- **Multi-Tenant**: Shared database for Keycloak and applications
|
||||||
|
|
||||||
### HashiCorp Vault
|
|
||||||
|
|
||||||
Centralized secrets management:
|
|
||||||
|
|
||||||
- **Secure Storage**: Encrypted secret storage with access control
|
|
||||||
- **Dynamic Secrets**: Automatic credential generation and rotation
|
|
||||||
- **External Secrets Integration**: Syncs with Kubernetes via External Secrets Operator
|
|
||||||
|
|
||||||
### Keycloak
|
### Keycloak
|
||||||
|
|
||||||
@@ -140,13 +134,21 @@ Open-source identity and access management:
|
|||||||
- **User Federation**: Identity brokering and external provider integration
|
- **User Federation**: Identity brokering and external provider integration
|
||||||
- **Group-Based Access**: Role and permission management
|
- **Group-Based Access**: Role and permission management
|
||||||
|
|
||||||
### PostgreSQL
|
### HashiCorp Vault
|
||||||
|
|
||||||
Production-ready relational database:
|
Centralized secrets management:
|
||||||
|
|
||||||
- **High Availability**: Clustered deployment with CloudNativePG
|
- **Secure Storage**: Encrypted secret storage with access control
|
||||||
- **pgvector Extension**: Vector similarity search for AI/ML workloads
|
- **Dynamic Secrets**: Automatic credential generation and rotation
|
||||||
- **Multi-Tenant**: Shared database for Keycloak and applications
|
- **External Secrets Integration**: Syncs with Kubernetes via External Secrets Operator
|
||||||
|
|
||||||
|
### External Secrets Operator
|
||||||
|
|
||||||
|
Kubernetes operator for secret synchronization:
|
||||||
|
|
||||||
|
- **Vault Integration**: Automatically syncs secrets from Vault to Kubernetes
|
||||||
|
- **Multiple Backends**: Supports various secret management systems
|
||||||
|
- **Secure Rotation**: Automatic secret lifecycle management
|
||||||
|
|
||||||
### Prometheus and Grafana
|
### Prometheus and Grafana
|
||||||
|
|
||||||
@@ -160,13 +162,27 @@ Comprehensive monitoring and observability stack:
|
|||||||
|
|
||||||
[📖 See Prometheus Documentation](./prometheus/README.md)
|
[📖 See Prometheus Documentation](./prometheus/README.md)
|
||||||
|
|
||||||
### External Secrets Operator
|
### Goldilocks
|
||||||
|
|
||||||
Kubernetes operator for secret synchronization:
|
Resource recommendation dashboard for right-sizing workloads:
|
||||||
|
|
||||||
- **Vault Integration**: Automatically syncs secrets from Vault to Kubernetes
|
- **VPA Integration**: Powered by Vertical Pod Autoscaler for metrics-based recommendations
|
||||||
- **Multiple Backends**: Supports various secret management systems
|
- **Visual Dashboard**: User-friendly interface for viewing resource recommendations
|
||||||
- **Secure Rotation**: Automatic secret lifecycle management
|
- **QoS Guidance**: Recommendations for Guaranteed, Burstable, and BestEffort classes
|
||||||
|
- **Monitoring-Only Mode**: Observes workloads without automatic scaling
|
||||||
|
- **Namespace-Based**: Enable monitoring per namespace with labels
|
||||||
|
|
||||||
|
[📖 See Goldilocks Documentation](./goldilocks/README.md)
|
||||||
|
|
||||||
|
[📖 See VPA Documentation](./vpa/README.md)
|
||||||
|
|
||||||
|
### Longhorn
|
||||||
|
|
||||||
|
Enterprise-grade distributed storage system:
|
||||||
|
|
||||||
|
- **Highly Available**: Block storage with no single point of failure
|
||||||
|
- **Backup & Recovery**: Built-in disaster recovery capabilities
|
||||||
|
- **NFS Support**: Persistent volumes with NFS compatibility
|
||||||
|
|
||||||
### MinIO
|
### MinIO
|
||||||
|
|
||||||
@@ -187,68 +203,6 @@ Multi-user platform for interactive computing:
|
|||||||
|
|
||||||
[📖 See JupyterHub Documentation](./jupyterhub/README.md)
|
[📖 See JupyterHub Documentation](./jupyterhub/README.md)
|
||||||
|
|
||||||
### MLflow
|
|
||||||
|
|
||||||
Machine learning lifecycle management platform:
|
|
||||||
|
|
||||||
- **Experiment Tracking**: Log parameters, metrics, and artifacts for ML experiments
|
|
||||||
- **Model Registry**: Version and manage ML models with deployment lifecycle
|
|
||||||
- **Keycloak Authentication**: OAuth2 integration with group-based access control
|
|
||||||
|
|
||||||
[📖 See MLflow Documentation](./mlflow/README.md)
|
|
||||||
|
|
||||||
### KServe
|
|
||||||
|
|
||||||
Model serving platform for deploying ML models on Kubernetes:
|
|
||||||
|
|
||||||
- **Multi-Framework Support**: TensorFlow, PyTorch, scikit-learn, XGBoost, MLflow, and more
|
|
||||||
- **MLflow Integration**: Deploy models directly from MLflow Model Registry
|
|
||||||
- **Inference Protocols**: REST and gRPC with v2 Open Inference Protocol
|
|
||||||
- **RawDeployment Mode**: Uses native Kubernetes Deployments without Knative dependency
|
|
||||||
|
|
||||||
[📖 See KServe Documentation](./kserve/README.md)
|
|
||||||
|
|
||||||
### Langfuse
|
|
||||||
|
|
||||||
LLM observability and analytics platform:
|
|
||||||
|
|
||||||
- **Trace Tracking**: Monitor LLM calls, chains, and agent executions with detailed traces
|
|
||||||
- **Prompt Management**: Version and test prompts with playground interface
|
|
||||||
- **Analytics**: Track costs, latency, and token usage across all LLM applications
|
|
||||||
- **Keycloak Authentication**: OAuth2 integration with automatic user provisioning
|
|
||||||
|
|
||||||
[📖 See Langfuse Documentation](./langfuse/README.md)
|
|
||||||
|
|
||||||
### Apache Superset
|
|
||||||
|
|
||||||
Modern business intelligence platform:
|
|
||||||
|
|
||||||
- **Rich Visualizations**: 40+ chart types including mixed charts, treemaps, and heatmaps
|
|
||||||
- **SQL Lab**: Powerful editor for complex queries and dataset creation
|
|
||||||
- **Keycloak & Trino**: OAuth2 authentication and Iceberg data lake integration
|
|
||||||
|
|
||||||
[📖 See Superset Documentation](./superset/README.md)
|
|
||||||
|
|
||||||
### Metabase
|
|
||||||
|
|
||||||
Lightweight business intelligence:
|
|
||||||
|
|
||||||
- **Simple Setup**: Quick configuration with clean, modern UI
|
|
||||||
- **Multiple Databases**: Connect to PostgreSQL, Trino, and more
|
|
||||||
- **Keycloak Authentication**: OAuth2 integration for user management
|
|
||||||
|
|
||||||
[📖 See Metabase Documentation](./metabase/README.md)
|
|
||||||
|
|
||||||
### Querybook
|
|
||||||
|
|
||||||
Big data querying UI with notebook interface:
|
|
||||||
|
|
||||||
- **Trino Integration**: SQL queries against multiple data sources with user impersonation
|
|
||||||
- **Notebook Interface**: Shareable datadocs with queries and visualizations
|
|
||||||
- **Real-time Execution**: WebSocket-based query progress updates
|
|
||||||
|
|
||||||
[📖 See Querybook Documentation](./querybook/README.md)
|
|
||||||
|
|
||||||
### Trino
|
### Trino
|
||||||
|
|
||||||
Fast distributed SQL query engine:
|
Fast distributed SQL query engine:
|
||||||
@@ -259,15 +213,15 @@ Fast distributed SQL query engine:
|
|||||||
|
|
||||||
[📖 See Trino Documentation](./trino/README.md)
|
[📖 See Trino Documentation](./trino/README.md)
|
||||||
|
|
||||||
### DataHub
|
### Querybook
|
||||||
|
|
||||||
Modern data catalog and metadata management:
|
Big data querying UI with notebook interface:
|
||||||
|
|
||||||
- **OIDC Integration**: Keycloak authentication for unified access
|
- **Trino Integration**: SQL queries against multiple data sources with user impersonation
|
||||||
- **Metadata Discovery**: Search and browse data assets across platforms
|
- **Notebook Interface**: Shareable datadocs with queries and visualizations
|
||||||
- **Lineage Tracking**: Visualize data flow and dependencies
|
- **Real-time Execution**: WebSocket-based query progress updates
|
||||||
|
|
||||||
[📖 See DataHub Documentation](./datahub/README.md)
|
[📖 See Querybook Documentation](./querybook/README.md)
|
||||||
|
|
||||||
### ClickHouse
|
### ClickHouse
|
||||||
|
|
||||||
@@ -309,15 +263,88 @@ Apache Iceberg REST Catalog:
|
|||||||
|
|
||||||
[📖 See Lakekeeper Documentation](./lakekeeper/README.md)
|
[📖 See Lakekeeper Documentation](./lakekeeper/README.md)
|
||||||
|
|
||||||
### Apache Airflow
|
### Apache Superset
|
||||||
|
|
||||||
Workflow orchestration platform:
|
Modern business intelligence platform:
|
||||||
|
|
||||||
- **DAG-Based**: Define data pipelines as code with Python
|
- **Rich Visualizations**: 40+ chart types including mixed charts, treemaps, and heatmaps
|
||||||
- **JupyterHub Integration**: Develop and test workflows in notebooks
|
- **SQL Lab**: Powerful editor for complex queries and dataset creation
|
||||||
- **Keycloak Authentication**: OAuth2 for user management
|
- **Keycloak & Trino**: OAuth2 authentication and Iceberg data lake integration
|
||||||
|
|
||||||
[📖 See Airflow Documentation](./airflow/README.md)
|
[📖 See Superset Documentation](./superset/README.md)
|
||||||
|
|
||||||
|
### Metabase
|
||||||
|
|
||||||
|
Lightweight business intelligence:
|
||||||
|
|
||||||
|
- **Simple Setup**: Quick configuration with clean, modern UI
|
||||||
|
- **Multiple Databases**: Connect to PostgreSQL, Trino, and more
|
||||||
|
- **Keycloak Authentication**: OAuth2 integration for user management
|
||||||
|
|
||||||
|
[📖 See Metabase Documentation](./metabase/README.md)
|
||||||
|
|
||||||
|
### DataHub
|
||||||
|
|
||||||
|
Modern data catalog and metadata management:
|
||||||
|
|
||||||
|
- **OIDC Integration**: Keycloak authentication for unified access
|
||||||
|
- **Metadata Discovery**: Search and browse data assets across platforms
|
||||||
|
- **Lineage Tracking**: Visualize data flow and dependencies
|
||||||
|
|
||||||
|
[📖 See DataHub Documentation](./datahub/README.md)
|
||||||
|
|
||||||
|
### MLflow
|
||||||
|
|
||||||
|
Machine learning lifecycle management platform:
|
||||||
|
|
||||||
|
- **Experiment Tracking**: Log parameters, metrics, and artifacts for ML experiments
|
||||||
|
- **Model Registry**: Version and manage ML models with deployment lifecycle
|
||||||
|
- **Keycloak Authentication**: OAuth2 integration with group-based access control
|
||||||
|
|
||||||
|
[📖 See MLflow Documentation](./mlflow/README.md)
|
||||||
|
|
||||||
|
### KServe
|
||||||
|
|
||||||
|
Model serving platform for deploying ML models on Kubernetes:
|
||||||
|
|
||||||
|
- **Multi-Framework Support**: TensorFlow, PyTorch, scikit-learn, XGBoost, MLflow, and more
|
||||||
|
- **MLflow Integration**: Deploy models directly from MLflow Model Registry
|
||||||
|
- **Inference Protocols**: REST and gRPC with v2 Open Inference Protocol
|
||||||
|
- **RawDeployment Mode**: Uses native Kubernetes Deployments without Knative dependency
|
||||||
|
|
||||||
|
[📖 See KServe Documentation](./kserve/README.md)
|
||||||
|
|
||||||
|
### Ollama
|
||||||
|
|
||||||
|
Local LLM inference server:
|
||||||
|
|
||||||
|
- **Local Inference**: Run LLMs locally without external API dependencies
|
||||||
|
- **GPU Acceleration**: NVIDIA GPU support with automatic runtime configuration
|
||||||
|
- **Model Library**: Access to thousands of open-source models (Llama, Qwen, DeepSeek, etc.)
|
||||||
|
- **OpenAI-Compatible API**: Drop-in replacement for OpenAI API endpoints
|
||||||
|
|
||||||
|
[📖 See Ollama Documentation](./ollama/README.md)
|
||||||
|
|
||||||
|
### LibreChat
|
||||||
|
|
||||||
|
Web-based chat interface for LLMs:
|
||||||
|
|
||||||
|
- **Multi-Model Support**: Connect to Ollama, OpenAI, Anthropic, and custom endpoints
|
||||||
|
- **MCP Integration**: Model Context Protocol support for web search and tools
|
||||||
|
- **Keycloak Authentication**: OAuth2 integration for user management
|
||||||
|
|
||||||
|
[📖 See LibreChat Documentation](./librechat/README.md)
|
||||||
|
|
||||||
|
### Langfuse
|
||||||
|
|
||||||
|
LLM observability and analytics platform:
|
||||||
|
|
||||||
|
- **Trace Tracking**: Monitor LLM calls, chains, and agent executions with detailed traces
|
||||||
|
- **Prompt Management**: Version and test prompts with playground interface
|
||||||
|
- **Analytics**: Track costs, latency, and token usage across all LLM applications
|
||||||
|
- **Keycloak Authentication**: OAuth2 integration with automatic user provisioning
|
||||||
|
|
||||||
|
[📖 See Langfuse Documentation](./langfuse/README.md)
|
||||||
|
|
||||||
### Dagster
|
### Dagster
|
||||||
|
|
||||||
@@ -329,6 +356,16 @@ Modern data orchestration platform:
|
|||||||
|
|
||||||
[📖 See Dagster Documentation](./dagster/README.md)
|
[📖 See Dagster Documentation](./dagster/README.md)
|
||||||
|
|
||||||
|
### Apache Airflow
|
||||||
|
|
||||||
|
Workflow orchestration platform:
|
||||||
|
|
||||||
|
- **DAG-Based**: Define data pipelines as code with Python
|
||||||
|
- **JupyterHub Integration**: Develop and test workflows in notebooks
|
||||||
|
- **Keycloak Authentication**: OAuth2 for user management
|
||||||
|
|
||||||
|
[📖 See Airflow Documentation](./airflow/README.md)
|
||||||
|
|
||||||
### Fairwinds Polaris
|
### Fairwinds Polaris
|
||||||
|
|
||||||
Kubernetes configuration validation and best practices auditing:
|
Kubernetes configuration validation and best practices auditing:
|
||||||
@@ -340,20 +377,6 @@ Kubernetes configuration validation and best practices auditing:
|
|||||||
|
|
||||||
[📖 See Fairwinds Polaris Documentation](./fairwinds-polaris/README.md)
|
[📖 See Fairwinds Polaris Documentation](./fairwinds-polaris/README.md)
|
||||||
|
|
||||||
### Goldilocks
|
|
||||||
|
|
||||||
Resource recommendation dashboard for right-sizing workloads:
|
|
||||||
|
|
||||||
- **VPA Integration**: Powered by Vertical Pod Autoscaler for metrics-based recommendations
|
|
||||||
- **Visual Dashboard**: User-friendly interface for viewing resource recommendations
|
|
||||||
- **QoS Guidance**: Recommendations for Guaranteed, Burstable, and BestEffort classes
|
|
||||||
- **Monitoring-Only Mode**: Observes workloads without automatic scaling
|
|
||||||
- **Namespace-Based**: Enable monitoring per namespace with labels
|
|
||||||
|
|
||||||
[📖 See Goldilocks Documentation](./goldilocks/README.md)
|
|
||||||
|
|
||||||
[📖 See VPA Documentation](./vpa/README.md)
|
|
||||||
|
|
||||||
## Common Operations
|
## Common Operations
|
||||||
|
|
||||||
### User Management
|
### User Management
|
||||||
@@ -462,6 +485,7 @@ kubectl --context yourpc-oidc get nodes
|
|||||||
# JupyterHub: https://jupyter.yourdomain.com
|
# JupyterHub: https://jupyter.yourdomain.com
|
||||||
# MLflow: https://mlflow.yourdomain.com
|
# MLflow: https://mlflow.yourdomain.com
|
||||||
# Langfuse: https://langfuse.yourdomain.com
|
# Langfuse: https://langfuse.yourdomain.com
|
||||||
|
# LibreChat: https://chat.yourdomain.com
|
||||||
```
|
```
|
||||||
|
|
||||||
## Customization
|
## Customization
|
||||||
|
|||||||
1
justfile
1
justfile
@@ -22,6 +22,7 @@ mod k8s
|
|||||||
mod kserve
|
mod kserve
|
||||||
mod langfuse
|
mod langfuse
|
||||||
mod lakekeeper
|
mod lakekeeper
|
||||||
|
mod librechat
|
||||||
mod longhorn
|
mod longhorn
|
||||||
mod metabase
|
mod metabase
|
||||||
mod mlflow
|
mod mlflow
|
||||||
|
|||||||
2
librechat/.gitignore
vendored
Normal file
2
librechat/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
values.yaml
|
||||||
|
librechat-config.yaml
|
||||||
227
librechat/README.md
Normal file
227
librechat/README.md
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
# LibreChat
|
||||||
|
|
||||||
|
Web-based chat interface for interacting with LLMs:
|
||||||
|
|
||||||
|
- **Multi-Model Support**: Connect to Ollama, OpenAI, Anthropic, and custom endpoints
|
||||||
|
- **MCP Integration**: Model Context Protocol for web search and external tools
|
||||||
|
- **Keycloak Authentication**: OAuth2/OIDC integration for user management
|
||||||
|
- **Conversation History**: MongoDB-backed chat history with search via Meilisearch
|
||||||
|
- **Persistent Storage**: User-uploaded images stored persistently
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- [Keycloak](../keycloak/README.md) for OIDC authentication
|
||||||
|
- [Vault](../vault/README.md) for secrets management
|
||||||
|
- [Ollama](../ollama/README.md) for local LLM inference (optional)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just librechat::install
|
||||||
|
```
|
||||||
|
|
||||||
|
During installation, you will be prompted for:
|
||||||
|
|
||||||
|
- **LibreChat host**: FQDN for LibreChat (e.g., `chat.example.com`)
|
||||||
|
- **Keycloak host**: FQDN for Keycloak (e.g., `auth.example.com`)
|
||||||
|
- **Tavily MCP**: Enable web search via Tavily API (requires API key)
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
| -------- | ------- | ----------- |
|
||||||
|
| `LIBRECHAT_NAMESPACE` | `librechat` | Kubernetes namespace |
|
||||||
|
| `LIBRECHAT_CHART_VERSION` | `1.9.3` | Helm chart version |
|
||||||
|
| `LIBRECHAT_HOST` | (prompt) | LibreChat FQDN |
|
||||||
|
| `LIBRECHAT_OIDC_CLIENT_ID` | `librechat` | Keycloak client ID |
|
||||||
|
| `KEYCLOAK_HOST` | (prompt) | Keycloak FQDN |
|
||||||
|
| `KEYCLOAK_REALM` | `buunstack` | Keycloak realm |
|
||||||
|
| `OLLAMA_HOST` | `ollama.ollama.svc.cluster.local` | Ollama service host |
|
||||||
|
| `TAVILY_MCP_ENABLED` | (prompt) | Enable Tavily MCP (`true`/`false`) |
|
||||||
|
|
||||||
|
### Example with Environment Variables
|
||||||
|
|
||||||
|
```bash
|
||||||
|
LIBRECHAT_HOST=chat.example.com \
|
||||||
|
KEYCLOAK_HOST=auth.example.com \
|
||||||
|
TAVILY_MCP_ENABLED=true \
|
||||||
|
just librechat::install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ollama Integration
|
||||||
|
|
||||||
|
LibreChat automatically connects to Ollama using the internal Kubernetes service
|
||||||
|
URL. The default models configured are:
|
||||||
|
|
||||||
|
- `qwen3:8b`
|
||||||
|
- `deepseek-r1:8b`
|
||||||
|
|
||||||
|
LibreChat fetches the available model list from Ollama, so any models you pull
|
||||||
|
will be available.
|
||||||
|
|
||||||
|
## MCP (Model Context Protocol)
|
||||||
|
|
||||||
|
LibreChat supports MCP servers for extending model capabilities with external tools.
|
||||||
|
|
||||||
|
### Tavily Web Search
|
||||||
|
|
||||||
|
When `TAVILY_MCP_ENABLED=true`, LibreChat can search the web using Tavily API:
|
||||||
|
|
||||||
|
1. Get a Tavily API key from [tavily.com](https://tavily.com/)
|
||||||
|
2. During installation, enter the API key when prompted (stored in Vault)
|
||||||
|
3. In the chat interface, select "tavily" from the MCP Servers dropdown
|
||||||
|
4. The model can now search the web to answer questions
|
||||||
|
|
||||||
|
### Adding Custom MCP Servers
|
||||||
|
|
||||||
|
Edit `librechat-config.gomplate.yaml` to add additional MCP servers:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
mcpServers:
|
||||||
|
tavily:
|
||||||
|
command: npx
|
||||||
|
args:
|
||||||
|
- "-y"
|
||||||
|
- "tavily-mcp@latest"
|
||||||
|
env:
|
||||||
|
TAVILY_API_KEY: "${TAVILY_API_KEY}"
|
||||||
|
filesystem:
|
||||||
|
command: npx
|
||||||
|
args:
|
||||||
|
- "-y"
|
||||||
|
- "@anthropic/mcp-server-filesystem"
|
||||||
|
- "/app/data"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Adding API Providers
|
||||||
|
|
||||||
|
Edit `librechat-config.gomplate.yaml` to add OpenAI, Anthropic, or other providers:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
endpoints:
|
||||||
|
openAI:
|
||||||
|
apiKey: "${OPENAI_API_KEY}"
|
||||||
|
models:
|
||||||
|
default:
|
||||||
|
- gpt-4o
|
||||||
|
- gpt-4o-mini
|
||||||
|
fetch: true
|
||||||
|
|
||||||
|
anthropic:
|
||||||
|
apiKey: "${ANTHROPIC_API_KEY}"
|
||||||
|
models:
|
||||||
|
default:
|
||||||
|
- claude-sonnet-4-20250514
|
||||||
|
- claude-3-5-haiku-20241022
|
||||||
|
```
|
||||||
|
|
||||||
|
Store the API keys in Kubernetes secrets and reference them in `values.gomplate.yaml`.
|
||||||
|
|
||||||
|
## Operations
|
||||||
|
|
||||||
|
### Check Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just librechat::status
|
||||||
|
```
|
||||||
|
|
||||||
|
### View Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just librechat::logs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Restart
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just librechat::restart
|
||||||
|
```
|
||||||
|
|
||||||
|
## Upgrade
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just librechat::upgrade
|
||||||
|
```
|
||||||
|
|
||||||
|
## Uninstall
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just librechat::uninstall
|
||||||
|
```
|
||||||
|
|
||||||
|
This removes the Helm release, namespace, and Keycloak client. Vault secrets
|
||||||
|
are preserved.
|
||||||
|
|
||||||
|
To delete Vault secrets:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just vault::delete librechat/credentials
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
LibreChat deployment includes:
|
||||||
|
|
||||||
|
- **LibreChat**: Main application (Node.js)
|
||||||
|
- **MongoDB**: Conversation and user data storage
|
||||||
|
- **Meilisearch**: Full-text search for conversations
|
||||||
|
|
||||||
|
All components run with Pod Security Standards set to `restricted`.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### OIDC Login Fails
|
||||||
|
|
||||||
|
**Symptom**: Redirect loop or error after Keycloak login
|
||||||
|
|
||||||
|
**Check**:
|
||||||
|
|
||||||
|
1. Verify `DOMAIN_CLIENT` and `DOMAIN_SERVER` match your LibreChat URL
|
||||||
|
2. Check Keycloak client redirect URI matches `https://<host>/oauth/openid/callback`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just keycloak::get-client buunstack librechat
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ollama Models Not Showing
|
||||||
|
|
||||||
|
**Symptom**: No models available in the model selector
|
||||||
|
|
||||||
|
**Check**:
|
||||||
|
|
||||||
|
1. Verify Ollama is running: `just ollama::status`
|
||||||
|
2. Check Ollama has models: `just ollama::list`
|
||||||
|
3. Check LibreChat logs for connection errors: `just librechat::logs`
|
||||||
|
|
||||||
|
### MCP Not Working
|
||||||
|
|
||||||
|
**Symptom**: MCP server not available in dropdown
|
||||||
|
|
||||||
|
**Check**:
|
||||||
|
|
||||||
|
1. Verify Tavily secret exists:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get secret tavily-api-key -n librechat
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Check for MCP errors in logs:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just librechat::logs | grep -i mcp
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Verify `librechat-config` ConfigMap has MCP configuration:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get configmap librechat-config -n librechat -o yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [LibreChat Website](https://www.librechat.ai/)
|
||||||
|
- [LibreChat Documentation](https://www.librechat.ai/docs)
|
||||||
|
- [LibreChat GitHub](https://github.com/danny-avila/LibreChat)
|
||||||
|
- [LibreChat Helm Chart](https://github.com/danny-avila/librechat-helm)
|
||||||
|
- [Model Context Protocol](https://modelcontextprotocol.io/)
|
||||||
|
- [Tavily API](https://tavily.com/)
|
||||||
309
librechat/justfile
Normal file
309
librechat/justfile
Normal file
@@ -0,0 +1,309 @@
|
|||||||
|
set fallback := true
|
||||||
|
|
||||||
|
export LIBRECHAT_NAMESPACE := env("LIBRECHAT_NAMESPACE", "librechat")
|
||||||
|
export LIBRECHAT_CHART_VERSION := env("LIBRECHAT_CHART_VERSION", "1.9.3")
|
||||||
|
export LIBRECHAT_HOST := env("LIBRECHAT_HOST", "")
|
||||||
|
export LIBRECHAT_OIDC_CLIENT_ID := env("LIBRECHAT_OIDC_CLIENT_ID", "librechat")
|
||||||
|
export KEYCLOAK_REALM := env("KEYCLOAK_REALM", "buunstack")
|
||||||
|
export KEYCLOAK_HOST := env("KEYCLOAK_HOST", "")
|
||||||
|
export K8S_VAULT_NAMESPACE := env("K8S_VAULT_NAMESPACE", "vault")
|
||||||
|
export EXTERNAL_SECRETS_NAMESPACE := env("EXTERNAL_SECRETS_NAMESPACE", "external-secrets")
|
||||||
|
export OLLAMA_NAMESPACE := env("OLLAMA_NAMESPACE", "ollama")
|
||||||
|
export OLLAMA_HOST := env("OLLAMA_HOST", "ollama.ollama.svc.cluster.local")
|
||||||
|
export TAVILY_MCP_ENABLED := env("TAVILY_MCP_ENABLED", "")
|
||||||
|
|
||||||
|
[private]
|
||||||
|
default:
|
||||||
|
@just --list --unsorted --list-submodules
|
||||||
|
|
||||||
|
# Create LibreChat namespace
|
||||||
|
create-namespace:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
if ! kubectl get namespace ${LIBRECHAT_NAMESPACE} &>/dev/null; then
|
||||||
|
kubectl create namespace ${LIBRECHAT_NAMESPACE}
|
||||||
|
fi
|
||||||
|
kubectl label namespace ${LIBRECHAT_NAMESPACE} \
|
||||||
|
pod-security.kubernetes.io/enforce=restricted \
|
||||||
|
pod-security.kubernetes.io/enforce-version=latest \
|
||||||
|
pod-security.kubernetes.io/warn=restricted \
|
||||||
|
pod-security.kubernetes.io/warn-version=latest \
|
||||||
|
--overwrite
|
||||||
|
|
||||||
|
# Delete LibreChat namespace
|
||||||
|
delete-namespace:
|
||||||
|
kubectl delete namespace ${LIBRECHAT_NAMESPACE} --ignore-not-found
|
||||||
|
|
||||||
|
# Generate credentials and store in Vault
|
||||||
|
generate-credentials:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
if just vault::exist librechat/credentials &>/dev/null; then
|
||||||
|
echo "LibreChat credentials already exist in Vault"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "Generating LibreChat credentials..."
|
||||||
|
CREDS_KEY=$(openssl rand -hex 32)
|
||||||
|
CREDS_IV=$(openssl rand -hex 16)
|
||||||
|
JWT_SECRET=$(openssl rand -hex 32)
|
||||||
|
JWT_REFRESH_SECRET=$(openssl rand -hex 32)
|
||||||
|
MEILI_MASTER_KEY=$(openssl rand -hex 32)
|
||||||
|
OPENID_SESSION_SECRET=$(openssl rand -hex 32)
|
||||||
|
|
||||||
|
just vault::put librechat/credentials \
|
||||||
|
creds_key="${CREDS_KEY}" \
|
||||||
|
creds_iv="${CREDS_IV}" \
|
||||||
|
jwt_secret="${JWT_SECRET}" \
|
||||||
|
jwt_refresh_secret="${JWT_REFRESH_SECRET}" \
|
||||||
|
meili_master_key="${MEILI_MASTER_KEY}" \
|
||||||
|
openid_session_secret="${OPENID_SESSION_SECRET}"
|
||||||
|
echo "Credentials stored in Vault"
|
||||||
|
|
||||||
|
# Create Keycloak client for LibreChat
|
||||||
|
create-keycloak-client:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
while [ -z "${LIBRECHAT_HOST}" ]; do
|
||||||
|
LIBRECHAT_HOST=$(
|
||||||
|
gum input --prompt="LibreChat host (FQDN): " --width=100 \
|
||||||
|
--placeholder="e.g., chat.example.com"
|
||||||
|
)
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Creating Keycloak client for LibreChat..."
|
||||||
|
|
||||||
|
just keycloak::delete-client ${KEYCLOAK_REALM} ${LIBRECHAT_OIDC_CLIENT_ID} || true
|
||||||
|
|
||||||
|
CLIENT_SECRET=$(just utils::random-password)
|
||||||
|
|
||||||
|
just keycloak::create-client \
|
||||||
|
realm=${KEYCLOAK_REALM} \
|
||||||
|
client_id=${LIBRECHAT_OIDC_CLIENT_ID} \
|
||||||
|
redirect_url="https://${LIBRECHAT_HOST}/oauth/openid/callback" \
|
||||||
|
client_secret="${CLIENT_SECRET}"
|
||||||
|
|
||||||
|
just vault::put keycloak/client/librechat \
|
||||||
|
client_id="${LIBRECHAT_OIDC_CLIENT_ID}" \
|
||||||
|
client_secret="${CLIENT_SECRET}"
|
||||||
|
|
||||||
|
echo "Keycloak client created successfully"
|
||||||
|
echo "Client ID: ${LIBRECHAT_OIDC_CLIENT_ID}"
|
||||||
|
echo "Redirect URI: https://${LIBRECHAT_HOST}/oauth/openid/callback"
|
||||||
|
|
||||||
|
# Delete Keycloak client
|
||||||
|
delete-keycloak-client:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
echo "Deleting Keycloak client for LibreChat..."
|
||||||
|
just keycloak::delete-client ${KEYCLOAK_REALM} ${LIBRECHAT_OIDC_CLIENT_ID} || true
|
||||||
|
if just vault::exist keycloak/client/librechat &>/dev/null; then
|
||||||
|
just vault::delete keycloak/client/librechat
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create Kubernetes secrets
|
||||||
|
create-secrets:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
just create-namespace
|
||||||
|
|
||||||
|
CREDS_KEY=$(just vault::get librechat/credentials creds_key)
|
||||||
|
CREDS_IV=$(just vault::get librechat/credentials creds_iv)
|
||||||
|
JWT_SECRET=$(just vault::get librechat/credentials jwt_secret)
|
||||||
|
JWT_REFRESH_SECRET=$(just vault::get librechat/credentials jwt_refresh_secret)
|
||||||
|
MEILI_MASTER_KEY=$(just vault::get librechat/credentials meili_master_key)
|
||||||
|
OPENID_SESSION_SECRET=$(just vault::get librechat/credentials openid_session_secret)
|
||||||
|
OPENID_CLIENT_ID=$(just vault::get keycloak/client/librechat client_id)
|
||||||
|
OPENID_CLIENT_SECRET=$(just vault::get keycloak/client/librechat client_secret)
|
||||||
|
|
||||||
|
kubectl delete secret librechat-credentials-env -n ${LIBRECHAT_NAMESPACE} --ignore-not-found
|
||||||
|
kubectl create secret generic librechat-credentials-env -n ${LIBRECHAT_NAMESPACE} \
|
||||||
|
--from-literal=CREDS_KEY="${CREDS_KEY}" \
|
||||||
|
--from-literal=CREDS_IV="${CREDS_IV}" \
|
||||||
|
--from-literal=JWT_SECRET="${JWT_SECRET}" \
|
||||||
|
--from-literal=JWT_REFRESH_SECRET="${JWT_REFRESH_SECRET}" \
|
||||||
|
--from-literal=MEILI_MASTER_KEY="${MEILI_MASTER_KEY}" \
|
||||||
|
--from-literal=OPENID_SESSION_SECRET="${OPENID_SESSION_SECRET}" \
|
||||||
|
--from-literal=OPENID_CLIENT_ID="${OPENID_CLIENT_ID}" \
|
||||||
|
--from-literal=OPENID_CLIENT_SECRET="${OPENID_CLIENT_SECRET}"
|
||||||
|
|
||||||
|
echo "Secrets created successfully"
|
||||||
|
|
||||||
|
# Install LibreChat
|
||||||
|
install:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
while [ -z "${LIBRECHAT_HOST}" ]; do
|
||||||
|
LIBRECHAT_HOST=$(
|
||||||
|
gum input --prompt="LibreChat host (FQDN): " --width=100 \
|
||||||
|
--placeholder="e.g., chat.example.com"
|
||||||
|
)
|
||||||
|
done
|
||||||
|
|
||||||
|
while [ -z "${KEYCLOAK_HOST}" ]; do
|
||||||
|
KEYCLOAK_HOST=$(
|
||||||
|
gum input --prompt="Keycloak host (FQDN): " --width=100 \
|
||||||
|
--placeholder="e.g., auth.example.com"
|
||||||
|
)
|
||||||
|
done
|
||||||
|
|
||||||
|
# Ask about Tavily MCP if not set
|
||||||
|
if [ -z "${TAVILY_MCP_ENABLED}" ]; then
|
||||||
|
if gum confirm "Enable Tavily MCP for web search?"; then
|
||||||
|
TAVILY_MCP_ENABLED="true"
|
||||||
|
else
|
||||||
|
TAVILY_MCP_ENABLED="false"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check External Secrets Operator if Tavily is enabled
|
||||||
|
if [ "${TAVILY_MCP_ENABLED}" = "true" ]; then
|
||||||
|
if ! helm status external-secrets -n ${EXTERNAL_SECRETS_NAMESPACE} &>/dev/null; then
|
||||||
|
echo "Error: Tavily MCP requires External Secrets Operator, but it is not installed."
|
||||||
|
echo "Please install External Secrets Operator first or set TAVILY_MCP_ENABLED=false"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# Check if Tavily API key exists in Vault
|
||||||
|
if ! just vault::exist tavily/api &>/dev/null; then
|
||||||
|
echo "Tavily API key not found in Vault."
|
||||||
|
TAVILY_API_KEY=$(
|
||||||
|
gum input --prompt="Enter Tavily API Key: " --width=100 \
|
||||||
|
--placeholder="tvly-xxxxxxxxxxxxxxxx"
|
||||||
|
)
|
||||||
|
just vault::put tavily/api api_key="${TAVILY_API_KEY}"
|
||||||
|
echo "Tavily API key stored in Vault"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
just create-namespace
|
||||||
|
just generate-credentials
|
||||||
|
just create-keycloak-client
|
||||||
|
just create-secrets
|
||||||
|
|
||||||
|
# Create Tavily ExternalSecret if enabled
|
||||||
|
if [ "${TAVILY_MCP_ENABLED}" = "true" ]; then
|
||||||
|
gomplate -f tavily-external-secret.gomplate.yaml | kubectl apply -f -
|
||||||
|
echo "Waiting for Tavily secret to be synced..."
|
||||||
|
kubectl wait --for=condition=Ready externalsecret/tavily-api-key \
|
||||||
|
-n ${LIBRECHAT_NAMESPACE} --timeout=60s
|
||||||
|
fi
|
||||||
|
|
||||||
|
gomplate -f values.gomplate.yaml -o values.yaml
|
||||||
|
gomplate -f librechat-config.gomplate.yaml -o librechat-config.yaml
|
||||||
|
|
||||||
|
kubectl delete configmap librechat-config -n ${LIBRECHAT_NAMESPACE} --ignore-not-found
|
||||||
|
kubectl create configmap librechat-config -n ${LIBRECHAT_NAMESPACE} \
|
||||||
|
--from-file=librechat.yaml=librechat-config.yaml
|
||||||
|
|
||||||
|
helm upgrade --install librechat oci://ghcr.io/danny-avila/librechat-chart/librechat \
|
||||||
|
--version ${LIBRECHAT_CHART_VERSION} \
|
||||||
|
-n ${LIBRECHAT_NAMESPACE} \
|
||||||
|
--wait --timeout=10m \
|
||||||
|
-f values.yaml
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "LibreChat installed successfully"
|
||||||
|
echo "URL: https://${LIBRECHAT_HOST}"
|
||||||
|
echo "Login with Keycloak OIDC"
|
||||||
|
if [ "${TAVILY_MCP_ENABLED}" = "true" ]; then
|
||||||
|
echo "Tavily MCP: Enabled"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Upgrade LibreChat
|
||||||
|
upgrade:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
while [ -z "${LIBRECHAT_HOST}" ]; do
|
||||||
|
LIBRECHAT_HOST=$(
|
||||||
|
gum input --prompt="LibreChat host (FQDN): " --width=100 \
|
||||||
|
--placeholder="e.g., chat.example.com"
|
||||||
|
)
|
||||||
|
done
|
||||||
|
|
||||||
|
while [ -z "${KEYCLOAK_HOST}" ]; do
|
||||||
|
KEYCLOAK_HOST=$(
|
||||||
|
gum input --prompt="Keycloak host (FQDN): " --width=100 \
|
||||||
|
--placeholder="e.g., auth.example.com"
|
||||||
|
)
|
||||||
|
done
|
||||||
|
|
||||||
|
# Ask about Tavily MCP if not set
|
||||||
|
if [ -z "${TAVILY_MCP_ENABLED}" ]; then
|
||||||
|
if gum confirm "Enable Tavily MCP for web search?"; then
|
||||||
|
TAVILY_MCP_ENABLED="true"
|
||||||
|
else
|
||||||
|
TAVILY_MCP_ENABLED="false"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check External Secrets Operator if Tavily is enabled
|
||||||
|
if [ "${TAVILY_MCP_ENABLED}" = "true" ]; then
|
||||||
|
if ! helm status external-secrets -n ${EXTERNAL_SECRETS_NAMESPACE} &>/dev/null; then
|
||||||
|
echo "Error: Tavily MCP requires External Secrets Operator, but it is not installed."
|
||||||
|
echo "Please install External Secrets Operator first or set TAVILY_MCP_ENABLED=false"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# Check if Tavily API key exists in Vault
|
||||||
|
if ! just vault::exist tavily/api &>/dev/null; then
|
||||||
|
echo "Tavily API key not found in Vault."
|
||||||
|
TAVILY_API_KEY=$(
|
||||||
|
gum input --prompt="Enter Tavily API Key: " --width=100 \
|
||||||
|
--placeholder="tvly-xxxxxxxxxxxxxxxx"
|
||||||
|
)
|
||||||
|
just vault::put tavily/api api_key="${TAVILY_API_KEY}"
|
||||||
|
echo "Tavily API key stored in Vault"
|
||||||
|
fi
|
||||||
|
# Create/update Tavily ExternalSecret
|
||||||
|
gomplate -f tavily-external-secret.gomplate.yaml | kubectl apply -f -
|
||||||
|
echo "Waiting for Tavily secret to be synced..."
|
||||||
|
kubectl wait --for=condition=Ready externalsecret/tavily-api-key \
|
||||||
|
-n ${LIBRECHAT_NAMESPACE} --timeout=60s
|
||||||
|
fi
|
||||||
|
|
||||||
|
gomplate -f values.gomplate.yaml -o values.yaml
|
||||||
|
gomplate -f librechat-config.gomplate.yaml -o librechat-config.yaml
|
||||||
|
|
||||||
|
kubectl delete configmap librechat-config -n ${LIBRECHAT_NAMESPACE} --ignore-not-found
|
||||||
|
kubectl create configmap librechat-config -n ${LIBRECHAT_NAMESPACE} \
|
||||||
|
--from-file=librechat.yaml=librechat-config.yaml
|
||||||
|
|
||||||
|
helm upgrade librechat oci://ghcr.io/danny-avila/librechat-chart/librechat \
|
||||||
|
--version ${LIBRECHAT_CHART_VERSION} \
|
||||||
|
-n ${LIBRECHAT_NAMESPACE} \
|
||||||
|
--wait --timeout=10m \
|
||||||
|
-f values.yaml
|
||||||
|
|
||||||
|
echo "LibreChat upgraded successfully"
|
||||||
|
if [ "${TAVILY_MCP_ENABLED}" = "true" ]; then
|
||||||
|
echo "Tavily MCP: Enabled"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Uninstall LibreChat
|
||||||
|
uninstall:
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
helm uninstall librechat -n ${LIBRECHAT_NAMESPACE} --wait --ignore-not-found
|
||||||
|
just delete-namespace
|
||||||
|
|
||||||
|
just delete-keycloak-client || true
|
||||||
|
|
||||||
|
echo "LibreChat uninstalled successfully"
|
||||||
|
echo ""
|
||||||
|
echo "Note: Vault secrets were NOT deleted:"
|
||||||
|
echo " - librechat/credentials"
|
||||||
|
echo ""
|
||||||
|
echo "To delete, run:"
|
||||||
|
echo " just vault::delete librechat/credentials"
|
||||||
|
|
||||||
|
# Show LibreChat logs
|
||||||
|
logs:
|
||||||
|
kubectl logs -n ${LIBRECHAT_NAMESPACE} -l app.kubernetes.io/name=librechat -f
|
||||||
|
|
||||||
|
# Get pod status
|
||||||
|
status:
|
||||||
|
kubectl get pods -n ${LIBRECHAT_NAMESPACE}
|
||||||
|
|
||||||
|
# Restart LibreChat
|
||||||
|
restart:
|
||||||
|
kubectl rollout restart deployment/librechat-librechat -n ${LIBRECHAT_NAMESPACE}
|
||||||
89
librechat/librechat-config.gomplate.yaml
Normal file
89
librechat/librechat-config.gomplate.yaml
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
version: 1.2.1
|
||||||
|
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
interface:
|
||||||
|
endpointsMenu: true
|
||||||
|
modelSelect: true
|
||||||
|
parameters: true
|
||||||
|
sidePanel: true
|
||||||
|
presets: true
|
||||||
|
|
||||||
|
registration:
|
||||||
|
socialLogins:
|
||||||
|
- openid
|
||||||
|
|
||||||
|
endpoints:
|
||||||
|
# Ollama - Local LLM (configured as custom endpoint)
|
||||||
|
# Note: Name must NOT start with "ollama" to avoid legacy code issues
|
||||||
|
custom:
|
||||||
|
- name: "LocalLLM"
|
||||||
|
apiKey: "ollama"
|
||||||
|
baseURL: "http://{{ .Env.OLLAMA_HOST }}:11434/v1/"
|
||||||
|
models:
|
||||||
|
default:
|
||||||
|
- "qwen3:8b"
|
||||||
|
- "deepseek-r1:8b"
|
||||||
|
fetch: true
|
||||||
|
titleConvo: true
|
||||||
|
titleModel: "current_model"
|
||||||
|
summarize: false
|
||||||
|
summaryModel: "current_model"
|
||||||
|
forcePrompt: false
|
||||||
|
modelDisplayLabel: "LocalLLM"
|
||||||
|
|
||||||
|
# OpenAI - Optional, requires API key
|
||||||
|
# openAI:
|
||||||
|
# apiKey: "${OPENAI_API_KEY}"
|
||||||
|
# models:
|
||||||
|
# default:
|
||||||
|
# - gpt-4o
|
||||||
|
# - gpt-4o-mini
|
||||||
|
# fetch: true
|
||||||
|
|
||||||
|
# Anthropic - Optional, requires API key
|
||||||
|
# anthropic:
|
||||||
|
# apiKey: "${ANTHROPIC_API_KEY}"
|
||||||
|
# models:
|
||||||
|
# default:
|
||||||
|
# - claude-sonnet-4-20250514
|
||||||
|
# - claude-3-5-haiku-20241022
|
||||||
|
|
||||||
|
# Additional custom endpoints example (OpenRouter, etc.)
|
||||||
|
# - name: "OpenRouter"
|
||||||
|
# apiKey: "${OPENROUTER_KEY}"
|
||||||
|
# baseURL: "https://openrouter.ai/api/v1"
|
||||||
|
# models:
|
||||||
|
# default:
|
||||||
|
# - "anthropic/claude-sonnet-4"
|
||||||
|
# fetch: true
|
||||||
|
# titleConvo: true
|
||||||
|
# modelDisplayLabel: "OpenRouter"
|
||||||
|
|
||||||
|
# MCP Servers configuration
|
||||||
|
{{- if eq .Env.TAVILY_MCP_ENABLED "true" }}
|
||||||
|
mcpServers:
|
||||||
|
tavily:
|
||||||
|
command: npx
|
||||||
|
args:
|
||||||
|
- "-y"
|
||||||
|
- "tavily-mcp@latest"
|
||||||
|
env:
|
||||||
|
TAVILY_API_KEY: "${TAVILY_API_KEY}"
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
# Additional MCP Servers (examples)
|
||||||
|
# mcpServers:
|
||||||
|
# filesystem:
|
||||||
|
# command: npx
|
||||||
|
# args:
|
||||||
|
# - "-y"
|
||||||
|
# - "@anthropic/mcp-server-filesystem"
|
||||||
|
# - "/app/data"
|
||||||
|
# brave-search:
|
||||||
|
# command: npx
|
||||||
|
# args:
|
||||||
|
# - "-y"
|
||||||
|
# - "@anthropic/mcp-server-brave-search"
|
||||||
|
# env:
|
||||||
|
# BRAVE_API_KEY: "${BRAVE_API_KEY}"
|
||||||
22
librechat/tavily-external-secret.gomplate.yaml
Normal file
22
librechat/tavily-external-secret.gomplate.yaml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
apiVersion: external-secrets.io/v1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: tavily-api-key
|
||||||
|
namespace: {{ .Env.LIBRECHAT_NAMESPACE }}
|
||||||
|
spec:
|
||||||
|
refreshInterval: 1h
|
||||||
|
secretStoreRef:
|
||||||
|
name: vault-secret-store
|
||||||
|
kind: ClusterSecretStore
|
||||||
|
target:
|
||||||
|
name: tavily-api-key
|
||||||
|
creationPolicy: Owner
|
||||||
|
template:
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
TAVILY_API_KEY: "{{ `{{ .api_key }}` }}"
|
||||||
|
data:
|
||||||
|
- secretKey: api_key
|
||||||
|
remoteRef:
|
||||||
|
key: tavily/api
|
||||||
|
property: api_key
|
||||||
150
librechat/values.gomplate.yaml
Normal file
150
librechat/values.gomplate.yaml
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
global:
|
||||||
|
librechat:
|
||||||
|
existingSecretName: "librechat-credentials-env"
|
||||||
|
existingSecretApiKey: OPENAI_API_KEY
|
||||||
|
{{- if eq .Env.TAVILY_MCP_ENABLED "true" }}
|
||||||
|
env:
|
||||||
|
- name: TAVILY_API_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: tavily-api-key
|
||||||
|
key: TAVILY_API_KEY
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
librechat:
|
||||||
|
configEnv:
|
||||||
|
# Domain configuration (required for OIDC redirects)
|
||||||
|
DOMAIN_CLIENT: "https://{{ .Env.LIBRECHAT_HOST }}"
|
||||||
|
DOMAIN_SERVER: "https://{{ .Env.LIBRECHAT_HOST }}"
|
||||||
|
|
||||||
|
# Ollama endpoint (internal k8s service)
|
||||||
|
OLLAMA_BASE_URL: "http://{{ .Env.OLLAMA_HOST }}:11434"
|
||||||
|
|
||||||
|
# OpenID Connect / Keycloak
|
||||||
|
ALLOW_SOCIAL_LOGIN: "true"
|
||||||
|
OPENID_BUTTON_LABEL: "Login with Keycloak"
|
||||||
|
OPENID_ISSUER: "https://{{ .Env.KEYCLOAK_HOST }}/realms/{{ .Env.KEYCLOAK_REALM }}"
|
||||||
|
OPENID_CALLBACK_URL: "/oauth/openid/callback"
|
||||||
|
OPENID_SCOPE: "openid profile email"
|
||||||
|
|
||||||
|
# Optional: Role-based access control
|
||||||
|
# OPENID_REQUIRED_ROLE_PARAMETER_PATH: "realm_access.roles"
|
||||||
|
# OPENID_REQUIRED_ROLE_TOKEN_KIND: "access"
|
||||||
|
|
||||||
|
# Optional: Group sync from Keycloak roles
|
||||||
|
# OPENID_SYNC_GROUPS_FROM_TOKEN: "true"
|
||||||
|
# OPENID_GROUPS_CLAIM_PATH: "realm_access.roles"
|
||||||
|
# OPENID_GROUPS_TOKEN_KIND: "access"
|
||||||
|
|
||||||
|
# Disable email registration (use Keycloak only)
|
||||||
|
ALLOW_EMAIL_LOGIN: "false"
|
||||||
|
ALLOW_REGISTRATION: "false"
|
||||||
|
ALLOW_SOCIAL_REGISTRATION: "true"
|
||||||
|
|
||||||
|
# Debug (set to true for troubleshooting)
|
||||||
|
DEBUG_OPENID_REQUESTS: "false"
|
||||||
|
DEBUG_PLUGINS: "false"
|
||||||
|
|
||||||
|
existingSecretName: "librechat-credentials-env"
|
||||||
|
|
||||||
|
# Use external configmap for librechat.yaml
|
||||||
|
existingConfigYaml: "librechat-config"
|
||||||
|
|
||||||
|
imageVolume:
|
||||||
|
enabled: true
|
||||||
|
size: 10Gi
|
||||||
|
accessModes: ReadWriteOnce
|
||||||
|
|
||||||
|
image:
|
||||||
|
repository: danny-avila/librechat
|
||||||
|
registry: ghcr.io
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
|
podSecurityContext:
|
||||||
|
fsGroup: 2000
|
||||||
|
|
||||||
|
securityContext:
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 1000
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
|
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
port: 3080
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: "traefik"
|
||||||
|
annotations:
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
hosts:
|
||||||
|
- host: {{ .Env.LIBRECHAT_HOST }}
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
tls: []
|
||||||
|
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 512Mi
|
||||||
|
limits:
|
||||||
|
cpu: 1000m
|
||||||
|
memory: 1Gi
|
||||||
|
|
||||||
|
mongodb:
|
||||||
|
enabled: true
|
||||||
|
auth:
|
||||||
|
enabled: false
|
||||||
|
databases:
|
||||||
|
- LibreChat
|
||||||
|
image:
|
||||||
|
tag: "latest"
|
||||||
|
persistence:
|
||||||
|
size: 8Gi
|
||||||
|
podSecurityContext:
|
||||||
|
fsGroup: 1001
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
|
containerSecurityContext:
|
||||||
|
runAsUser: 1001
|
||||||
|
runAsNonRoot: true
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
|
||||||
|
meilisearch:
|
||||||
|
enabled: true
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
image:
|
||||||
|
tag: "v1.7.3"
|
||||||
|
auth:
|
||||||
|
existingMasterKeySecret: "librechat-credentials-env"
|
||||||
|
podSecurityContext:
|
||||||
|
fsGroup: 1000
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
|
containerSecurityContext:
|
||||||
|
runAsUser: 1000
|
||||||
|
runAsNonRoot: true
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
|
||||||
|
librechat-rag-api:
|
||||||
|
enabled: false
|
||||||
Reference in New Issue
Block a user