add openclaw
parent
d4f9eb3ab7
commit
26190c21db
@ -0,0 +1,23 @@
|
||||
# Patterns to ignore when building packages.
|
||||
# This supports shell glob matching, relative path matching, and
|
||||
# negation (prefixed with !). Only one pattern per line.
|
||||
.DS_Store
|
||||
# Common VCS dirs
|
||||
.git/
|
||||
.gitignore
|
||||
.bzr/
|
||||
.bzrignore
|
||||
.hg/
|
||||
.hgignore
|
||||
.svn/
|
||||
# Common backup files
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*.orig
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
.vscode/
|
||||
@ -0,0 +1,21 @@
|
||||
apiVersion: v2
|
||||
name: openclaw
|
||||
description: Personal AI assistant with multi-channel support
|
||||
type: application
|
||||
version: 1.0.0
|
||||
appVersion: "2026.2.1"
|
||||
keywords:
|
||||
- ai
|
||||
- assistant
|
||||
- whatsapp
|
||||
- telegram
|
||||
- discord
|
||||
- claude
|
||||
- chatgpt
|
||||
home: https://github.com/openclaw/openclaw
|
||||
sources:
|
||||
- https://github.com/openclaw/openclaw
|
||||
maintainers:
|
||||
- name: Openclaw Team
|
||||
url: https://docs.clawd.bot
|
||||
icon: https://github.com/openclaw/openclaw/raw/main/README-header.png
|
||||
@ -0,0 +1,253 @@
|
||||
# Publishing the Openclaw Helm Chart
|
||||
|
||||
This guide covers how to publish the Helm chart to make it available for users.
|
||||
|
||||
## Quick Start (Automated)
|
||||
|
||||
The chart is automatically published to GitHub Pages when you:
|
||||
|
||||
1. Update `charts/openclaw/Chart.yaml` version
|
||||
2. Commit and push to `main` branch
|
||||
3. GitHub Actions automatically packages and publishes
|
||||
|
||||
## Publishing Methods
|
||||
|
||||
### Option 1: GitHub Pages (Recommended)
|
||||
|
||||
#### Initial Setup
|
||||
|
||||
1. **Enable GitHub Pages:**
|
||||
- Go to repository Settings → Pages
|
||||
- Source: Deploy from a branch
|
||||
- Branch: `gh-pages` → `/ (root)`
|
||||
- Click Save
|
||||
|
||||
2. **Create gh-pages branch (first time only):**
|
||||
```bash
|
||||
# Create empty gh-pages branch
|
||||
git checkout --orphan gh-pages
|
||||
git rm -rf .
|
||||
echo "# Openclaw Helm Charts" > README.md
|
||||
git add README.md
|
||||
git commit -m "Initial gh-pages"
|
||||
git push origin gh-pages
|
||||
git checkout main
|
||||
```
|
||||
|
||||
3. **The workflow will automatically:**
|
||||
- Package the chart
|
||||
- Create a GitHub release
|
||||
- Update the chart repository index
|
||||
- Publish to GitHub Pages
|
||||
|
||||
#### Manual Publishing (if needed)
|
||||
|
||||
```bash
|
||||
# 1. Package the chart
|
||||
helm package charts/openclaw -d .cr-release-packages
|
||||
|
||||
# 2. Create index
|
||||
helm repo index .cr-release-packages --url https://openclaw.github.io/openclaw
|
||||
|
||||
# 3. Commit to gh-pages branch
|
||||
git checkout gh-pages
|
||||
cp .cr-release-packages/* .
|
||||
git add .
|
||||
git commit -m "Release chart version X.Y.Z"
|
||||
git push origin gh-pages
|
||||
git checkout main
|
||||
```
|
||||
|
||||
#### Usage for End Users
|
||||
|
||||
Once published, users can install via:
|
||||
|
||||
```bash
|
||||
# Add repo
|
||||
helm repo add openclaw https://openclaw.github.io/openclaw
|
||||
helm repo update
|
||||
|
||||
# Install
|
||||
helm install my-openclaw openclaw/openclaw
|
||||
```
|
||||
|
||||
### Option 2: OCI Registry (GitHub Container Registry)
|
||||
|
||||
Modern approach using OCI registries:
|
||||
|
||||
#### Setup
|
||||
|
||||
```bash
|
||||
# Login to GHCR
|
||||
echo $GITHUB_TOKEN | helm registry login ghcr.io -u USERNAME --password-stdin
|
||||
|
||||
# Package chart
|
||||
helm package charts/openclaw
|
||||
|
||||
# Push to GHCR
|
||||
helm push openclaw-1.0.0.tgz oci://ghcr.io/openclaw
|
||||
```
|
||||
|
||||
#### Automate in GitHub Actions
|
||||
|
||||
```yaml
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Push chart to GHCR
|
||||
run: |
|
||||
helm package charts/openclaw
|
||||
helm push openclaw-*.tgz oci://ghcr.io/${{ github.repository_owner }}
|
||||
```
|
||||
|
||||
#### Usage for End Users
|
||||
|
||||
```bash
|
||||
# Install directly from OCI
|
||||
helm install my-openclaw oci://ghcr.io/openclaw/openclaw --version 1.0.0
|
||||
```
|
||||
|
||||
### Option 3: Artifact Hub
|
||||
|
||||
Make your chart discoverable on [Artifact Hub](https://artifacthub.io).
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
- Chart published to GitHub Pages or OCI registry
|
||||
- Artifact Hub metadata file
|
||||
|
||||
#### Add Artifact Hub metadata
|
||||
|
||||
Create `charts/openclaw/artifacthub-repo.yml`:
|
||||
|
||||
```yaml
|
||||
repositoryID: <your-repo-id>
|
||||
owners:
|
||||
- name: Openclaw Team
|
||||
email: team@openclaw.com
|
||||
```
|
||||
|
||||
#### Submit to Artifact Hub
|
||||
|
||||
1. Go to https://artifacthub.io
|
||||
2. Sign in with GitHub
|
||||
3. Add repository
|
||||
4. Provide repository URL: `https://openclaw.github.io/openclaw`
|
||||
5. Wait for verification
|
||||
|
||||
### Option 4: ChartMuseum (Self-Hosted)
|
||||
|
||||
For private/internal charts:
|
||||
|
||||
```bash
|
||||
# Run ChartMuseum
|
||||
docker run -d \
|
||||
-p 8080:8080 \
|
||||
-v $(pwd)/charts:/charts \
|
||||
ghcr.io/helm/chartmuseum:latest \
|
||||
--storage local \
|
||||
--storage-local-rootdir /charts
|
||||
|
||||
# Upload chart
|
||||
curl --data-binary "@openclaw-1.0.0.tgz" http://localhost:8080/api/charts
|
||||
```
|
||||
|
||||
## Versioning
|
||||
|
||||
Follow Semantic Versioning:
|
||||
|
||||
- **Chart version** (`version` in Chart.yaml): Chart changes
|
||||
- **App version** (`appVersion` in Chart.yaml): Openclaw version
|
||||
|
||||
### Bumping Versions
|
||||
|
||||
```bash
|
||||
# Update chart version
|
||||
vim charts/openclaw/Chart.yaml
|
||||
# Change version: 1.0.0 → 1.1.0
|
||||
|
||||
# Update app version (when openclaw version changes)
|
||||
vim charts/openclaw/Chart.yaml
|
||||
# Change appVersion: "2026.1.25" → "2026.1.26"
|
||||
```
|
||||
|
||||
### Version Guidelines
|
||||
|
||||
- **Major** (1.0.0 → 2.0.0): Breaking changes to values.yaml or behavior
|
||||
- **Minor** (1.0.0 → 1.1.0): New features, non-breaking changes
|
||||
- **Patch** (1.0.0 → 1.0.1): Bug fixes, documentation
|
||||
|
||||
## Release Checklist
|
||||
|
||||
- [ ] Update `version` in `Chart.yaml`
|
||||
- [ ] Update `appVersion` if openclaw version changed
|
||||
- [ ] Update `CHANGELOG.md` (if you have one)
|
||||
- [ ] Test chart locally: `./scripts/test-helm-local.sh`
|
||||
- [ ] Lint chart: `helm lint charts/openclaw`
|
||||
- [ ] Commit changes
|
||||
- [ ] Push to main (triggers automated release)
|
||||
- [ ] Verify GitHub Pages deployment
|
||||
- [ ] Test installation from published repo
|
||||
|
||||
## Testing Published Chart
|
||||
|
||||
```bash
|
||||
# Add your published repo
|
||||
helm repo add openclaw https://openclaw.github.io/openclaw
|
||||
helm repo update
|
||||
|
||||
# Search for chart
|
||||
helm search repo openclaw
|
||||
|
||||
# Install from published repo
|
||||
helm install test openclaw/openclaw --dry-run --debug
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Chart not appearing after publish
|
||||
|
||||
1. Check GitHub Actions logs
|
||||
2. Verify gh-pages branch exists
|
||||
3. Check GitHub Pages settings are enabled
|
||||
4. Wait 5-10 minutes for GitHub Pages to deploy
|
||||
|
||||
### Users getting "not found" error
|
||||
|
||||
```bash
|
||||
# Check index.yaml exists
|
||||
curl https://openclaw.github.io/openclaw/index.yaml
|
||||
|
||||
# Verify chart package exists
|
||||
curl https://openclaw.github.io/openclaw/openclaw-1.0.0.tgz
|
||||
```
|
||||
|
||||
### Permission denied during publishing
|
||||
|
||||
Ensure GitHub Actions has write permissions:
|
||||
- Settings → Actions → General → Workflow permissions
|
||||
- Select "Read and write permissions"
|
||||
|
||||
## Advanced: Multi-Chart Repository
|
||||
|
||||
If you add more charts:
|
||||
|
||||
```
|
||||
charts/
|
||||
openclaw/
|
||||
openclaw-operator/
|
||||
openclaw-monitoring/
|
||||
```
|
||||
|
||||
The `helm/chart-releaser-action` automatically handles multiple charts.
|
||||
|
||||
## References
|
||||
|
||||
- [Helm Chart Repository Guide](https://helm.sh/docs/topics/chart_repository/)
|
||||
- [Chart Releaser Action](https://github.com/helm/chart-releaser-action)
|
||||
- [Artifact Hub](https://artifacthub.io/docs/topics/repositories/)
|
||||
- [OCI Registry Support](https://helm.sh/docs/topics/registries/)
|
||||
@ -0,0 +1,302 @@
|
||||
# Openclaw Helm Chart
|
||||
|
||||
Personal AI assistant with multi-channel support (WhatsApp, Telegram, Discord, and more) running on Kubernetes.
|
||||
|
||||
## TL;DR
|
||||
|
||||
```bash
|
||||
helm install my-openclaw ./openclaw \
|
||||
--set secrets.data.anthropicApiKey=sk-ant-xxx \
|
||||
--set secrets.data.gatewayToken=$(openssl rand -hex 32)
|
||||
```
|
||||
|
||||
## Introduction
|
||||
|
||||
This chart deploys Openclaw Gateway on a Kubernetes cluster using the Helm package manager.
|
||||
|
||||
**Important:** Openclaw is designed as a single-user personal assistant. The chart enforces `replicas: 1` and does not support horizontal scaling.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Kubernetes 1.19+
|
||||
- Helm 3.x
|
||||
- PV provisioner support in the underlying infrastructure (for persistent storage)
|
||||
- **Optional:** Ingress controller (NGINX, Traefik, etc.) for external access
|
||||
- **Optional:** cert-manager for automatic TLS certificates
|
||||
|
||||
## Installing the Chart
|
||||
|
||||
### Basic Installation
|
||||
|
||||
```bash
|
||||
helm install my-openclaw ./openclaw
|
||||
```
|
||||
|
||||
### With Custom Values
|
||||
|
||||
```bash
|
||||
helm install my-openclaw ./openclaw \
|
||||
--values examples/values-production.yaml \
|
||||
--set secrets.data.anthropicApiKey=sk-ant-xxx \
|
||||
--set ingress.hosts[0].host=assistant.example.com
|
||||
```
|
||||
|
||||
### From Examples
|
||||
|
||||
```bash
|
||||
# Basic (local testing)
|
||||
helm install my-openclaw ./openclaw -f examples/values-basic.yaml
|
||||
|
||||
# Production
|
||||
helm install my-openclaw ./openclaw -f examples/values-production.yaml
|
||||
|
||||
# Fly.io-like setup
|
||||
helm install my-openclaw ./openclaw -f examples/values-fly-like.yaml
|
||||
```
|
||||
|
||||
## Uninstalling the Chart
|
||||
|
||||
```bash
|
||||
helm uninstall my-openclaw
|
||||
|
||||
# Also delete PVCs (data will be lost)
|
||||
kubectl delete pvc -l app.kubernetes.io/instance=my-openclaw
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Key Parameters
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|-----------|-------------|---------|
|
||||
| `replicaCount` | Number of replicas (must be 1) | `1` |
|
||||
| `image.repository` | Openclaw image repository | `openclaw/openclaw` |
|
||||
| `image.tag` | Image tag | Chart appVersion |
|
||||
| `gateway.bind` | Gateway binding mode (`loopback`, `lan`, `auto`) | `lan` |
|
||||
| `gateway.port` | Gateway port | `18789` |
|
||||
| `secrets.data.anthropicApiKey` | Anthropic API key | `""` |
|
||||
| `secrets.data.openaiApiKey` | OpenAI API key | `""` |
|
||||
| `secrets.data.gatewayToken` | Gateway authentication token (auto-generated if empty) | `""` |
|
||||
| `persistence.enabled` | Enable persistent storage | `true` |
|
||||
| `persistence.size` | PVC size | `10Gi` |
|
||||
| `ingress.enabled` | Enable Ingress | `false` |
|
||||
| `ingress.className` | Ingress class | `nginx` |
|
||||
| `resources.limits.memory` | Memory limit | `2Gi` |
|
||||
| `resources.requests.memory` | Memory request | `512Mi` |
|
||||
|
||||
### Full Values Reference
|
||||
|
||||
See [values.yaml](values.yaml) for all available parameters.
|
||||
|
||||
## Storage
|
||||
|
||||
The chart creates a StatefulSet with a persistent volume claim template that mounts storage at two locations:
|
||||
|
||||
- `/home/node/.openclaw` (subPath: `openclaw-state`) - Configuration, sessions, device identity, SQLite databases
|
||||
- `/home/node/clawd` (subPath: `openclaw-workspace`) - Agent workspace files
|
||||
|
||||
**Storage Class:** By default, uses the cluster's default storage class. Override with `persistence.storageClass`.
|
||||
|
||||
**Size Recommendations:**
|
||||
- Development/Testing: 5-10Gi
|
||||
- Production (single user): 20Gi+
|
||||
- Depends on session history and workspace usage
|
||||
|
||||
## Secrets Management
|
||||
|
||||
### Option 1: Inline Secrets (Development Only)
|
||||
|
||||
```bash
|
||||
helm install my-openclaw ./openclaw \
|
||||
--set secrets.data.anthropicApiKey=sk-ant-xxx \
|
||||
--set secrets.data.gatewayToken=$(openssl rand -hex 32)
|
||||
```
|
||||
|
||||
### Option 2: External Secret (Production)
|
||||
|
||||
Create a Kubernetes Secret:
|
||||
|
||||
```bash
|
||||
kubectl create secret generic openclaw-secrets \
|
||||
--from-literal=gatewayToken=$(openssl rand -hex 32) \
|
||||
--from-literal=anthropicApiKey=sk-ant-xxx \
|
||||
--from-literal=discordBotToken=MTQ...
|
||||
```
|
||||
|
||||
Install with existing secret:
|
||||
|
||||
```bash
|
||||
helm install my-openclaw ./openclaw \
|
||||
--set secrets.create=false \
|
||||
--set secrets.existingSecret=openclaw-secrets
|
||||
```
|
||||
|
||||
### Option 3: External Secrets Operator
|
||||
|
||||
Use External Secrets Operator to sync from Vault, AWS Secrets Manager, etc.
|
||||
|
||||
## Ingress
|
||||
|
||||
### NGINX Ingress Controller
|
||||
|
||||
```yaml
|
||||
ingress:
|
||||
enabled: true
|
||||
className: nginx
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
|
||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
|
||||
nginx.ingress.kubernetes.io/websocket-services: "{{ include \"openclaw.fullname\" . }}"
|
||||
hosts:
|
||||
- host: assistant.example.com
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
tls:
|
||||
- secretName: openclaw-tls
|
||||
hosts:
|
||||
- assistant.example.com
|
||||
```
|
||||
|
||||
**Important:** WebSocket support requires extended timeouts (3600s recommended).
|
||||
|
||||
### Traefik
|
||||
|
||||
```yaml
|
||||
ingress:
|
||||
className: traefik
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||
```
|
||||
|
||||
## Health Checks
|
||||
|
||||
The chart uses exec-based probes that run the CLI health command:
|
||||
|
||||
```yaml
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- node dist/index.js health --token "${CLAWDBOT_GATEWAY_TOKEN}" || exit 1
|
||||
```
|
||||
|
||||
## Upgrading
|
||||
|
||||
```bash
|
||||
# Pull latest chart changes
|
||||
git pull
|
||||
|
||||
# Upgrade with current values
|
||||
helm upgrade my-openclaw ./openclaw --reuse-values
|
||||
|
||||
# Upgrade with new values
|
||||
helm upgrade my-openclaw ./openclaw -f values-production.yaml
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Pod Not Starting
|
||||
|
||||
```bash
|
||||
# Check pod events
|
||||
kubectl describe pod my-openclaw-0
|
||||
|
||||
# Check logs
|
||||
kubectl logs my-openclaw-0
|
||||
```
|
||||
|
||||
### OOM (Out of Memory)
|
||||
|
||||
Increase memory limits:
|
||||
|
||||
```yaml
|
||||
resources:
|
||||
limits:
|
||||
memory: 4Gi
|
||||
requests:
|
||||
memory: 1Gi
|
||||
```
|
||||
|
||||
**Note:** 512MB is too small for production. 2GB recommended minimum.
|
||||
|
||||
### PVC Not Binding
|
||||
|
||||
```bash
|
||||
# Check PVC status
|
||||
kubectl get pvc
|
||||
|
||||
# Check storage class
|
||||
kubectl get storageclass
|
||||
|
||||
# Describe for events
|
||||
kubectl describe pvc data-my-openclaw-0
|
||||
```
|
||||
|
||||
### WebSocket Connections Timing Out
|
||||
|
||||
Ensure Ingress has WebSocket annotations:
|
||||
|
||||
```yaml
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
|
||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
|
||||
```
|
||||
|
||||
### Gateway Lock File Issues
|
||||
|
||||
If the gateway won't start due to stale lock files:
|
||||
|
||||
```bash
|
||||
kubectl exec my-openclaw-0 -- rm -f /home/node/.openclaw/gateway.*.lock
|
||||
kubectl delete pod my-openclaw-0 # Restart pod
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Local Testing (Minikube/Kind/Docker Desktop)
|
||||
|
||||
```bash
|
||||
# Build local image
|
||||
docker build -t openclaw:local .
|
||||
|
||||
# Load into cluster (example for Minikube)
|
||||
minikube image load openclaw:local
|
||||
|
||||
# Install chart
|
||||
helm install test ./openclaw \
|
||||
-f examples/values-basic.yaml \
|
||||
--set image.repository=openclaw \
|
||||
--set image.tag=local \
|
||||
--set image.pullPolicy=Never
|
||||
```
|
||||
|
||||
### Production Deployment
|
||||
|
||||
```bash
|
||||
# Create external secret first
|
||||
kubectl create secret generic openclaw-secrets \
|
||||
--from-literal=gatewayToken=$(openssl rand -hex 32) \
|
||||
--from-literal=anthropicApiKey=$ANTHROPIC_API_KEY
|
||||
|
||||
# Install with production values
|
||||
helm install my-openclaw ./openclaw -f examples/values-production.yaml
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Openclaw Documentation](https://docs.clawd.bot)
|
||||
- [Kubernetes Installation Guide](https://docs.clawd.bot/install/kubernetes)
|
||||
- [GitHub Repository](https://github.com/openclaw/openclaw)
|
||||
|
||||
## Support
|
||||
|
||||
- [GitHub Issues](https://github.com/openclaw/openclaw/issues)
|
||||
- [Documentation](https://docs.clawd.bot)
|
||||
|
||||
## License
|
||||
|
||||
See [LICENSE](https://github.com/openclaw/openclaw/blob/main/LICENSE)
|
||||
@ -0,0 +1,33 @@
|
||||
# Basic configuration for local testing or development
|
||||
|
||||
image:
|
||||
repository: openclaw
|
||||
tag: local
|
||||
pullPolicy: Never
|
||||
|
||||
gateway:
|
||||
bind: lan
|
||||
port: 18789
|
||||
allowUnconfigured: false
|
||||
|
||||
secrets:
|
||||
create: true
|
||||
data:
|
||||
# Set via --set or environment variables
|
||||
anthropicApiKey: ""
|
||||
gatewayToken: ""
|
||||
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 5Gi
|
||||
|
||||
ingress:
|
||||
enabled: false
|
||||
|
||||
resources:
|
||||
limits:
|
||||
memory: 2Gi
|
||||
cpu: 1000m
|
||||
requests:
|
||||
memory: 512Mi
|
||||
cpu: 250m
|
||||
@ -0,0 +1,55 @@
|
||||
# Configuration similar to Fly.io deployment
|
||||
# Mimics fly.toml settings
|
||||
|
||||
image:
|
||||
repository: ghcr.io/openclaw/openclaw
|
||||
tag: "2026.1.25"
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
gateway:
|
||||
bind: lan
|
||||
port: 3000 # Fly.io uses port 3000
|
||||
allowUnconfigured: true
|
||||
extraArgs: []
|
||||
|
||||
env:
|
||||
NODE_ENV: production
|
||||
CLAWDBOT_STATE_DIR: /home/node/.openclaw
|
||||
CLAWDBOT_WORKSPACE_DIR: /home/node/clawd
|
||||
NODE_OPTIONS: "--max-old-space-size=1536" # Fly.io recommendation
|
||||
|
||||
secrets:
|
||||
create: false
|
||||
existingSecret: openclaw-secrets
|
||||
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 1Gi # Similar to Fly.io volume size
|
||||
|
||||
resources:
|
||||
limits:
|
||||
memory: 2Gi # shared-cpu-2x on Fly.io
|
||||
cpu: 1000m
|
||||
requests:
|
||||
memory: 512Mi
|
||||
cpu: 250m
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 3000
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
className: nginx
|
||||
domain: "my-openclaw.example.com"
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
|
||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
|
||||
nginx.ingress.kubernetes.io/websocket-services: "openclaw"
|
||||
tls:
|
||||
enabled: true
|
||||
secretName: openclaw-tls
|
||||
certManager:
|
||||
enabled: true
|
||||
issuer: letsencrypt-prod
|
||||
@ -0,0 +1,89 @@
|
||||
# Production configuration with Ingress and external secrets
|
||||
|
||||
image:
|
||||
repository: ghcr.io/openclaw/openclaw
|
||||
tag: "2026.1.25"
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
gateway:
|
||||
bind: lan
|
||||
port: 18789
|
||||
allowUnconfigured: false
|
||||
|
||||
# Use external secret in production
|
||||
secrets:
|
||||
create: false
|
||||
existingSecret: openclaw-secrets
|
||||
|
||||
config:
|
||||
create: true
|
||||
data:
|
||||
agents:
|
||||
defaults:
|
||||
model:
|
||||
primary: "anthropic/claude-opus-4-5"
|
||||
fallbacks:
|
||||
- "anthropic/claude-sonnet-4-5"
|
||||
maxConcurrent: 4
|
||||
sandbox:
|
||||
mode: "off"
|
||||
list:
|
||||
- id: main
|
||||
default: true
|
||||
auth:
|
||||
profiles:
|
||||
"anthropic:default":
|
||||
mode: token
|
||||
provider: anthropic
|
||||
gateway:
|
||||
mode: local
|
||||
bind: auto
|
||||
auth:
|
||||
mode: token
|
||||
controlUi:
|
||||
enabled: true
|
||||
channels:
|
||||
discord:
|
||||
enabled: true
|
||||
meta:
|
||||
lastTouchedVersion: "2026.1.25"
|
||||
|
||||
persistence:
|
||||
enabled: true
|
||||
storageClass: fast-ssd
|
||||
size: 20Gi
|
||||
accessMode: ReadWriteOnce
|
||||
|
||||
resources:
|
||||
limits:
|
||||
memory: 4Gi
|
||||
cpu: 2000m
|
||||
requests:
|
||||
memory: 1Gi
|
||||
cpu: 500m
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
className: nginx
|
||||
domain: "assistant.example.com"
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
|
||||
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
|
||||
nginx.ingress.kubernetes.io/websocket-services: "openclaw"
|
||||
tls:
|
||||
enabled: true
|
||||
secretName: openclaw-tls
|
||||
certManager:
|
||||
enabled: true
|
||||
issuer: letsencrypt-prod
|
||||
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
preference:
|
||||
matchExpressions:
|
||||
- key: workload-type
|
||||
operator: In
|
||||
values:
|
||||
- stateful
|
||||
@ -0,0 +1,73 @@
|
||||
Thank you for installing {{ .Chart.Name }}!
|
||||
|
||||
Your Openclaw gateway is starting up. This may take 1-2 minutes.
|
||||
|
||||
{{- if .Values.ingress.enabled }}
|
||||
{{- $domain := .Values.ingress.domain }}
|
||||
{{- $tlsEnabled := .Values.ingress.tls.enabled }}
|
||||
{{- if $domain }}
|
||||
|
||||
==========================================================
|
||||
Openclaw is accessible at:
|
||||
|
||||
{{- if $tlsEnabled }}
|
||||
https://{{ $domain }}
|
||||
{{- else }}
|
||||
http://{{ $domain }}
|
||||
{{- end }}
|
||||
==========================================================
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
1. Check the gateway status:
|
||||
|
||||
kubectl get statefulset {{ include "openclaw.fullname" . }} -n {{ .Release.Namespace }}
|
||||
kubectl logs -f {{ include "openclaw.fullname" . }}-0 -n {{ .Release.Namespace }}
|
||||
|
||||
2. Access the Control UI:
|
||||
|
||||
{{- if .Values.ingress.enabled }}
|
||||
{{- $domain := .Values.ingress.domain }}
|
||||
{{- $tlsEnabled := .Values.ingress.tls.enabled }}
|
||||
{{- if $domain }}
|
||||
{{- if $tlsEnabled }}
|
||||
https://{{ $domain }}
|
||||
{{- else }}
|
||||
http://{{ $domain }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- range .Values.ingress.hosts }}
|
||||
https://{{ .host }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
# Port-forward to access locally:
|
||||
kubectl port-forward {{ include "openclaw.fullname" . }}-0 {{ .Values.gateway.port }}:{{ .Values.gateway.port }} -n {{ .Release.Namespace }}
|
||||
|
||||
Then visit: http://localhost:{{ .Values.gateway.port }}
|
||||
{{- end }}
|
||||
|
||||
3. Your gateway token (for authentication):
|
||||
|
||||
kubectl get secret {{ include "openclaw.secretName" . }} -n {{ .Release.Namespace }} -o jsonpath='{.data.gatewayToken}' | base64 -d && echo
|
||||
|
||||
4. Configure channels:
|
||||
|
||||
kubectl exec -it {{ include "openclaw.fullname" . }}-0 -n {{ .Release.Namespace }} -- node dist/index.js channels add --channel discord --token YOUR_BOT_TOKEN
|
||||
|
||||
5. Check health:
|
||||
|
||||
kubectl exec -it {{ include "openclaw.fullname" . }}-0 -n {{ .Release.Namespace }} -- node dist/index.js health
|
||||
|
||||
Documentation: https://docs.clawd.bot
|
||||
Support: https://github.com/openclaw/openclaw/issues
|
||||
|
||||
{{- if not .Values.persistence.enabled }}
|
||||
|
||||
WARNING: Persistence is disabled. State will be lost on pod restart.
|
||||
{{- end }}
|
||||
|
||||
{{- if eq .Values.gateway.bind "loopback" }}
|
||||
|
||||
WARNING: Gateway is bound to loopback. External access will not work.
|
||||
{{- end }}
|
||||
@ -0,0 +1,84 @@
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "openclaw.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "openclaw.fullname" -}}
|
||||
{{- if .Values.fullnameOverride }}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||
{{- if contains $name .Release.Name }}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "openclaw.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "openclaw.labels" -}}
|
||||
helm.sh/chart: {{ include "openclaw.chart" . }}
|
||||
{{ include "openclaw.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "openclaw.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "openclaw.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "openclaw.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
{{- default (include "openclaw.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else }}
|
||||
{{- default "default" .Values.serviceAccount.name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the secret to use
|
||||
*/}}
|
||||
{{- define "openclaw.secretName" -}}
|
||||
{{- if .Values.secrets.existingSecret }}
|
||||
{{- .Values.secrets.existingSecret }}
|
||||
{{- else }}
|
||||
{{- include "openclaw.fullname" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the config map to use
|
||||
*/}}
|
||||
{{- define "openclaw.configMapName" -}}
|
||||
{{- if .Values.config.existingConfigMap }}
|
||||
{{- .Values.config.existingConfigMap }}
|
||||
{{- else }}
|
||||
{{- printf "%s-config" (include "openclaw.fullname" .) }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,11 @@
|
||||
{{- if .Values.config.create -}}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ include "openclaw.configMapName" . }}
|
||||
labels:
|
||||
{{- include "openclaw.labels" . | nindent 4 }}
|
||||
data:
|
||||
openclaw.json: |
|
||||
{{ .Values.config.data | toJson | nindent 4 }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,62 @@
|
||||
{{- if .Values.ingress.enabled -}}
|
||||
{{- $fullName := include "openclaw.fullname" . -}}
|
||||
{{- $svcPort := .Values.service.port -}}
|
||||
{{- $domain := .Values.ingress.domain -}}
|
||||
{{- $tlsEnabled := .Values.ingress.tls.enabled -}}
|
||||
{{- $tlsSecretName := .Values.ingress.tls.secretName | default (printf "%s-tls" $fullName) -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
labels:
|
||||
{{- include "openclaw.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- if and $tlsEnabled .Values.ingress.tls.certManager.enabled }}
|
||||
cert-manager.io/cluster-issuer: {{ .Values.ingress.tls.certManager.issuer | quote }}
|
||||
{{- end }}
|
||||
{{- with .Values.ingress.annotations }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if .Values.ingress.className }}
|
||||
ingressClassName: {{ .Values.ingress.className }}
|
||||
{{- end }}
|
||||
{{- if $tlsEnabled }}
|
||||
tls:
|
||||
- hosts:
|
||||
{{- if $domain }}
|
||||
- {{ $domain | quote }}
|
||||
{{- end }}
|
||||
{{- range .Values.ingress.hosts }}
|
||||
- {{ .host | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ $tlsSecretName }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- if $domain }}
|
||||
- host: {{ $domain | quote }}
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: {{ $fullName }}
|
||||
port:
|
||||
number: {{ $svcPort }}
|
||||
{{- end }}
|
||||
{{- range .Values.ingress.hosts }}
|
||||
- host: {{ .host | quote }}
|
||||
http:
|
||||
paths:
|
||||
{{- range .paths }}
|
||||
- path: {{ .path }}
|
||||
pathType: {{ .pathType }}
|
||||
backend:
|
||||
service:
|
||||
name: {{ $fullName }}
|
||||
port:
|
||||
number: {{ $svcPort }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,23 @@
|
||||
{{- if .Values.secrets.create -}}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ include "openclaw.fullname" . }}
|
||||
labels:
|
||||
{{- include "openclaw.labels" . | nindent 4 }}
|
||||
type: Opaque
|
||||
stringData:
|
||||
gatewayToken: {{ .Values.secrets.data.gatewayToken | default (randAlphaNum 32) | quote }}
|
||||
{{- with .Values.secrets.data.anthropicApiKey }}
|
||||
anthropicApiKey: {{ . | quote }}
|
||||
{{- end }}
|
||||
{{- with .Values.secrets.data.openaiApiKey }}
|
||||
openaiApiKey: {{ . | quote }}
|
||||
{{- end }}
|
||||
{{- with .Values.secrets.data.discordBotToken }}
|
||||
discordBotToken: {{ . | quote }}
|
||||
{{- end }}
|
||||
{{- with .Values.secrets.data.telegramBotToken }}
|
||||
telegramBotToken: {{ . | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,19 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "openclaw.fullname" . }}
|
||||
labels:
|
||||
{{- include "openclaw.labels" . | nindent 4 }}
|
||||
{{- with .Values.service.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.service.port }}
|
||||
targetPort: gateway
|
||||
protocol: TCP
|
||||
name: gateway
|
||||
selector:
|
||||
{{- include "openclaw.selectorLabels" . | nindent 4 }}
|
||||
@ -0,0 +1,12 @@
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "openclaw.serviceAccountName" . }}
|
||||
labels:
|
||||
{{- include "openclaw.labels" . | nindent 4 }}
|
||||
{{- with .Values.serviceAccount.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,202 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: {{ include "openclaw.fullname" . }}
|
||||
labels:
|
||||
{{- include "openclaw.labels" . | nindent 4 }}
|
||||
spec:
|
||||
serviceName: {{ include "openclaw.fullname" . }}
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "openclaw.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{- if .Values.config.create }}
|
||||
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
|
||||
{{- end }}
|
||||
{{- if .Values.secrets.create }}
|
||||
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
|
||||
{{- end }}
|
||||
{{- with .Values.podAnnotations }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "openclaw.selectorLabels" . | nindent 8 }}
|
||||
spec:
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "openclaw.serviceAccountName" . }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||
{{- if or .Values.config.create .Values.initContainers }}
|
||||
initContainers:
|
||||
{{- if .Values.config.create }}
|
||||
- name: init-config
|
||||
image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- |
|
||||
echo "Initializing configuration..."
|
||||
mkdir -p /home/node/.openclaw
|
||||
if [ ! -f /home/node/.openclaw/openclaw.json ]; then
|
||||
echo "Copying default config..."
|
||||
cp /config/openclaw.json /home/node/.openclaw/openclaw.json
|
||||
echo "Config initialized"
|
||||
else
|
||||
echo "Config already exists, skipping"
|
||||
fi
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /config
|
||||
- name: data
|
||||
mountPath: /home/node/.openclaw
|
||||
subPath: openclaw-state
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.initContainers }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: gateway
|
||||
image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
command:
|
||||
- node
|
||||
- dist/index.js
|
||||
- gateway
|
||||
- --bind
|
||||
- {{ .Values.gateway.bind }}
|
||||
- --port
|
||||
- {{ .Values.gateway.port | quote }}
|
||||
{{- if .Values.gateway.allowUnconfigured }}
|
||||
- --allow-unconfigured
|
||||
{{- end }}
|
||||
{{- range .Values.gateway.extraArgs }}
|
||||
- {{ . }}
|
||||
{{- end }}
|
||||
env:
|
||||
{{- range $key, $value := .Values.env }}
|
||||
- name: {{ $key }}
|
||||
value: {{ $value | quote }}
|
||||
{{- end }}
|
||||
- name: CLAWDBOT_GATEWAY_PORT
|
||||
value: {{ .Values.gateway.port | quote }}
|
||||
- name: CLAWDBOT_GATEWAY_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "openclaw.secretName" . }}
|
||||
key: gatewayToken
|
||||
{{- if .Values.secrets.data.anthropicApiKey }}
|
||||
- name: ANTHROPIC_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "openclaw.secretName" . }}
|
||||
key: anthropicApiKey
|
||||
optional: true
|
||||
{{- end }}
|
||||
{{- if .Values.secrets.data.openaiApiKey }}
|
||||
- name: OPENAI_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "openclaw.secretName" . }}
|
||||
key: openaiApiKey
|
||||
optional: true
|
||||
{{- end }}
|
||||
{{- if .Values.secrets.data.discordBotToken }}
|
||||
- name: DISCORD_BOT_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "openclaw.secretName" . }}
|
||||
key: discordBotToken
|
||||
optional: true
|
||||
{{- end }}
|
||||
{{- if .Values.secrets.data.telegramBotToken }}
|
||||
- name: TELEGRAM_BOT_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ include "openclaw.secretName" . }}
|
||||
key: telegramBotToken
|
||||
optional: true
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: gateway
|
||||
containerPort: {{ .Values.gateway.port }}
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /home/node/.openclaw
|
||||
subPath: openclaw-state
|
||||
- name: data
|
||||
mountPath: /home/node/clawd
|
||||
subPath: openclaw-workspace
|
||||
{{- if .Values.livenessProbe.enabled }}
|
||||
livenessProbe:
|
||||
{{- omit .Values.livenessProbe "enabled" | toYaml | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.readinessProbe.enabled }}
|
||||
readinessProbe:
|
||||
{{- omit .Values.readinessProbe "enabled" | toYaml | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.startupProbe.enabled }}
|
||||
startupProbe:
|
||||
{{- omit .Values.startupProbe "enabled" | toYaml | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.lifecycle }}
|
||||
lifecycle:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
{{- with .Values.extraContainers }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
{{- if .Values.config.create }}
|
||||
- name: config
|
||||
configMap:
|
||||
name: {{ include "openclaw.configMapName" . }}
|
||||
{{- end }}
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.persistence.enabled }}
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: data
|
||||
{{- with .Values.persistence.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
accessModes:
|
||||
- {{ .Values.persistence.accessMode }}
|
||||
{{- if .Values.persistence.storageClass }}
|
||||
storageClassName: {{ .Values.persistence.storageClass }}
|
||||
{{- end }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.persistence.size }}
|
||||
{{- with .Values.persistence.selector }}
|
||||
selector:
|
||||
{{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: "{{ include "openclaw.fullname" . }}-test-connection"
|
||||
labels:
|
||||
{{- include "openclaw.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
"helm.sh/hook": test
|
||||
spec:
|
||||
containers:
|
||||
- name: wget
|
||||
image: busybox
|
||||
command: ['wget']
|
||||
args: ['{{ include "openclaw.fullname" . }}:{{ .Values.service.port }}']
|
||||
restartPolicy: Never
|
||||
@ -0,0 +1,74 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"replicaCount": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 1,
|
||||
"default": 1,
|
||||
"description": "Must be 1 for single-user architecture. Openclaw does not support horizontal scaling."
|
||||
},
|
||||
"image": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"repository": {
|
||||
"type": "string"
|
||||
},
|
||||
"pullPolicy": {
|
||||
"type": "string",
|
||||
"enum": ["Always", "IfNotPresent", "Never"]
|
||||
},
|
||||
"tag": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gateway": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"bind": {
|
||||
"type": "string",
|
||||
"enum": ["loopback", "lan", "auto"],
|
||||
"description": "Gateway binding mode"
|
||||
},
|
||||
"port": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 65535
|
||||
}
|
||||
}
|
||||
},
|
||||
"persistence": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"size": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9]+(Gi|Mi|Ti)$"
|
||||
},
|
||||
"accessMode": {
|
||||
"type": "string",
|
||||
"enum": ["ReadWriteOnce", "ReadOnlyMany", "ReadWriteMany"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"service": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["ClusterIP", "NodePort", "LoadBalancer"]
|
||||
},
|
||||
"port": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 65535
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["replicaCount"]
|
||||
}
|
||||
@ -0,0 +1,233 @@
|
||||
# Default values for openclaw.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
# Image configuration
|
||||
image:
|
||||
registry: ghcr.io
|
||||
repository: openclaw/openclaw
|
||||
pullPolicy: IfNotPresent
|
||||
# Overrides the image tag whose default is the chart appVersion.
|
||||
tag: ""
|
||||
|
||||
imagePullSecrets: []
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
# Replica count - MUST be 1 for single-user architecture
|
||||
replicaCount: 1
|
||||
|
||||
# Service account
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created
|
||||
create: true
|
||||
# Annotations to add to the service account
|
||||
annotations: {}
|
||||
# The name of the service account to use.
|
||||
# If not set and create is true, a name is generated using the fullname template
|
||||
name: ""
|
||||
|
||||
# Pod annotations
|
||||
podAnnotations: {}
|
||||
|
||||
# Pod security context
|
||||
podSecurityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
fsGroup: 1000
|
||||
|
||||
# Container security context
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: false # Node needs write access to /tmp
|
||||
|
||||
# Gateway configuration
|
||||
gateway:
|
||||
# Binding mode: loopback, lan, auto
|
||||
bind: lan
|
||||
# Gateway port
|
||||
port: 18789
|
||||
# Allow unconfigured startup (creates minimal config)
|
||||
allowUnconfigured: false
|
||||
# Additional CLI arguments
|
||||
extraArgs: []
|
||||
|
||||
# Environment variables (non-sensitive)
|
||||
env:
|
||||
NODE_ENV: production
|
||||
CLAWDBOT_STATE_DIR: /home/node/.openclaw
|
||||
CLAWDBOT_WORKSPACE_DIR: /home/node/clawd
|
||||
NODE_OPTIONS: "--max-old-space-size=2048"
|
||||
|
||||
# Secrets configuration
|
||||
secrets:
|
||||
# Create secret from values (dev/testing only - use existingSecret in production)
|
||||
create: true
|
||||
# Use existing secret (production)
|
||||
existingSecret: ""
|
||||
# Secret data (only used if create is true)
|
||||
data:
|
||||
anthropicApiKey: ""
|
||||
openaiApiKey: ""
|
||||
discordBotToken: ""
|
||||
telegramBotToken: ""
|
||||
gatewayToken: "" # Auto-generated if empty
|
||||
|
||||
# Config file (openclaw.json)
|
||||
config:
|
||||
# Create ConfigMap from inline config
|
||||
create: true
|
||||
# Use existing ConfigMap
|
||||
existingConfigMap: ""
|
||||
# Config data (JSON5 format)
|
||||
data:
|
||||
agents:
|
||||
defaults:
|
||||
model:
|
||||
primary: "anthropic/claude-opus-4-5"
|
||||
fallbacks:
|
||||
- "anthropic/claude-sonnet-4-5"
|
||||
- "openai/gpt-4o"
|
||||
maxConcurrent: 4
|
||||
sandbox:
|
||||
mode: "off" # Disable Docker-in-Docker for Kubernetes
|
||||
list:
|
||||
- id: main
|
||||
default: true
|
||||
auth:
|
||||
profiles:
|
||||
"anthropic:default":
|
||||
mode: token
|
||||
provider: anthropic
|
||||
"openai:default":
|
||||
mode: token
|
||||
provider: openai
|
||||
gateway:
|
||||
mode: local
|
||||
bind: auto
|
||||
auth:
|
||||
mode: token
|
||||
controlUi:
|
||||
enabled: true
|
||||
channels: {}
|
||||
|
||||
# Persistence
|
||||
persistence:
|
||||
enabled: true
|
||||
# Storage class (use cluster default if empty)
|
||||
storageClass: ""
|
||||
# Access mode
|
||||
accessMode: ReadWriteOnce
|
||||
# Volume size
|
||||
size: 10Gi
|
||||
# Annotations
|
||||
annotations: {}
|
||||
# Selector
|
||||
selector: {}
|
||||
|
||||
# Service configuration
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 18789
|
||||
annotations: {}
|
||||
|
||||
# Ingress configuration
|
||||
ingress:
|
||||
enabled: false
|
||||
className: nginx
|
||||
|
||||
# Simplified domain configuration (recommended)
|
||||
# Set your domain here - TLS will be auto-configured if tls.enabled is true
|
||||
domain: "" # e.g., "openclaw.yourdomain.com"
|
||||
|
||||
# TLS configuration
|
||||
tls:
|
||||
enabled: false
|
||||
# Secret name for TLS certificate (auto-generated name if empty)
|
||||
secretName: ""
|
||||
# Use cert-manager for automatic certificate provisioning
|
||||
certManager:
|
||||
enabled: false
|
||||
issuer: "letsencrypt-prod"
|
||||
|
||||
# Additional annotations
|
||||
annotations: {}
|
||||
# WebSocket support (recommended for real-time features):
|
||||
# nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
|
||||
# nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
|
||||
|
||||
# Advanced: Manual host configuration (overrides domain if set)
|
||||
hosts: []
|
||||
# - host: openclaw.example.com
|
||||
# paths:
|
||||
# - path: /
|
||||
# pathType: Prefix
|
||||
|
||||
# Resource limits/requests
|
||||
resources:
|
||||
limits:
|
||||
memory: 2Gi
|
||||
cpu: 1000m
|
||||
requests:
|
||||
memory: 512Mi
|
||||
cpu: 250m
|
||||
|
||||
# Node selector
|
||||
nodeSelector: {}
|
||||
|
||||
# Tolerations
|
||||
tolerations: []
|
||||
|
||||
# Affinity rules
|
||||
affinity: {}
|
||||
|
||||
# Init containers (for setup tasks)
|
||||
initContainers: []
|
||||
|
||||
# Extra containers (sidecars)
|
||||
extraContainers: []
|
||||
|
||||
# Lifecycle hooks
|
||||
lifecycle:
|
||||
preStop:
|
||||
exec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- rm -f /home/node/.openclaw/gateway.*.lock; sleep 10
|
||||
|
||||
# Probes
|
||||
# Use tcpSocket for startup/readiness (lightweight), exec for liveness (thorough)
|
||||
livenessProbe:
|
||||
enabled: true
|
||||
exec:
|
||||
command:
|
||||
- node
|
||||
- dist/index.js
|
||||
- health
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 60
|
||||
timeoutSeconds: 30
|
||||
failureThreshold: 3
|
||||
|
||||
readinessProbe:
|
||||
enabled: true
|
||||
tcpSocket:
|
||||
port: 18789
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
|
||||
startupProbe:
|
||||
enabled: true
|
||||
tcpSocket:
|
||||
port: 18789
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 30 # 150 seconds max startup time
|
||||
Loading…
Reference in New Issue