search
AILinux5 min lectura

OpenClaw: instalación oficial (Quadlet) vs distrobox — lo que la documentación no te cuenta

Pablo IB

TL;DR: OpenClaw recomienda instalar con su script oficial (run-openclaw-podman.sh) que usa Quadlet + --userns=keep-id. Yo lo instalé en un container distrobox ya existente. Los dos funcionan, pero tienen trade-offs muy distintos en seguridad, permisos, y mantenimiento. Aquí va la comparativa real, no la de marketing.


Las dos rutas

Ruta A: Instalación oficial (Quadlet)

OpenClaw incluye scripts para Podman en su paquete npm. El proceso:

# 1. Build de la imagen
./scripts/podman/setup.sh

# 2. Con Quadlet (systemd nativo)
./scripts/podman/setup.sh --quadlet

# 3. Lanzar
./scripts/run-openclaw-podman.sh launch

Esto crea:

  • Imagen openclaw:local (basada en la imagen oficial de OpenClaw)
  • Container con --userns=keep-id --user <tu_uid>:<tu_gid>
  • Quadlet en ~/.config/containers/systemd/openclaw.container
  • Token en ~/.openclaw/.env
  • Puertos publicados en 127.0.0.1:18789 y 127.0.0.1:18790

Ruta B: Distrobox

Yo ya tenía un container distrobox con Debian Bookworm para otros proyectos. Instalé OpenClaw dentro:

# Dentro del container
npm install -g openclaw
openclaw configure

Y creé un systemd service manual:

# ~/.config/systemd/user/openclaw-gateway.service
ExecStart=/usr/bin/podman exec -u pablo openclaw bash -c '...'

La comparativa real

AspectoOficial (Quadlet)Distrobox
Imagenopenclaw:local (propias, optimizada)debian:bookworm (genérica)
UserNSkeep-id (mapea UIDs automáticamente)private (sin mapeo)
UsuarioTu uid:gid explícitoRoot por defecto, necesita -u pablo
PrivilegedNo
Bind mountsSolo ~/.openclaw28 mounts (todo /home, /tmp, /usr…)
PuertosSolo 18789 + 18790 (en 127.0.0.1)Hereda del host
SystemdQuadlet nativo (openclaw.service)Service manual
TokenAuto-generado en ~/.openclaw/.envManual
UpdatesRebuild de imagennpm update -g openclaw
TamañoImagen dedicada (~500MB)Imagen compartida con otros tools
SeguridadHardened por defectoPermisivo (privileged, full mounts)
Permisos pluginsAutomático (keep-id)Manual (-u pablo)

El problema que no te cuenta la documentación

La documentación oficial dice:

“Permission denied (EACCES) on config or workspace: The container runs with –userns=keep-id and –user : by default.”

Es decir: si usas el script oficial, esto no te pasa. Los UIDs se mapean solos. Plugins, config, workspace — todo pertenece al usuario correcto automáticamente.

La realidad con distrobox: 3 horas de debug

El container corre como root. Los archivos del host son de tu usuario. OpenClaw detecta el mismatch y bloquea todos los plugins externos:

WARN plugin codex: blocked plugin candidate: suspicious ownership
  (/home/pablo/.openclaw/npm/node_modules/@openclaw/codex, uid=1000, expected uid=0 or root)

Lo que intenté (y no funcionó)

chown -R root:root — Funcionó hasta que instalé algo desde el host o ejecuté openclaw doctor --fix. Los archivos volvían a UID 1000. Y al reiniciar: bloqueados.

Instalar desde dentro del container — Los archivos se creaban como root ✅, pero el CLI del host decía “plugin not found” ❌. El host valida contra su propio filesystem.

El círculo vicioso:

Host instala    → archivos UID 1000 → container bloquea "suspicious ownership"
Container instala → archivos root    → host CLI dice "plugin not found"

La solución: -u pablo

Distrobox crea un usuario dentro del container con el mismo UID que tu usuario del host. En mi caso, pablo (UID 1000) existe en ambos lados.

# Verificar
podman exec openclaw grep pablo /etc/passwd
# pablo::1000:1000:Pablo:/home/pablo:/usr/bin/fish

# Solución: un flag
podman exec -u pablo openclaw bash -c 'openclaw gateway run ...'

Un flag. Tres letras. El gateway corre como pablo dentro del container. Los archivos que crea son pablo:pablo. Desde el host también son pablo:pablo. Cero conflicto.

Pero esto no está documentado en ningún sitio. Lo encontré por trial-and-error después de 3 horas.

El issue de GitHub

Encontré un reporte similar en openclaw/openclaw#33685: en Fedora Silverblue, el script oficial también fallaba con permisos porque el UID mapping no funcionaba con su configuración de storage. El workaround: quitar UserNS=keep-id y cambiar ownership manualmente. Mismo problema, distro diferente.


¿Cuándo elegir cada ruta?

Elige la ruta oficial si:

  • ✅ Estás instalando OpenClaw por primera vez
  • ✅ No tienes un container existente
  • ✅ Quieres la configuración más segura (no-privileged, keep-id)
  • ✅ Quieres updates limpios (rebuild imagen)
  • ✅ Estás en un entorno multi-usuario o production-ish

Elige distrobox si:

  • ✅ Ya tienes un container distrobox con herramientas compartidas
  • ✅ Quieres que OpenClaw comparta el mismo entorno que otros tools
  • ✅ No quieres mantener una imagen Docker separada
  • ✅ Actualizas con npm update en vez de rebuild
  • ⚠️ Pero tienes que añadir -u pablo al service

Mi situación

Yo elegí distrobox porque mi container ya tiene Node.js, Python, y otras herramientas. No quería mantener una imagen separada solo para OpenClaw. El trade-off: tuve que debuguear los permisos manualmente y el container es privileged (menos aislamiento).


Cómo migrar de distrobox a oficial (si algún día quieres)

# 1. Backup del estado actual
cp -r ~/.openclaw ~/.openclaw.backup

# 2. Parar el container actual
podman stop openclaw

# 3. Setup oficial
cd $(npm root -g)/openclaw
./scripts/podman/setup.sh --quadlet

# 4. Restaurar config
cp ~/.openclaw.backup/openclaw.json ~/.openclaw/openclaw.json
cp -r ~/.openclaw.backup/workspace ~/.openclaw/workspace
cp -r ~/.openclaw.backup/agents ~/.openclaw/agents
cp -r ~/.openclaw.backup/memory ~/.openclaw/memory

# 5. Iniciar
systemctl --user daemon-reload
systemctl --user start openclaw.service

Lecciones aprendidas

1. Lee la documentación oficial ANTES de improvisar. Si hubiera empezado con el script oficial, habría ahorrado 3 horas de permisos.

2. Si usas distrobox, verifica el usuario. podman exec <container> id <tu-usuario>. Si existe, usa -u <tu-usuario>. Si no existe, créalo.

3. openclaw doctor --fix puede empeorar las cosas. En mi caso, desactivó skills que yo había instalado manualmente. Úsalo con cuidado y revisa qué cambia antes de aceptar.

4. El security audit es tu amigo. openclaw security audit te dice exactamente qué está mal. En mi caso pasó de 3 critical a 0 después de: rotar token, añadir rate limiting, limpiar allowedOrigins, y fixear plugin ownership.

5. Los plugins externos necesitan atención. memory-core (bundled) funciona siempre. memory-lancedb (externo) necesita que el ownership sea correcto. Si ves “suspicious ownership”, el problema no es el plugin — es cómo corres el container.


El estado actual de mi setup

Container:     distrobox (debian:bookworm)
Gateway:       -u pablo, puerto 18789, bind lan
Modelo:        glm-5-turbo (z.ai) + failover gpt-5.4-mini
Compaction:    glm-4.7
Memory:        memory-lancedb + text-embedding-3-small (z.ai)
Acceso móvil:  Tailscale serve → HTTPS
Telegram:      @Sitensobot
Skills:        github, obsidian, session-logs (3 reales, 0 rotos)
Contexto:      3.8 KB inyectado (target < 8KB)
Security:      0 critical, 0 warn
Sessions:      185
Disco:         612 MB (~/.openclaw/)

Funciona. Pero si volviera a empezar, usaría el script oficial.