The "Persistent Sandbox" Architecture
Goal: Provide friends/family with a robust, persistent OpenClaw environment on a VPS (via Coolify) that feels like a full Linux VM but runs safely in a Docker container.
Core Concept
Use Docker volumes to persist package managers (brew, uv, npm) so user installations survive container updates/restarts. No inbound ports required.
Key Components
Package Managers (Persisted):
- Homebrew (Linuxbrew): System tools (
ffmpeg,jq,gh). - uv (Astral): Python environment, virtualenvs, and toolchain.
- npm (Global): Node.js CLI tools (
cdk,vercel,firebase-tools).
- Homebrew (Linuxbrew): System tools (
Volumes Strategy:
workspace: User code/projects.data: Agent memory/config.brew:/home/linuxbrew/.linuxbrew(The "System Binaries").npm:/root/.npm-global(Global node modules).uv:/root/.uv_cache(Python build cache).
Networking:
- Outbound Only: Connects to Relay Network via WebSocket.
- No Inbound Ports: Safe behind firewall. No subdomain/SSL config needed.
- Web Previews: User handles via
cloudflaredorngrok(installed via brew).
Implementation (Docker Compose)
Paste this into Coolify for each user (e.g., agent-henry).
yaml
services:
agent-henry:
image: ghcr.io/openclaw/openclaw:latest
user: root
restart: unless-stopped
environment:
- OPENCLAW_GATEWAY_TOKEN=henry-secret-token
# PATH: Prioritize persisted user binaries
- PATH=/root/.npm-global/bin:/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# CONFIG: Tell tools where to persist
- NPM_CONFIG_PREFIX=/root/.npm-global
- UV_CACHE_DIR=/root/.uv_cache
volumes:
# --- DATA (The "Hard Drive") ---
- henry_workspace:/root/.openclaw/workspace # Code
- henry_data:/root/.openclaw # Agent Brain
# --- TOOLS (The "App Store") ---
- henry_brew:/home/linuxbrew/.linuxbrew # Brew (ffmpeg, etc)
- henry_npm:/root/.npm-global # NPM Global (cdk, etc)
- henry_uv:/root/.uv_cache # UV Cache (python speed)
# Startup Script: Fix permissions & ensure uv is installed
command: >
/bin/bash -c "
mkdir -p /root/.npm-global/bin &&
chown -R root:root /home/linuxbrew /root/.npm-global &&
if ! command -v uv &> /dev/null; then curl -LsSf https://astral.sh/uv/install.sh | sh; fi &&
openclaw gateway start --host"
volumes:
henry_workspace:
henry_data:
henry_brew:
henry_npm:
henry_uv: