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:
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
@@ -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. |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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": ""
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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' },
|
||||
];
|
||||
|
||||
|
||||
@@ -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: {}
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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")`
|
||||
@@ -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 "$@"
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,4 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: openclaw
|
||||
@@ -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 ==="
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,12 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: openclaw
|
||||
namespace: openclaw
|
||||
spec:
|
||||
selector:
|
||||
app: openclaw
|
||||
ports:
|
||||
- port: 18789
|
||||
targetPort: 18789
|
||||
type: ClusterIP
|
||||
Reference in New Issue
Block a user