前言
OpenClaw 作为连接 Claude、DeepSeek 等 LLM 与 Discord、Telegram 等平台的 AI 助手网关,在 UNRAID 社区中逐渐受到关注。然而,官方 CA 应用市场提供的模板存在严重的路径映射错误,导致插件系统失效、Workspace 目录空载等典型问题。
本文记录从踩坑到解决的完整过程,提供经过验证的 UNRAID XML 模板,并说明为何通过 onboard 交互式配置比环境变量注入更安全可靠。
环境信息:UNRAID 7.x | OpenClaw v0.x | 网络模式:Bridge
一、解决过程:从故障排查到成功部署
1.1 初始故障现象
在 UNRAID CA 应用市场部署 OpenClaw 后,容器虽能启动且 Web UI 可访问,但立即发现功能残缺:
Workspace 空载:宿主机映射目录 /mnt/user/appdata/openclaw/workspace 始终为空,无 AGENTS.md、skills 或 memory 目录生成
插件系统失效:进入容器执行 openclaw plugins list 报错,提示无法读取配置
配置不生效:修改 /mnt/user/appdata/openclaw/config/openclaw.json 后重启容器,变更未被应用读取
Web 终端受限:通过 UNRAID Web UI 进入容器控制台时,部分命令无法正常使用
1.2 排查与根因定位
通过对比容器内路径与宿主机映射,发现核心问题为路径错位:
用户目录错配:CA 模板将配置映射到 /root/.openclaw,但 OpenClaw 应用实际运行于 node 用户上下文,寻找的是 /home/node/.openclaw
Workspace 路径错误:CA 模板将工作目录设为 /home/node/clawd,而官方规范应为 /home/node/.openclaw/workspace(作为配置目录的子目录)
HOME 变量缺失:未设置 HOME=/home/node 导致应用无法正确解析相对路径
初始化脚本干扰:CA 模板的 PostArgs 试图在错误的 /root/.openclaw 路径预生成配置文件,导致配置"悬空"
1.3 修正过程
基于官方 docker-compose.yml 的规范,进行以下修正:
路径修正:
Config Path Target:/root/.openclaw → /home/node/.openclaw
Workspace Path Target:/home/node/clawd → /home/node/.openclaw/workspace
添加 Environment Variable:HOME=/home/node
初始化方式重构:
清空 PostArgs 字段(移除 CA 模板的自动初始化脚本)
保留 ExtraParams 为 --user root(注意:不含 --hostname 参数)
改为手动执行 openclaw onboard --install-daemon 完成初始化
权限与 Shell 优化:
Privileged 设为 true(解决 UNRAID 特定的权限限制)
添加 PUID=1000 和 PGID=100 环境变量(匹配 node 用户/组,确保文件权限一致性)
将 <Shell> 从 sh 改为 bash(修复 Web UI 终端命令行功能)
1.4 验证成功
修正后部署流程:
启动容器
进入控制台执行 openclaw onboard --install-daemon 完成交互式引导
检查宿主机 workspace 目录,正常生成 AGENTS.md、skills/、memory/ 等结构
插件系统恢复正常,配置文件修改后重启容器可正确加载
Web UI 终端可正常使用 docker 及相关命令
二、模板差异分析
2.1 核心差异对比表
2.2 模板文件展示
模板 A:修正后的 UNRAID 模板(my-OpenClaw.xml)
<?xml version="1.0"?>
<Container version="2">
<Name>OpenClaw</Name>
<Repository>ghcr.io/openclaw/openclaw:latest</Repository>
<Registry>https://github.com/openclaw/openclaw/pkgs/container/openclaw</Registry>
<Network>bridge</Network>
<MyIP/>
<Shell>bash</Shell>
<Privileged>true</Privileged>
<Support>https://forums.unraid.net/topic/196865-support-openclaw-ai-personal-assistant</Support>
<Project>https://github.com/openclaw/openclaw</Project>
<ReadMe/>
<Overview>OpenClaw is a powerful AI assistant gateway that connects Claude and other LLMs to messaging platforms like Discord, Telegram, WhatsApp, and more. Features include file access, shell commands, web browsing, cron jobs, and a web-based Control UI.
To access the Control UI, add your token to the URL: http://YOUR-IP:18789/?token=YOUR-GATEWAY-TOKEN
For setup details and documentation, see: https://github.com/jdhill777/openclaw-unraid
OpenClaw project and source: https://github.com/openclaw/openclaw
Requires at least one LLM API key. Anthropic (Claude) is recommended, but many providers are supported.
Optional Homebrew: Some skills require tools installed via brew/go. This is completely optional and at your own discretion. If needed, open OpenClaw's container console and run:
NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
We recommend reviewing the install script at brew.sh before running. You can ignore the "Next steps" output - the template has already configured the PATH for you.</Overview>
<Category>Productivity: Tools:Utilities AI:</Category>
<WebUI>http://[IP]:[PORT:18789]/</WebUI>
<TemplateURL>https://raw.githubusercontent.com/selfhosters/unRAID-CA-templates/master/templates/openclaw.xml</TemplateURL>
<Icon>https://raw.githubusercontent.com/selfhosters/unRAID-CA-templates/master/templates/img/openclaw.png</Icon>
<ExtraParams>--user root</ExtraParams>
<PostArgs/>
<CPUset/>
<DateInstalled>1775638320</DateInstalled>
<DonateText/>
<DonateLink/>
<Requires/>
<Config Name="Control UI Port" Target="18789" Default="18789" Mode="tcp" Description="Port for Control UI and Gateway API. Access at http://IP:18789/?token=YOUR_TOKEN" Type="Port" Display="always" Required="true" Mask="false">18789</Config>
<Config Name="Config Path" Target="/home/node/.openclaw" Default="/mnt/user/appdata/openclaw/config" Mode="rw" Description="Path to store OpenClaw configuration files, sessions, and credentials" Type="Path" Display="always" Required="true" Mask="false">/mnt/disk1/appdata/openclaw/config</Config>
<Config Name="Workspace Path" Target="/home/node/.openclaw/workspace" Default="/mnt/user/appdata/openclaw/workspace" Mode="rw" Description="Path for agent workspace (files, memory, AGENTS.md, projects)" Type="Path" Display="always" Required="true" Mask="false">/mnt/disk1/appdata/openclaw/workspace</Config>
<Config Name="HOME" Target="HOME" Default="/home/node" Mode="" Description="" Type="Variable" Display="always" Required="false" Mask="false">/home/node</Config>
<Config Name="OPENCLAW_BRIDGE_PORT" Target="18790" Default="" Mode="tcp" Description="" Type="Port" Display="always" Required="false" Mask="false">18790</Config>
<Config Name="PUID" Target="PUID" Default="" Mode="" Description="" Type="Variable" Display="always" Required="false" Mask="false">1000</Config>
<Config Name="PGID" Target="PGID" Default="" Mode="" Description="" Type="Variable" Display="always" Required="false" Mask="false">100</Config>
<TailscaleEnabled>true</TailscaleEnabled>
<TailscaleIsExitNode>false</TailscaleIsExitNode>
<TailscaleHostname>openclaw</TailscaleHostname>
<TailscaleExitNodeIP/>
<TailscaleSSH>false</TailscaleSSH>
<TailscaleUserspaceNetworking>false</TailscaleUserspaceNetworking>
<TailscaleLANAccess>false</TailscaleLANAccess>
<TailscaleServe>serve</TailscaleServe>
<TailscaleWebUI>https://[hostname][magicdns]/</TailscaleWebUI>
<TailscaleServePort>18789</TailscaleServePort>
<TailscaleServeTarget/>
<TailscaleServeLocalPath/>
<TailscaleServeProtocol/>
<TailscaleServeProtocolPort/>
<TailscaleServePath/>
<TailscaleDParams/>
<TailscaleParams/>
<TailscaleRoutes/>
<TailscaleAcceptRoutes>false</TailscaleAcceptRoutes>
<TailscaleStateDir>/mnt/disk1/appdata/openclaw/tailscale_state</TailscaleStateDir>
</Container>
关键特征:
Config Path Target: /home/node/.openclaw
Workspace Path Target: /home/node/.openclaw/workspace
Environment Variables: HOME=/home/node, PUID=1000, PGID=100
PostArgs: 空
ExtraParams: --user root
Privileged: true
Shell: bash
模板 B:官方 Docker Compose 参考(docker-compose.yml)
services:
openclaw-gateway:
image: ${OPENCLAW_IMAGE:-openclaw:local}
environment:
HOME: /home/node
TERM: xterm-256color
OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN:-}
OPENCLAW_ALLOW_INSECURE_PRIVATE_WS: ${OPENCLAW_ALLOW_INSECURE_PRIVATE_WS:-}
CLAUDE_AI_SESSION_KEY: ${CLAUDE_AI_SESSION_KEY:-}
CLAUDE_WEB_SESSION_KEY: ${CLAUDE_WEB_SESSION_KEY:-}
CLAUDE_WEB_COOKIE: ${CLAUDE_WEB_COOKIE:-}
TZ: ${OPENCLAW_TZ:-UTC}
volumes:
- ${OPENCLAW_CONFIG_DIR}:/home/node/.openclaw
- ${OPENCLAW_WORKSPACE_DIR}:/home/node/.openclaw/workspace
## Uncomment the lines below to enable sandbox isolation
## (agents.defaults.sandbox). Requires Docker CLI in the image
## (build with --build-arg OPENCLAW_INSTALL_DOCKER_CLI=1) or use
## scripts/docker/setup.sh with OPENCLAW_SANDBOX=1 for automated setup.
## Set DOCKER_GID to the host's docker group GID (run: stat -c '%g' /var/run/docker.sock).
# - /var/run/docker.sock:/var/run/docker.sock
# group_add:
# - "${DOCKER_GID:-999}"
ports:
- "${OPENCLAW_GATEWAY_PORT:-18789}:18789"
- "${OPENCLAW_BRIDGE_PORT:-18790}:18790"
init: true
restart: unless-stopped
command:
[
"node",
"dist/index.js",
"gateway",
"--bind",
"${OPENCLAW_GATEWAY_BIND:-lan}",
"--port",
"18789",
]
healthcheck:
test:
[
"CMD",
"node",
"-e",
"fetch('http://127.0.0.1:18789/healthz').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))",
]
interval: 30s
timeout: 5s
retries: 5
start_period: 20s
openclaw-cli:
image: ${OPENCLAW_IMAGE:-openclaw:local}
network_mode: "service:openclaw-gateway"
cap_drop:
- NET_RAW
- NET_ADMIN
security_opt:
- no-new-privileges:true
environment:
HOME: /home/node
TERM: xterm-256color
OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN:-}
OPENCLAW_ALLOW_INSECURE_PRIVATE_WS: ${OPENCLAW_ALLOW_INSECURE_PRIVATE_WS:-}
BROWSER: echo
CLAUDE_AI_SESSION_KEY: ${CLAUDE_AI_SESSION_KEY:-}
CLAUDE_WEB_SESSION_KEY: ${CLAUDE_WEB_SESSION_KEY:-}
CLAUDE_WEB_COOKIE: ${CLAUDE_WEB_COOKIE:-}
TZ: ${OPENCLAW_TZ:-UTC}
volumes:
- ${OPENCLAW_CONFIG_DIR}:/home/node/.openclaw
- ${OPENCLAW_WORKSPACE_DIR}:/home/node/.openclaw/workspace
stdin_open: true
tty: true
init: true
entrypoint: ["node", "dist/index.js"]
depends_on:
- openclaw-gateway
参考要点:
volumes 映射逻辑:/home/node/.openclaw 与 /home/node/.openclaw/workspace
环境变量 HOME: /home/node 的定义位置
无 PostArgs 或 Entrypoint 覆盖,依赖镜像默认命令
模板 C:CA 市场原始模板(openclaw.xml)
<?xml version="1.0"?>
<Container version="2">
<Name>OpenClaw</Name>
<Repository>ghcr.io/openclaw/openclaw:latest</Repository>
<Registry>https://github.com/openclaw/openclaw/pkgs/container/openclaw</Registry>
<Network>bridge</Network>
<Shell>sh</Shell>
<Privileged>false</Privileged>
<Support>https://forums.unraid.net/topic/196865-support-openclaw-ai-personal-assistant</Support>
<Project>https://github.com/openclaw/openclaw</Project>
<Overview>OpenClaw is a powerful AI assistant gateway that connects Claude and other LLMs to messaging platforms like Discord, Telegram, WhatsApp, and more. Features include file access, shell commands, web browsing, cron jobs, and a web-based Control UI.

To access the Control UI, add your token to the URL: http://YOUR-IP:18789/?token=YOUR-GATEWAY-TOKEN

For setup details and documentation, see: https://github.com/jdhill777/openclaw-unraid

OpenClaw project and source: https://github.com/openclaw/openclaw

Requires at least one LLM API key. Anthropic (Claude) is recommended, but many providers are supported.

Optional Homebrew: Some skills require tools installed via brew/go. This is completely optional and at your own discretion. If needed, open OpenClaw's container console and run:

NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

We recommend reviewing the install script at brew.sh before running. You can ignore the "Next steps" output - the template has already configured the PATH for you.</Overview>
<Category>Productivity: Tools: AI</Category>
<WebUI>http://[IP]:[PORT:18789]/</WebUI>
<Icon>https://raw.githubusercontent.com/jdhill777/openclaw-unraid/master/openclaw-icon.png</Icon>
<Screenshot>https://raw.githubusercontent.com/jdhill777/openclaw-unraid/master/screenshot.png</Screenshot>
<ExtraParams>--user root --hostname OpenClaw</ExtraParams>
<PostArgs>sh -c "mkdir -p /root/.openclaw /home/linuxbrew; [ -s /root/.openclaw/openclaw.json ] || echo '{\"gateway\":{\"mode\":\"local\",\"bind\":\"lan\",\"controlUi\":{\"allowInsecureAuth\":true},\"auth\":{\"mode\":\"token\"}}}' > /root/.openclaw/openclaw.json; exec node dist/index.js gateway --bind lan"</PostArgs>
<DonateText>Support the template maintainer</DonateText>
<DonateLink>https://buymeacoffee.com/jdhill777</DonateLink>
<Description>OpenClaw is a powerful AI assistant gateway that connects Claude and other LLMs to messaging platforms like Discord, Telegram, WhatsApp, and more. Features include file access, shell commands, web browsing, cron jobs, and a web-based Control UI. To access the Control UI, add your token to the URL: http://YOUR-IP:18789/?token=YOUR-GATEWAY-TOKEN</Description>
<!-- Port -->
<Config Name="Control UI Port" Target="18789" Default="18789" Mode="tcp" Description="Port for Control UI and Gateway API. Access at http://IP:18789/?token=YOUR_TOKEN" Type="Port" Display="always" Required="true" Mask="false">18789</Config>
<!-- Volume Mappings -->
<Config Name="Config Path" Target="/root/.openclaw" Default="/mnt/user/appdata/openclaw/config" Mode="rw" Description="Path to store OpenClaw configuration files, sessions, and credentials" Type="Path" Display="always" Required="true" Mask="false">/mnt/user/appdata/openclaw/config</Config>
<Config Name="Workspace Path" Target="/home/node/clawd" Default="/mnt/user/appdata/openclaw/workspace" Mode="rw" Description="Path for agent workspace (files, memory, AGENTS.md, projects)" Type="Path" Display="always" Required="true" Mask="false">/mnt/user/appdata/openclaw/workspace</Config>
<Config Name="Projects Path" Target="/projects" Default="/mnt/user/appdata/openclaw/projects" Mode="rw" Description="Optional additional path for coding projects" Type="Path" Display="advanced" Required="false" Mask="false">/mnt/user/appdata/openclaw/projects</Config>
<Config Name="Homebrew Path" Target="/home/linuxbrew/.linuxbrew" Default="/mnt/user/appdata/openclaw/homebrew" Mode="rw" Description="Persistent storage for Homebrew packages. If you install Homebrew manually via console, this mount ensures it persists across restarts." Type="Path" Display="advanced" Required="false" Mask="false">/mnt/user/appdata/openclaw/homebrew</Config>
<!-- Required Settings -->
<Config Name="Gateway Token" Target="OPENCLAW_GATEWAY_TOKEN" Default="" Mode="" Description="Secret token for authentication. Generate with: openssl rand -hex 24 (or use any secret value). Required to access the Control UI." Type="Variable" Display="always" Required="true" Mask="true"/>
<!-- LLM API Keys (fill in at least one) -->
<Config Name="Anthropic API Key" Target="ANTHROPIC_API_KEY" Default="" Mode="" Description="API key for Claude models (recommended). Get from console.anthropic.com" Type="Variable" Display="always" Required="false" Mask="true"/>
<Config Name="OpenAI API Key" Target="OPENAI_API_KEY" Default="" Mode="" Description="API key for GPT models. Get from platform.openai.com" Type="Variable" Display="always" Required="false" Mask="true"/>
<Config Name="OpenRouter API Key" Target="OPENROUTER_API_KEY" Default="" Mode="" Description="API key for OpenRouter - access 100+ models. Get from openrouter.ai" Type="Variable" Display="always" Required="false" Mask="true"/>
<Config Name="Gemini API Key" Target="GEMINI_API_KEY" Default="" Mode="" Description="API key for Google Gemini models. Get from aistudio.google.com" Type="Variable" Display="always" Required="false" Mask="true"/>
<Config Name="Groq API Key" Target="GROQ_API_KEY" Default="" Mode="" Description="API key for Groq (fast Llama/Mixtral inference). Get from console.groq.com" Type="Variable" Display="always" Required="false" Mask="true"/>
<Config Name="xAI API Key" Target="XAI_API_KEY" Default="" Mode="" Description="API key for xAI Grok models. Get from console.x.ai" Type="Variable" Display="always" Required="false" Mask="true"/>
<Config Name="Z.AI API Key" Target="ZAI_API_KEY" Default="" Mode="" Description="API key for Z.AI/Zhipu GLM models. Get from z.ai/model-api" Type="Variable" Display="always" Required="false" Mask="true"/>
<!-- Subscription-based Auth -->
<Config Name="GitHub Copilot Token" Target="COPILOT_GITHUB_TOKEN" Default="" Mode="" Description="(Advanced) GitHub Copilot OAuth token. Requires running 'openclaw models auth login-github-copilot' on another machine first." Type="Variable" Display="advanced" Required="false" Mask="true"/>
<!-- Optional: Channel Tokens (can also configure via Control UI after install) -->
<Config Name="Discord Bot Token" Target="DISCORD_BOT_TOKEN" Default="" Mode="" Description="(Optional) Discord bot token for Discord integration. Can also configure via Control UI after install." Type="Variable" Display="advanced" Required="false" Mask="true"/>
<Config Name="Telegram Bot Token" Target="TELEGRAM_BOT_TOKEN" Default="" Mode="" Description="(Optional) Telegram bot token from @BotFather. Can also configure via Control UI after install." Type="Variable" Display="advanced" Required="false" Mask="true"/>
<!-- Advanced Settings -->
<Config Name="Gateway Port" Target="OPENCLAW_GATEWAY_PORT" Default="18789" Mode="" Description="Internal gateway port. Change if 18789 is already in use (must match Control UI Port)." Type="Variable" Display="advanced" Required="false" Mask="false">18789</Config>
<Config Name="PATH" Target="PATH" Default="/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/root/.bun/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" Mode="" Description="System PATH including Homebrew. Do not modify unless you know what you're doing." Type="Variable" Display="advanced" Required="false" Mask="false">/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/root/.bun/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin</Config>
<Config Name="Web Search API Key" Target="BRAVE_API_KEY" Default="" Mode="" Description="(Optional) Brave Search API key for web search. Free tier: 2000 queries/month at brave.com/search/api" Type="Variable" Display="advanced" Required="false" Mask="true"/>
</Container>
问题点标注:
<Config Target="/root/.openclaw" .../> ← 错误用户目录
<Config Target="/home/node/clawd" .../> ← 错误路径名称与层级
<PostArgs> 字段包含复杂初始化逻辑,在错误路径生成配置
缺少 HOME、PUID、PGID 环境变量定义
<Shell>sh</Shell> ← 导致 Web UI 终端功能受限
三、问题案例与解决办法
案例 1:Workspace 目录为空,无 AGENTS.md 生成
现象:宿主机 workspace 文件夹为空,Web UI 中文件管理功能无法使用。
原因:CA 模板将 Workspace 映射到 /home/node/clawd,但应用实际写入 /home/node/.openclaw/workspace。由于挂载点错误,容器内写入操作未同步到宿主机。
解决:
停止容器
修改模板:将 Workspace Path Target 从 /home/node/clawd 改为 /home/node/.openclaw/workspace
重新启动并执行 openclaw onboard --install-daemon
案例 2:配置文件修改后不生效,重启后丢失设置
现象:修改 /mnt/user/appdata/openclaw/config/openclaw.json 后重启容器,配置恢复默认值。
原因:CA 模板将配置映射到 /root/.openclaw,而应用实际读取 /home/node/.openclaw。PostArgs 脚本在 /root/.openclaw 生成初始配置,应用启动后读取的是未挂载的 /home/node/.openclaw(容器层),导致宿主机修改无效。
解决:
修改模板:Config Path Target 改为 /home/node/.openclaw
添加 Environment Variable:HOME=/home/node
清空 PostArgs,避免自动脚本覆盖配置
如已有配置,手动将文件从 /root/.openclaw 复制到 /home/node/.openclaw
案例 3:执行 openclaw 命令提示 "command not found" 或权限 denied
现象:进入容器后无法执行 openclaw 相关命令。
原因:CA 模板使用 --user root 但环境变量缺失,或 Privileged 权限不足导致无法访问必要系统资源。
解决:
确保 ExtraParams 包含 --user root
确保 Privileged 设置为 true
确保 HOME 环境变量设置为 /home/node(影响 Shell 配置加载)
案例 4:Onboard 执行失败,提示目录不可写
现象:运行 openclaw onboard --install-daemon 时提示无法创建目录或写入文件。
原因:路径映射后权限未正确传递,或挂载目录在宿主机端由 root 创建,容器内 node 用户(UID 1000)无法写入。
解决:
在模板中添加 PUID=1000 和 PGID=100 环境变量
在 UNRAID 终端预先创建目录并设置权限:
mkdir -p /mnt/user/appdata/openclaw/{config,workspace} chown 1000:100 /mnt/user/appdata/openclaw -R或使用 Privileged=true 赋予容器足够权限覆盖目录权限问题
案例 5:Web UI 终端无法使用 docker 命令(Shell 配置问题)
现象:通过 UNRAID 的 Web 界面进入容器控制台(Console),执行 docker 相关命令时提示 "command not found" 或权限不足,但进入宿主机的 SSH 终端执行 docker exec 进入同一容器后,命令却可以正常使用。
原因:CA 模板中使用了 <Shell>sh</Shell>。UNRAID Web 终端使用的 sh 可能缺少必要的环境变量(如 PATH 配置)或与 docker socket 的权限交互存在问题,而 bash 能正确加载完整的 shell 环境。
解决:
修改模板中的 Shell 定义:
<!-- 错误 -->
<Shell>sh</Shell>
<!-- 正确 -->
<Shell>bash</Shell>
验证:修改后,通过 UNRAID Web UI 的 Console 按钮进入容器,执行 docker ps 或 openclaw 命令应能正常响应。