chore(openclaw): golden config snapshot + RBAC manifest in git
- Add openclaw/golden/ with stable copies of openclaw.json, SOUL.md, TOOLS.md, HOMELAB.md, kubectl-ro - Fix HOMELAB.md model roles (qwen3-es:14b=primary, llama3.1-es:8b=fallback) - Add rbac-openclaw-agent.yaml (ClusterRole read-only + binding + SA) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,62 @@
|
|||||||
|
# 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.
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
# 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.
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# 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")`
|
||||||
Executable
+10
@@ -0,0 +1,10 @@
|
|||||||
|
#!/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 "$@"
|
||||||
@@ -0,0 +1,220 @@
|
|||||||
|
{
|
||||||
|
"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": "8611913802:AAFlrFtc0vYISOliO_W8B4c-W1ue0hG9Fio",
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
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
|
||||||
Reference in New Issue
Block a user