Decomisión de openclaw

- Elimina manifests openclaw/ y argocd/application-openclaw.yaml
- backup-system: fuera del backup diario, crown-jewels, expected y retain;
  fuera el mount hostPath del cronjob y la fila de RESTORE.md
- monitoring: eliminado panel openclaw del dashboard homelab-overview
- n8n: openclaw y polymarket fuera del health-check (espejo del workflow vivo)
- cluster-wide/namespaces.yaml: fuera openclaw + añadidos separadores '---'
  que faltaban (el archivo era un único doc YAML donde ganaba el último ns)

Cluster ya limpio: app ArgoCD, namespace, PVC/PV, RBAC cluster-scoped y
monitor de Uptime Kuma. Backup final: ~/decommissioned/openclaw-final-2026-07-18.tar.gz

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-18 14:57:46 +00:00
co-authored by Claude Fable 5
parent d011a4c50f
commit e00c520a26
21 changed files with 17 additions and 796 deletions
-1
View File
@@ -27,7 +27,6 @@ Los secrets TLS los gestiona **cert-manager** automáticamente a partir del recu
| `authentik` | `authentik-secret` | Ver Vaultwarden → "authentik" |
| `cloudflare-ddns` | `cloudflare-ddns-secret` | Ver Vaultwarden → "cloudflare-ddns" |
| `vaultwarden` | `vaultwarden-secret` | Ver Vaultwarden → "vaultwarden" |
| `openclaw` | `openclaw-token` | Ver Vaultwarden → "openclaw" |
| `ghost-en` | `ghost-en-smtp` | `kubectl create secret generic ghost-en-smtp --from-literal=SMTP_USER='<user-gmail>' --from-literal=SMTP_PASS='<app-password>' -n ghost-en` |
| `argocd` | `argocd-secret` | Gestionado por ArgoCD bootstrap |
| `argocd` | `argocd-redis` | Gestionado por ArgoCD bootstrap |
-20
View File
@@ -1,20 +0,0 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: openclaw
namespace: argocd
spec:
destination:
namespace: openclaw
server: https://kubernetes.default.svc
project: default
source:
path: openclaw
repoURL: https://git.chemavx.xyz/chemavx/k8s-manifests
targetRevision: main
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
-1
View File
@@ -61,7 +61,6 @@ umami-pg, roswell-pg (la BD corre en n97) y `/opt/reddit-intel` + Docker.
| Artefacto | Cómo restaurar |
|---|---|
| `n8n_*.tar.gz` | Extraer en `/data/n8n` (hostPath master), reiniciar deploy. Incluye encryptionKey. |
| `openclaw_*.tar.gz` | Extraer en el PVC `openclaw-pvc` (pod parado). |
| `homarr_*.tar.gz` | `db/db.sqlite` → PVC db; `redis/dump.rdb` → PVC redis. |
| `authentik-pg_*.sql.gz` | `gunzip -c \| kubectl exec -i postgresql-0 -n authentik -- psql -U authentik authentik` (BD vacía primero). |
| `grafana_*.tar.gz` | `grafana.db` → PVC de grafana, reiniciar pod. |
+5 -11
View File
@@ -4,7 +4,7 @@ data:
#!/bin/bash
# Backup diario del homelab. Imagen: bitnami/kubectl (bash GNU, corre en chemavx-k8).
# Regla: cada artefacto se valida (gzip -t + tamaño mínimo) — un tar vacío
# como el bug histórico de openclaw (104 bytes) cuenta como FALLO y el job sale 1
# (bug histórico: tar de 104 bytes de una app ya decomisada) cuenta como FALLO y el job sale 1
# (→ alerta Grafana homelab-backup-job-failed → Telegram).
set -u
@@ -59,12 +59,6 @@ data:
tar -czf "$BACKUP_DIR/n8n_${DATE}.tar.gz" -C /data/n8n . 2>/dev/null
check "$BACKUP_DIR/n8n_${DATE}.tar.gz" 10000000 n8n
# === openclaw (PVC local-path; el hostPath /data/openclaw era un stub vacío) ===
log "Backing up openclaw..."
OC=$(pvpath openclaw openclaw-pvc)
tar -czf "$BACKUP_DIR/openclaw_${DATE}.tar.gz" -C "$OC" . 2>/dev/null
check "$BACKUP_DIR/openclaw_${DATE}.tar.gz" 50000 openclaw
# === homarr ===
log "Backing up homarr..."
HOMARR_DB=$(pvpath homarr homarr-db-pvc)
@@ -189,7 +183,7 @@ data:
\( -name "${1}_*.tar.gz" -o -name "${1}_*.sql.gz" -o -name "${1}_*.db.gz" \) | \
sort | head -n -"$2" | xargs -r rm -f
}
for p in n8n openclaw homarr authentik-pg grafana k3s-db gitea \
for p in n8n homarr authentik-pg grafana k3s-db gitea \
ghost-en-db ghost-en-content zona-exclusion-db zona-exclusion-content \
researchowl roswell-pg umami-pg infisical-pg trilium vaultwarden filebrowser-db; do
retain "$p" 7
@@ -257,7 +251,7 @@ data:
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }
BACKUP_DIR=/data/backups/backups
CROWN="n8n openclaw homarr authentik-pg grafana k3s-db gitea ghost-en-db ghost-en-content zona-exclusion-db zona-exclusion-content researchowl roswell-pg umami-pg infisical-pg trilium vaultwarden filebrowser-db home-master"
CROWN="n8n homarr authentik-pg grafana k3s-db gitea ghost-en-db ghost-en-content zona-exclusion-db zona-exclusion-content researchowl roswell-pg umami-pg infisical-pg trilium vaultwarden filebrowser-db home-master"
KEEP=/tmp/crown-jewels
rm -rf "$KEEP"; mkdir -p "$KEEP"
@@ -303,7 +297,7 @@ data:
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }
EXPECTED_SERVICES="n8n openclaw homarr authentik-pg grafana k3s-db gitea ghost-en-db ghost-en-content zona-exclusion-db zona-exclusion-content researchowl roswell-pg umami-pg infisical-pg trilium vaultwarden uptime-kuma filebrowser-db home-master"
EXPECTED_SERVICES="n8n homarr authentik-pg grafana k3s-db gitea ghost-en-db ghost-en-content zona-exclusion-db zona-exclusion-content researchowl roswell-pg umami-pg infisical-pg trilium vaultwarden uptime-kuma filebrowser-db home-master"
ERRORS=0
# Ventana de frescura: backup y sync son diarios → un backup es "reciente"
@@ -356,7 +350,7 @@ data:
# === Segundo offsite: B2 crown-jewels (todo menos uptime-kuma) ===
log "=== Verificación de crown-jewels en B2 ==="
CROWN="n8n openclaw homarr authentik-pg grafana k3s-db gitea ghost-en-db ghost-en-content zona-exclusion-db zona-exclusion-content researchowl roswell-pg umami-pg infisical-pg trilium vaultwarden filebrowser-db home-master"
CROWN="n8n homarr authentik-pg grafana k3s-db gitea ghost-en-db ghost-en-content zona-exclusion-db zona-exclusion-content researchowl roswell-pg umami-pg infisical-pg trilium vaultwarden filebrowser-db home-master"
B2FILES=$(rclone ls b2:chemavx-k3s-backups/ --config /rclone/rclone.conf 2>&1)
for svc in $CROWN; do
FOUND=0
-6
View File
@@ -40,8 +40,6 @@ spec:
mountPath: /data/backups/backups
- name: n8n-data
mountPath: /data/n8n
- name: openclaw-data
mountPath: /data/openclaw
- name: scripts
mountPath: /scripts
- name: k3s-storage
@@ -67,10 +65,6 @@ spec:
hostPath:
path: /data/n8n
type: DirectoryOrCreate
- name: openclaw-data
hostPath:
path: /data/openclaw
type: DirectoryOrCreate
- name: scripts
configMap:
name: backup-scripts
+11 -26
View File
@@ -11,7 +11,7 @@ metadata:
spec:
finalizers:
- kubernetes
---
apiVersion: v1
kind: Namespace
metadata:
@@ -25,7 +25,7 @@ metadata:
spec:
finalizers:
- kubernetes
---
apiVersion: v1
kind: Namespace
metadata:
@@ -39,7 +39,7 @@ metadata:
spec:
finalizers:
- kubernetes
---
apiVersion: v1
kind: Namespace
metadata:
@@ -53,7 +53,7 @@ metadata:
spec:
finalizers:
- kubernetes
---
apiVersion: v1
kind: Namespace
metadata:
@@ -67,7 +67,7 @@ metadata:
spec:
finalizers:
- kubernetes
---
apiVersion: v1
kind: Namespace
metadata:
@@ -77,7 +77,7 @@ metadata:
spec:
finalizers:
- kubernetes
---
apiVersion: v1
kind: Namespace
metadata:
@@ -91,7 +91,7 @@ metadata:
spec:
finalizers:
- kubernetes
---
apiVersion: v1
kind: Namespace
metadata:
@@ -105,7 +105,7 @@ metadata:
spec:
finalizers:
- kubernetes
---
apiVersion: v1
kind: Namespace
metadata:
@@ -119,7 +119,7 @@ metadata:
spec:
finalizers:
- kubernetes
---
apiVersion: v1
kind: Namespace
metadata:
@@ -133,21 +133,7 @@ metadata:
spec:
finalizers:
- kubernetes
apiVersion: v1
kind: Namespace
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: '{"apiVersion":"v1","kind":"Namespace","metadata":{"annotations":{},"name":"openclaw"},"spec":{},"status":{}}
'
labels:
kubernetes.io/metadata.name: openclaw
name: openclaw
spec:
finalizers:
- kubernetes
---
apiVersion: v1
kind: Namespace
metadata:
@@ -161,7 +147,7 @@ metadata:
spec:
finalizers:
- kubernetes
---
apiVersion: v1
kind: Namespace
metadata:
@@ -175,4 +161,3 @@ metadata:
spec:
finalizers:
- kubernetes
@@ -407,94 +407,6 @@ data:
"title": "n8n",
"type": "stat"
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [
{
"options": {
"0": {
"color": "red",
"index": 0,
"text": "Down"
}
},
"type": "value"
},
{
"options": {
"from": 1,
"result": {
"color": "green",
"index": 1,
"text": "Running"
},
"to": null
},
"type": "range"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "red",
"value": null
},
{
"color": "green",
"value": 1
}
]
},
"unit": "short"
},
"overrides": []
},
"gridPos": {
"h": 4,
"w": 4,
"x": 4,
"y": 10
},
"id": 8,
"options": {
"colorMode": "background",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"textMode": "auto"
},
"pluginVersion": "12.4.2",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"expr": "sum(kube_pod_status_phase{namespace=\"openclaw\",phase=\"Running\"}) or vector(0)",
"instant": true,
"legendFormat": "openclaw",
"refId": "A"
}
],
"title": "openclaw",
"type": "stat"
},
{
"datasource": {
"type": "prometheus",
@@ -1870,5 +1782,4 @@ data:
"uid": "chemavx-homelab-v1",
"version": 3,
"weekStart": ""
}
}
-2
View File
@@ -14,7 +14,6 @@ return await (async () => {
const SERVICES = [
{ name: 'n8n', url: 'https://n8n.chemavx.xyz' },
{ name: 'openclaw', url: 'https://openclaw.chemavx.xyz' },
{ name: 'vaultwarden', url: 'https://vaultwarden.chemavx.xyz' },
{ name: 'grafana', url: 'https://grafana.chemavx.xyz' },
{ name: 'uptime', url: 'https://uptime.chemavx.xyz' },
@@ -22,7 +21,6 @@ return await (async () => {
{ name: 'home', url: 'https://home.chemavx.xyz' },
{ name: 'git', url: 'https://git.chemavx.xyz' },
{ name: 'argocd', url: 'https://argocd.chemavx.xyz' },
{ name: 'polymarket', url: 'https://polymarket.chemavx.xyz' },
{ name: 'ollama', url: 'https://ollama.chemavx.xyz/api/tags' },
];
-76
View File
@@ -1,76 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: openclaw
namespace: openclaw
spec:
replicas: 1
selector:
matchLabels:
app: openclaw
template:
metadata:
labels:
app: openclaw
spec:
nodeSelector:
kubernetes.io/hostname: chemavx-k8
serviceAccountName: openclaw-agent
securityContext:
runAsUser: 1000
fsGroup: 1000
initContainers:
- name: setup-kubectl
image: bitnami/kubectl:latest
imagePullPolicy: IfNotPresent
command:
- sh
- -c
- |
cp $(which kubectl) /opt/kube/kubectl
chmod +x /opt/kube/kubectl
cat > /opt/kube/kubectl-ro << 'SCRIPT'
#!/bin/sh
DENIED="delete apply patch edit exec scale rollout drain cordon uncordon taint replace create annotate label"
if [ "$#" -eq 0 ]; then exec /opt/kube/kubectl "$@"; fi
SUBCMD="$1"
for d in $DENIED; do
if [ "$SUBCMD" = "$d" ]; then
echo "ERROR: \"$SUBCMD\" no permitido en modo solo lectura." >&2; exit 1
fi
done
exec /opt/kube/kubectl "$@"
SCRIPT
chmod +x /opt/kube/kubectl-ro
volumeMounts:
- name: kube-tools
mountPath: /opt/kube
securityContext:
runAsUser: 0
containers:
- name: openclaw
image: ghcr.io/openclaw/openclaw:2026.4.22
imagePullPolicy: IfNotPresent
ports:
- containerPort: 18789
env:
- name: NODE_OPTIONS
value: --max-old-space-size=1536
resources:
requests:
cpu: 100m
memory: 512Mi
limits:
cpu: "1"
memory: 2Gi
volumeMounts:
- name: data
mountPath: /home/node/.openclaw
- name: kube-tools
mountPath: /opt/kube
volumes:
- name: data
persistentVolumeClaim:
claimName: openclaw-pvc
- name: kube-tools
emptyDir: {}
-62
View File
@@ -1,62 +0,0 @@
# HOMELAB.md - Infraestructura del Homelab
Lee este archivo al inicio de cada sesión. Contiene el contexto completo del homelab.
## Cluster k3s
- **chemavx-k8** (master/control-plane): 192.168.1.225, Ubuntu 22.04.5 LTS, k3s v1.34.6
- CPU: 16 cores · RAM: ~32 GB
- GPU: NVIDIA GeForce RTX 3060 12 GB (CUDA, Ampere gfx8.6) — usada por Ollama
- **chemavx-n97** (worker): 192.168.1.238, Ubuntu 24.04.4 LTS, k3s v1.34.6
- CPU: 4 cores · RAM: ~12 GB
- Ingress: Traefik (LoadBalancer 192.168.1.225 + 192.168.1.238) · TLS: cert-manager + letsencrypt-prod
- Dominio: *.chemavx.xyz
- Storage: local-path (hostPath) — datos en chemavx-k8 NO accesibles desde chemavx-n97
## Servicios desplegados
| Servicio | Namespace | URL | Notas |
|-----------------|-----------------|------------------------------|-------|
| OpenClaw | openclaw | openclaw.chemavx.xyz | este agente, PVC /data |
| Ollama | ollama | ollama.chemavx.xyz | llama3.1-es:8b + qwen3-es:14b, RTX 3060 |
| Open WebUI | open-webui | chat.chemavx.xyz | interfaz web para Ollama |
| ArgoCD | argocd | argocd.chemavx.xyz | GitOps CD |
| Authentik | authentik | auth.chemavx.xyz | SSO, postgresql en chemavx-k8 |
| Gitea | gitea | git.chemavx.xyz | con Gitea Runner |
| Grafana | monitoring | grafana.chemavx.xyz | kube-prometheus-stack |
| Prometheus | monitoring | prometheus.chemavx.xyz | |
| Uptime Kuma | monitoring | status.chemavx.xyz | |
| n8n | n8n | n8n.chemavx.xyz | |
| Vaultwarden | vaultwarden | vaultwarden.chemavx.xyz | |
| Homarr | homarr | home.chemavx.xyz | dashboard |
| Polymarket Bot | polymarket-bot | polymarket.chemavx.xyz | api + bot + dashboard + postgres |
| Portfolio | portfolio | chemavx.xyz | web personal |
| Gitea | gitea | git.chemavx.xyz | |
## Modelos Ollama activos
| Modelo | Tipo | Rol en OpenClaw | Tok/s | Notas |
|------------------|---------|-----------------|-------|-------|
| qwen3-es:14b | custom | primary | ~34 | Modelfile español + /nothink, base qwen3:14b |
| llama3.1-es:8b | custom | fallback | ~50 | Modelfile español, base llama3.1:8b |
| qwen3:14b | base | disponible | 34.5 | RTX 3060 |
| qwen2.5:14b | base | disponible | - | |
| llama3.1:8b | base | disponible | - | |
## Namespaces activos
argocd · authentik · backup-system · cert-manager · cloudflare-ddns · gitea · gpu-operator · homarr · monitoring · n8n · ollama · open-webui · openclaw · polymarket-bot · portfolio · vaultwarden
## Manifiestos
Todos los manifiestos en: `/home/chemavx/k8s-manifests/<namespace>/`
## RBAC OpenClaw
ServiceAccount `openclaw-agent` con ClusterRole read-only:
- Puede: get/list/watch — pods, logs, services, nodes, namespaces, events, deployments, replicasets, statefulsets, daemonsets, ingresses
- NO puede: delete, patch, create, update — nada
## Reglas de operación
Ver SOUL.md sección "Homelab Safety" — **NUNCA** ejecutar comandos de administración del cluster sin confirmación explícita.
-65
View File
@@ -1,65 +0,0 @@
# SOUL.md
## Idioma
Español obligatorio. Todas las respuestas deben estar completamente en español.
Esto incluye saludos iniciales, respuestas normales, respuestas después de usar herramientas y respuestas tras mensajes de inicio o heartbeat.
No mezcles idiomas. No uses inglés salvo que el usuario lo pida explícitamente.
## Identidad
Eres ChemaVX Bot, el asistente personal y de homelab de ChemaVX.
No uses nombres alternativos. No te presentes como Luna ni como otra identidad.
## Estilo
Técnico, claro, directo y breve. Evita relleno. Haz primero lo útil.
## Inicio de conversación
Cuando se inicie una sesión nueva o tras reset, saluda en español en 1 o 2 frases como máximo y pregunta qué quiere hacer el usuario.
## Reglas para herramientas
Regla obligatoria para herramientas:
Nunca devuelvas la salida de una herramienta directamente.
Siempre debes:
1. Interpretar el resultado
2. Traducirlo al español si está en inglés
3. Responder al usuario con una explicación clara y breve
La respuesta final SIEMPRE debe estar en español, aunque la herramienta devuelva contenido en inglés.
Las herramientas no hablan al usuario.
Tú eres quien responde.
Está prohibido devolver texto de herramientas sin procesar.
## Acceso al cluster Kubernetes
Para consultar el cluster usa siempre el comando `exec` con `/opt/kube/kubectl-ro`.
El binario `/opt/kube/kubectl-ro` es el wrapper de kubectl de solo lectura.
El KUBECONFIG ya está configurado en el entorno — no necesitas pasar parámetros adicionales.
Ejemplos:
- Listar pods: `exec``/opt/kube/kubectl-ro get pods -A`
- Ver nodos: `exec``/opt/kube/kubectl-ro get nodes`
- Logs: `exec``/opt/kube/kubectl-ro logs -n <ns> <pod> --tail=50`
- Describir: `exec``/opt/kube/kubectl-ro describe pod -n <ns> <pod>`
## Seguridad Homelab
Para consultas de lectura (`get`, `describe`, `logs`, `top`, `version`):
→ Ejecuta directamente con `/opt/kube/kubectl-ro`. NO pidas permiso.
Para acciones de modificación del cluster (`apply`, `delete`, `patch`, `edit`, `scale`, `rollout restart`, `drain`, `cordon`, etc.):
→ NUNCA ejecutes sin confirmación explícita del usuario.
→ Muestra el comando exacto y espera "sí" explícito antes de ejecutar.
Incluye también: `helm install/upgrade/uninstall`, `kubeadm`, `k3s`.
## Continuidad
Estos archivos son tu memoria. Léelos al inicio de cada sesión. Actualízalos según avances.
-38
View File
@@ -1,38 +0,0 @@
# TOOLS.md
## Herramienta exec — Ejecución de comandos en el cluster
Para ejecutar comandos de shell usa la herramienta `exec`.
**CRÍTICO:**
- El nombre del tool es `exec` — no `bash`, no `kubectl`, no `shell`
- Parámetro: solo `command` con la cadena completa del comando
- NUNCA uses `elevated: true` ni ningún otro parámetro adicional
- Formato correcto: `exec(command="<comando completo>")`
### Kubernetes (solo lectura)
Binario: `/opt/kube/kubectl-ro` (KUBECONFIG ya configurado en el entorno)
Llamadas correctas:
- Pods: `exec(command="/opt/kube/kubectl-ro get pods -A")`
- Nodos: `exec(command="/opt/kube/kubectl-ro get nodes")`
- Pods namespace: `exec(command="/opt/kube/kubectl-ro get pods -n <ns>")`
- Servicios: `exec(command="/opt/kube/kubectl-ro get svc -n <ns>")`
- Logs: `exec(command="/opt/kube/kubectl-ro logs -n <ns> deployment/<nombre> --tail=30")`
- Describir: `exec(command="/opt/kube/kubectl-ro describe pod -n <ns> <pod>")`
Subcomandos permitidos: `get`, `describe`, `logs`, `top`, `version`, `api-resources`
Para consultas de lectura: ejecuta directamente, SIN pedir permiso.
### Regla de uso
Ante cualquier pregunta sobre el cluster:
1. Llama a `exec(command="/opt/kube/kubectl-ro <subcomando> ...")`
2. Interpreta el resultado
3. Responde en español con un resumen claro y conciso
## Herramienta read
Para leer archivos: `read(path="/data/workspace/archivo.md")`
-10
View File
@@ -1,10 +0,0 @@
#!/bin/bash
DENIED="delete apply patch edit exec scale rollout drain cordon uncordon taint replace create annotate label"
if [ "$#" -eq 0 ]; then exec /opt/kube/kubectl "$@"; fi
SUBCMD="$1"
for d in $DENIED; do
if [ "$SUBCMD" = "$d" ]; then
echo "ERROR: \"$SUBCMD\" no permitido en modo solo lectura." >&2; exit 1
fi
done
exec /opt/kube/kubectl "$@"
-220
View File
@@ -1,220 +0,0 @@
{
"meta": {
"lastTouchedVersion": "2026.4.12",
"lastTouchedAt": "2026-04-20T15:00:00.000Z"
},
"browser": {
"cdpUrl": "http://localhost:9222"
},
"models": {
"mode": "merge",
"providers": {
"ollama": {
"baseUrl": "http://ollama.ollama.svc.cluster.local:11434",
"api": "ollama",
"apiKey": "ollama-local",
"models": [
{
"id": "qwen3-es:14b",
"name": "Qwen3 ES 14B",
"reasoning": false,
"input": [
"text"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 128000,
"contextTokens": 32768,
"maxTokens": 8192
},
{
"id": "qwen3:14b",
"name": "Qwen3 14B",
"reasoning": false,
"input": [
"text"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 128000,
"contextTokens": 32768,
"maxTokens": 8192
},
{
"id": "llama3.1-es:8b",
"name": "Llama 3.1 ES 8B",
"reasoning": false,
"input": [
"text"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 128000,
"contextTokens": 16384,
"maxTokens": 4096
},
{
"id": "llama3.1:8b",
"name": "Llama 3.1 8B",
"reasoning": false,
"input": [
"text"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 128000,
"contextTokens": 16384,
"maxTokens": 4096
}
]
}
}
},
"agents": {
"defaults": {
"userTimezone": "Europe/Madrid",
"timeFormat": "24",
"model": {
"primary": "ollama/qwen3-es:14b",
"fallbacks": [
"ollama/llama3.1-es:8b"
]
},
"timeoutSeconds": 600,
"heartbeat": {
"every": "6h"
},
"workspace": "/data/workspace",
"contextInjection": "continuation-skip",
"bootstrapMaxChars": 4000,
"bootstrapTotalMaxChars": 12000,
"bootstrapPromptTruncationWarning": "once",
"compaction": {
"mode": "safeguard"
},
"startupContext": {
"enabled": true,
"applyOn": [
"new",
"reset"
],
"dailyMemoryDays": 1,
"maxFileBytes": 8192,
"maxFileChars": 800,
"maxTotalChars": 1600
},
"contextPruning": {
"mode": "cache-ttl",
"ttl": "1h",
"keepLastAssistants": 3,
"softTrimRatio": 0.3,
"hardClearRatio": 0.5,
"minPrunableToolChars": 30000,
"softTrim": {
"maxChars": 2500,
"headChars": 1000,
"tailChars": 1000
},
"hardClear": {
"enabled": true,
"placeholder": "[Old tool result content cleared]"
},
"tools": {
"deny": [
"browser",
"canvas"
]
}
},
"memorySearch": {
"enabled": true,
"provider": "ollama"
}
}
},
"commands": {
"native": "auto",
"nativeSkills": "auto",
"restart": true,
"ownerDisplay": "raw"
},
"channels": {
"telegram": {
"enabled": true,
"dmPolicy": "pairing",
"botToken": "<set-via-infisical: homelab/prod/telegram TELEGRAM_BOT_TOKEN>",
"groupPolicy": "allowlist",
"streaming": {
"mode": "partial"
}
}
},
"gateway": {
"mode": "local",
"bind": "lan",
"controlUi": {
"allowedOrigins": [
"http://localhost:18789",
"http://192.168.1.92:18789",
"https://openclaw.chemavx.xyz"
]
},
"auth": {
"mode": "token",
"token": "9242ad46f6604770bb98ed2bda7bded7546f21c5233f1b24",
"rateLimit": {
"maxAttempts": 100,
"lockoutMs": 0
}
},
"trustedProxies": [
"10.42.0.0/16"
]
},
"plugins": {
"entries": {
"ollama": {
"enabled": true
},
"browser": {
"enabled": true
}
}
},
"tools": {
"profile": "coding",
"deny": [
"edit",
"write",
"apply_patch"
],
"exec": {
"host": "gateway",
"security": "allowlist",
"ask": "off",
"pathPrepend": [
"/opt/kube"
],
"timeoutSec": 30
},
"elevated": {
"enabled": true
}
}
}
-22
View File
@@ -1,22 +0,0 @@
apiVersion: secrets.infisical.com/v1beta1
kind: InfisicalStaticSecret
metadata:
name: telegram-notify
namespace: openclaw
spec:
# Shared, read-only machine identity (no write grant, no PushSecret).
infisicalAuthRef:
name: infisical-auth
namespace: infisical-operator
sources:
- projectId: 17e98e9d-70f5-43d1-8382-7da818dfcdd0 # project "homelab"
environmentSlug: prod
secretPath: /telegram # shared across all 5 namespaces
syncOptions:
refreshInterval: 60s
targets:
- kind: Secret
name: telegram-notify-infisical # parallel name — old telegram-notify stays live until 3c
namespace: openclaw
creationPolicy: Owner
# key passthrough: synced Secret carries TELEGRAM_BOT_TOKEN + TELEGRAM_CHAT_ID verbatim
-25
View File
@@ -1,25 +0,0 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: openclaw
namespace: openclaw
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
traefik.ingress.kubernetes.io/router.entrypoints: websecure
spec:
ingressClassName: traefik
rules:
- host: openclaw.chemavx.xyz
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: openclaw
port:
number: 18789
tls:
- hosts:
- openclaw.chemavx.xyz
secretName: openclaw-tls
-4
View File
@@ -1,4 +0,0 @@
apiVersion: v1
kind: Namespace
metadata:
name: openclaw
-54
View File
@@ -1,54 +0,0 @@
apiVersion: batch/v1
kind: Job
metadata:
name: postsync-smoke-test
namespace: openclaw
annotations:
argocd.argoproj.io/hook: PostSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
ttlSecondsAfterFinished: 600
backoffLimit: 0
template:
spec:
restartPolicy: Never
containers:
- name: smoke-test
image: curlimages/curl:latest
env:
- name: TELEGRAM_BOT_TOKEN
valueFrom:
secretKeyRef:
name: telegram-notify-infisical
key: TELEGRAM_BOT_TOKEN
- name: TELEGRAM_CHAT_ID
valueFrom:
secretKeyRef:
name: telegram-notify-infisical
key: TELEGRAM_CHAT_ID
command: ["/bin/sh", "-c"]
args:
- |
set -e
BASE="http://openclaw.openclaw.svc.cluster.local:18789"
notify() {
curl -s --max-time 10 -X POST \
"https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
-d "chat_id=${TELEGRAM_CHAT_ID}" \
--data-urlencode "text=$1" \
> /dev/null || true
}
fail() {
notify "[FAIL] openclaw PostSync: $1"
exit 1
}
echo "--- [1/1] GET / (HTTP 200) ---"
curl -sfL --max-time 15 --retry 3 --retry-delay 5 --retry-all-errors \
"$BASE/" > /dev/null || fail "GET / returned non-200"
echo "OK"
notify "[OK] openclaw PostSync passed"
echo "=== openclaw: all smoke tests passed ==="
-15
View File
@@ -1,15 +0,0 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
annotations:
# Never let ArgoCD prune this PVC: it holds persistent app data.
argocd.argoproj.io/sync-options: Prune=false
name: openclaw-pvc
namespace: openclaw
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 5Gi
-36
View File
@@ -1,36 +0,0 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: openclaw-agent
namespace: openclaw
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: openclaw-agent-readonly
rules:
- apiGroups: [""]
resources: [pods, pods/log, services, nodes, namespaces, events]
verbs: [get, list, watch]
- apiGroups: [apps]
resources: [deployments, replicasets, statefulsets, daemonsets]
verbs: [get, list, watch]
- apiGroups: [networking.k8s.io]
resources: [ingresses]
verbs: [get, list, watch]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: openclaw-agent-readonly-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: openclaw-agent-readonly
subjects:
- kind: ServiceAccount
name: openclaw-agent
namespace: openclaw
-12
View File
@@ -1,12 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: openclaw
namespace: openclaw
spec:
selector:
app: openclaw
ports:
- port: 18789
targetPort: 18789
type: ClusterIP