diff --git a/charts/godaddy-webhook/0.2.0/extra/clusterissuer.yml b/charts/godaddy-webhook/0.2.0/extra/clusterissuer.yml index 4314543..85abcaa 100644 --- a/charts/godaddy-webhook/0.2.0/extra/clusterissuer.yml +++ b/charts/godaddy-webhook/0.2.0/extra/clusterissuer.yml @@ -15,9 +15,6 @@ spec: solvers: - selector: dnsZones: - - 'bassengvegen.com' - - 'app.bassengvegen.com' - - 'dyn.bassengvegen.com' - 'dogella.com' dns01: webhook: @@ -36,6 +33,9 @@ spec: - 'krystallen-a401.com' - 'ensup.no' - 'glossifyme.com' + - 'bassengvegen.com' + - 'app.bassengvegen.com' + - 'dyn.bassengvegen.com' dns01: cloudflare: email: marius@ensrud.net diff --git a/charts/openclaw/2026.02.1/.helmignore b/charts/openclaw/2026.02.1/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/charts/openclaw/2026.02.1/.helmignore @@ -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/ diff --git a/charts/openclaw/2026.02.1/Chart.yaml b/charts/openclaw/2026.02.1/Chart.yaml new file mode 100644 index 0000000..2b75075 --- /dev/null +++ b/charts/openclaw/2026.02.1/Chart.yaml @@ -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 diff --git a/charts/openclaw/2026.02.1/PUBLISHING.md b/charts/openclaw/2026.02.1/PUBLISHING.md new file mode 100644 index 0000000..44e878a --- /dev/null +++ b/charts/openclaw/2026.02.1/PUBLISHING.md @@ -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: +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/) diff --git a/charts/openclaw/2026.02.1/README.md b/charts/openclaw/2026.02.1/README.md new file mode 100644 index 0000000..758c413 --- /dev/null +++ b/charts/openclaw/2026.02.1/README.md @@ -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) diff --git a/charts/openclaw/2026.02.1/examples/values-basic.yaml b/charts/openclaw/2026.02.1/examples/values-basic.yaml new file mode 100644 index 0000000..75f3c46 --- /dev/null +++ b/charts/openclaw/2026.02.1/examples/values-basic.yaml @@ -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 diff --git a/charts/openclaw/2026.02.1/examples/values-fly-like.yaml b/charts/openclaw/2026.02.1/examples/values-fly-like.yaml new file mode 100644 index 0000000..0cb18c2 --- /dev/null +++ b/charts/openclaw/2026.02.1/examples/values-fly-like.yaml @@ -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 diff --git a/charts/openclaw/2026.02.1/examples/values-production.yaml b/charts/openclaw/2026.02.1/examples/values-production.yaml new file mode 100644 index 0000000..4b115ea --- /dev/null +++ b/charts/openclaw/2026.02.1/examples/values-production.yaml @@ -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 diff --git a/charts/openclaw/2026.02.1/templates/NOTES.txt b/charts/openclaw/2026.02.1/templates/NOTES.txt new file mode 100644 index 0000000..4246f7a --- /dev/null +++ b/charts/openclaw/2026.02.1/templates/NOTES.txt @@ -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 }} diff --git a/charts/openclaw/2026.02.1/templates/_helpers.tpl b/charts/openclaw/2026.02.1/templates/_helpers.tpl new file mode 100644 index 0000000..313693e --- /dev/null +++ b/charts/openclaw/2026.02.1/templates/_helpers.tpl @@ -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 }} diff --git a/charts/openclaw/2026.02.1/templates/configmap.yaml b/charts/openclaw/2026.02.1/templates/configmap.yaml new file mode 100644 index 0000000..633e7cc --- /dev/null +++ b/charts/openclaw/2026.02.1/templates/configmap.yaml @@ -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 }} diff --git a/charts/openclaw/2026.02.1/templates/ingress.yaml b/charts/openclaw/2026.02.1/templates/ingress.yaml new file mode 100644 index 0000000..d8d523b --- /dev/null +++ b/charts/openclaw/2026.02.1/templates/ingress.yaml @@ -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 }} diff --git a/charts/openclaw/2026.02.1/templates/secret.yaml b/charts/openclaw/2026.02.1/templates/secret.yaml new file mode 100644 index 0000000..fece8ab --- /dev/null +++ b/charts/openclaw/2026.02.1/templates/secret.yaml @@ -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 }} diff --git a/charts/openclaw/2026.02.1/templates/service.yaml b/charts/openclaw/2026.02.1/templates/service.yaml new file mode 100644 index 0000000..2713dcc --- /dev/null +++ b/charts/openclaw/2026.02.1/templates/service.yaml @@ -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 }} diff --git a/charts/openclaw/2026.02.1/templates/serviceaccount.yaml b/charts/openclaw/2026.02.1/templates/serviceaccount.yaml new file mode 100644 index 0000000..36af400 --- /dev/null +++ b/charts/openclaw/2026.02.1/templates/serviceaccount.yaml @@ -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 }} diff --git a/charts/openclaw/2026.02.1/templates/statefulset.yaml b/charts/openclaw/2026.02.1/templates/statefulset.yaml new file mode 100644 index 0000000..39acd39 --- /dev/null +++ b/charts/openclaw/2026.02.1/templates/statefulset.yaml @@ -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 }} diff --git a/charts/openclaw/2026.02.1/templates/tests/test-connection.yaml b/charts/openclaw/2026.02.1/templates/tests/test-connection.yaml new file mode 100644 index 0000000..45a4d7c --- /dev/null +++ b/charts/openclaw/2026.02.1/templates/tests/test-connection.yaml @@ -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 diff --git a/charts/openclaw/2026.02.1/values.schema.json b/charts/openclaw/2026.02.1/values.schema.json new file mode 100644 index 0000000..7b32303 --- /dev/null +++ b/charts/openclaw/2026.02.1/values.schema.json @@ -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"] +} diff --git a/charts/openclaw/2026.02.1/values.yaml b/charts/openclaw/2026.02.1/values.yaml new file mode 100644 index 0000000..7b29ff6 --- /dev/null +++ b/charts/openclaw/2026.02.1/values.yaml @@ -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