mirror of
https://github.com/techartdev/OpenClawHomeAssistant.git
synced 2026-08-14 08:52:15 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9235903ef2 | ||
|
|
d5f3831131 | ||
|
|
b45e665bca | ||
|
|
0b799f5fb1 | ||
|
|
6129b62512 | ||
|
|
fe082864ec | ||
|
|
4d8fa8996a | ||
|
|
45d4066d2a | ||
|
|
28574b28ef | ||
|
|
089594a95b | ||
|
|
08bc68b9e7 | ||
|
|
3a06c4604f | ||
|
|
661085afc3 | ||
|
|
ccde8598d7 | ||
|
|
80f86ae030 | ||
|
|
082c2c74b2 | ||
|
|
d070dbe1e1 | ||
|
|
9824f7c138 | ||
|
|
71e3fbe410 | ||
|
|
c2398c84a4 | ||
|
|
3e5e0877b1 | ||
|
|
c769cb88e1 | ||
|
|
865ca08873 | ||
|
|
f0a465bf7c | ||
|
|
80ef635315 | ||
|
|
2acfc77a3f | ||
|
|
91a2ddd01f |
@@ -43,10 +43,10 @@ When you open the add-on page in Home Assistant, nginx serves a landing page wit
|
||||
| `/config/` | Yes | All user data — survives add-on updates and rebuilds |
|
||||
| `/config/.openclaw/` | Yes | OpenClaw configuration (`openclaw.json`), skills, agent data |
|
||||
| `/config/clawd/` | Yes | Agent workspace (ClawHub-installed skills, files) |
|
||||
| `/config/.node_global/` | Yes | User-installed npm packages (skills installed via dashboard) |
|
||||
| `/config/.node_global/` | Optional | User-installed npm packages when `persist_node_global=true` |
|
||||
| `/config/secrets/` | Yes | Tokens (e.g., `homeassistant.token`) |
|
||||
| `/config/keys/` | Yes | SSH keys (e.g., router SSH key) |
|
||||
| `/config/.linuxbrew/` | Yes | Homebrew install and brew-installed CLI tools |
|
||||
| `/config/.linuxbrew/` | Optional | Homebrew install and brew-installed CLI tools when `persist_brew_tools=true` |
|
||||
| `/config/gogcli/` | Yes | gog OAuth credentials for Google APIs |
|
||||
| `/usr/lib/node_modules/openclaw/` | No | OpenClaw installation (rebuilt with each image update) |
|
||||
|
||||
@@ -113,8 +113,9 @@ Save this token — you'll need it to access the Gateway Web UI and for API inte
|
||||
|
||||
1. In the terminal, confirm the gateway is running:
|
||||
```sh
|
||||
openclaw gateway status
|
||||
oc-gateway status
|
||||
```
|
||||
> In this add-on, the gateway is supervised by `run.sh` (not systemd), so `openclaw gateway status` can show misleading service-manager warnings.
|
||||
2. Click the **Open Gateway Web UI** button on the landing page
|
||||
3. If prompted for a token, paste the one from Step 2 or go to the Overview tab, paste the token in the 'Gateway Token' field and press Connect.
|
||||
|
||||
@@ -313,7 +314,10 @@ To provide the SSH key: place the private key file in the add-on config director
|
||||
| Option | Type | Default | Description |
|
||||
|---|---|---|---|
|
||||
| `clean_session_locks_on_start` | bool | `true` | Remove stale session lock files on startup (safe — only removes locks when gateway isn't running) |
|
||||
| `clean_session_locks_on_exit` | bool | `true` | Remove session lock files on clean shutdown || `auto_configure_mcp` | bool | `false` | Auto-register Home Assistant as an MCP server on startup (requires `homeassistant_token`) |
|
||||
| `clean_session_locks_on_exit` | bool | `true` | Remove session lock files on clean shutdown |
|
||||
| `persist_node_global` | bool | `false` | Persist user-installed npm global skills/packages in `/config/.node_global/`. Turn on only if you want those installs to survive add-on rebuilds. |
|
||||
| `persist_brew_tools` | bool | `false` | Persist Homebrew and brew-installed CLI tools in `/config/.linuxbrew/`. Turn on only if you want those installs to survive add-on rebuilds. |
|
||||
| `auto_configure_mcp` | bool | `false` | Auto-register Home Assistant as an MCP server on startup (requires `homeassistant_token`) |
|
||||
---
|
||||
|
||||
## 6. Use Case Guides
|
||||
@@ -647,10 +651,10 @@ You should see your account listed with the `sheets` service.
|
||||
| Built-in skills | `/config/.openclaw/skills/` | Yes |
|
||||
| Agent sessions & data | `/config/.openclaw/agents/` | Yes |
|
||||
| ClawHub workspace | `/config/clawd/` | Yes |
|
||||
| User-installed npm skills | `/config/.node_global/` | Yes |
|
||||
| User-installed npm skills | `/config/.node_global/` | Optional (`persist_node_global=true`) |
|
||||
| SSH keys | `/config/keys/` | Yes |
|
||||
| Tokens | `/config/secrets/` | Yes |
|
||||
| Homebrew & brew-installed tools | `/config/.linuxbrew/` | Yes (synced on startup) |
|
||||
| Homebrew & brew-installed tools | `/config/.linuxbrew/` | Optional (`persist_brew_tools=true`) |
|
||||
| gog OAuth credentials | `/config/gogcli/` | Yes |
|
||||
| TLS certificates (lan_https) | `/config/certs/` | Yes (CA persists; server cert regenerated if IP changes) |
|
||||
| OpenClaw binary | `/usr/lib/node_modules/openclaw/` | **No** — reinstalled from image |
|
||||
@@ -667,19 +671,21 @@ This means built-in skills survive image rebuilds, and any customizations you ma
|
||||
|
||||
### How user-installed skills work
|
||||
|
||||
When you install a skill via the OpenClaw dashboard or `npm install -g`, the add-on redirects global npm installs to `/config/.node_global/`. This directory persists across updates.
|
||||
By default, user-installed npm skills and global packages are **ephemeral** to keep Home Assistant backups small.
|
||||
|
||||
The add-on also configures `pnpm` global directory to persistent storage at `/config/.node_global/pnpm/`.
|
||||
If you enable `persist_node_global`, the add-on redirects global npm installs to `/config/.node_global/` so dashboard-installed skills survive add-on rebuilds. The add-on also configures the pnpm global directory at `/config/.node_global/pnpm/` in that mode.
|
||||
|
||||
### Homebrew-installed tools
|
||||
|
||||
Homebrew (Linuxbrew) and all brew-installed CLI tools (e.g., `gemini`, `aider`, `gh`, `bw`) are now **persisted** across add-on updates. On each startup, the add-on:
|
||||
By default, Homebrew (Linuxbrew) and brew-installed CLI tools are **ephemeral** to keep Home Assistant backups small.
|
||||
|
||||
If you enable `persist_brew_tools`, the add-on:
|
||||
|
||||
1. Syncs the image's Homebrew install to `/config/.linuxbrew/`
|
||||
2. Creates a symlink from `/home/linuxbrew/.linuxbrew/` to the persistent copy
|
||||
3. On subsequent boots, only newer files are synced (user-installed packages are preserved)
|
||||
|
||||
This means `brew install` packages survive image rebuilds.
|
||||
This means `brew install` packages survive image rebuilds only when persistence is enabled.
|
||||
|
||||
---
|
||||
|
||||
@@ -705,6 +711,7 @@ The add-on image includes these tools, available in the terminal:
|
||||
| Chromium | `chromium` | Headless browser for automation |
|
||||
| SSH | `ssh` | Remote access |
|
||||
| oc-cleanup | `oc-cleanup` | Interactive disk space monitor & cache cleanup helper |
|
||||
| oc-gateway | `oc-gateway status` / `oc-gateway restart` | Add-on-native gateway status/restart helper (`run.sh` supervised, no systemd) |
|
||||
|
||||
### oc-cleanup
|
||||
|
||||
@@ -740,7 +747,7 @@ Home Assistant checks for add-on updates automatically. When an update is availa
|
||||
**What happens during an update**:
|
||||
- The container is destroyed and recreated from the new image
|
||||
- Everything under `/config/` is preserved (config, skills, workspace, keys)
|
||||
- Homebrew and brew-installed packages are preserved (synced to `/config/.linuxbrew/`)
|
||||
- Homebrew and npm global packages are preserved only if you explicitly enable `persist_brew_tools` / `persist_node_global`
|
||||
- The OpenClaw binary is updated to the version in the new image
|
||||
|
||||
### Checking your version
|
||||
@@ -753,7 +760,20 @@ openclaw --version
|
||||
|
||||
### Backup
|
||||
|
||||
Home Assistant's built-in backup system automatically includes add-on configuration data (`/config/`). This covers all persistent data: OpenClaw config, skills, workspace, keys, and tokens.
|
||||
Home Assistant's built-in backup system automatically includes add-on configuration data (`/config/`). By default this covers the important user state: OpenClaw config, skills, workspace, keys, and tokens — without large optional toolchains.
|
||||
|
||||
### Backup-friendly defaults (v0.5.75+)
|
||||
|
||||
Starting with v0.5.75, the add-on keeps large optional toolchains out of backups by default:
|
||||
|
||||
- `persist_node_global: false` → `/config/.node_global/` is not used unless you opt in
|
||||
- `persist_brew_tools: false` → `/config/.linuxbrew/` is not used unless you opt in
|
||||
|
||||
Turn these on only if you specifically want user-installed npm global skills or brew-installed CLI tools to survive add-on rebuilds.
|
||||
|
||||
### Migration note for older installs
|
||||
|
||||
If you used an older add-on version, you may already have legacy directories such as `/config/.node_global/` or `/config/.linuxbrew/` from previous persistent behavior. Disabling persistence stops future growth, but those directories still count toward backup size until you remove or archive them manually.
|
||||
|
||||
**To create a backup**: Go to **Settings → System → Backups → Create Backup**
|
||||
|
||||
@@ -762,7 +782,8 @@ Home Assistant's built-in backup system automatically includes add-on configurat
|
||||
# Key paths to back up:
|
||||
# /config/.openclaw/ - OpenClaw config, skills, agent data
|
||||
# /config/clawd/ - ClawHub workspace
|
||||
# /config/.node_global/ - User-installed npm skills
|
||||
# /config/.node_global/ - User-installed npm skills (only if persist_node_global=true)
|
||||
# /config/.linuxbrew/ - Homebrew tools (only if persist_brew_tools=true)
|
||||
# /config/keys/ - SSH keys
|
||||
# /config/secrets/ - Tokens
|
||||
```
|
||||
@@ -772,12 +793,12 @@ Home Assistant's built-in backup system automatically includes add-on configurat
|
||||
To reset the add-on to a clean state, remove the persistent data:
|
||||
|
||||
```sh
|
||||
rm -rf /config/.openclaw /config/clawd /config/.node_global
|
||||
rm -rf /config/.openclaw /config/clawd /config/.node_global /config/.linuxbrew
|
||||
```
|
||||
|
||||
Then restart the add-on. It will re-bootstrap a fresh configuration.
|
||||
|
||||
> **Warning**: This deletes all your OpenClaw configuration, skills, and workspace data. Back up first if needed.
|
||||
> **Warning**: This deletes all your OpenClaw configuration, skills, workspace data, and any optionally persisted tool installations. Back up first if needed.
|
||||
|
||||
---
|
||||
|
||||
@@ -806,11 +827,23 @@ Go to **Settings → Add-ons → OpenClaw Assistant → Log** tab. Logs show sta
|
||||
**Symptom**: Browser shows connection refused when opening the Gateway Web UI.
|
||||
|
||||
**Checks**:
|
||||
1. Is the gateway running? In the terminal: `openclaw gateway status`
|
||||
1. Is the gateway running? In the terminal: `oc-gateway status`
|
||||
2. Is the bind mode correct? `openclaw config get gateway.bind` — must be `lan` for direct LAN access, or `loopback` if using `lan_https` mode
|
||||
3. Is the port correct? `openclaw config get gateway.port`
|
||||
4. Is the firewall blocking the port? Check your HA host firewall rules
|
||||
|
||||
### Gateway restart loop: `web_search provider is not available: brave`
|
||||
|
||||
**Symptom**: Logs repeat `Invalid config at /config/.openclaw/openclaw.json` and `tools.web.search.provider: web_search provider is not available: brave`.
|
||||
|
||||
**Cause**: The persisted OpenClaw config selects the Brave web search provider, but that provider plugin is not currently installed or enabled in the add-on runtime.
|
||||
|
||||
**Fix**: In v0.5.72+ the add-on clears that unavailable provider automatically during startup. On older versions, run this in the add-on terminal, then restart:
|
||||
|
||||
```sh
|
||||
jq 'del(.tools.web.search.provider)' /config/.openclaw/openclaw.json > /tmp/openclaw.json && mv /tmp/openclaw.json /config/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
### "disconnected (1008): control ui requires device identity" / "requires HTTPS or localhost"
|
||||
|
||||
**Symptom**: Gateway UI shows error 1008 or "requires secure context / device identity".
|
||||
@@ -860,7 +893,7 @@ Go to **Settings → Add-ons → OpenClaw Assistant → Log** tab. Logs show sta
|
||||
"allowedOrigins": ["https://YOUR_IP:18789"]
|
||||
}
|
||||
```
|
||||
Then restart the gateway: `openclaw gateway restart`
|
||||
Then restart only the gateway process: `oc-gateway restart`
|
||||
3. Alternatively, approve devices individually without disabling auth:
|
||||
```sh
|
||||
openclaw devices list # show pending pairing requests
|
||||
@@ -934,7 +967,7 @@ Built-in skills are synced to persistent storage on each startup. If skills are
|
||||
|
||||
1. Check logs for `INFO: Synced built-in skills to persistent storage` — this confirms the sync ran
|
||||
2. If you see `WARN: Built-in skills directory not found`, the OpenClaw installation may be corrupted. Try reinstalling the add-on.
|
||||
3. User-installed skills (via dashboard) are stored in `/config/.node_global/` and should survive updates
|
||||
3. User-installed skills (via dashboard) survive updates only when `persist_node_global` is enabled. With the default backup-friendly setting (`false`), they are ephemeral and may need to be reinstalled after an add-on rebuild.
|
||||
|
||||
### Homebrew errors / CPU compatibility
|
||||
|
||||
|
||||
@@ -2,6 +2,61 @@
|
||||
|
||||
All notable changes to the OpenClaw Assistant Home Assistant Add-on will be documented in this file.
|
||||
|
||||
## [0.5.75] - 2026-05-28
|
||||
|
||||
### Changed
|
||||
- **Backup-friendly persistence defaults**: new add-on options `persist_node_global` and `persist_brew_tools`, both defaulting to `false` so large optional toolchains are no longer persisted into Home Assistant backups unless users explicitly opt in.
|
||||
- `run.sh` now keeps npm global installs and Homebrew ephemeral by default, while preserving the old rebuild-survival behavior when the new toggles are enabled.
|
||||
|
||||
### Added
|
||||
- Migration notes and documentation for older installs that already have legacy `/config/.node_global/` or `/config/.linuxbrew/` directories contributing to backup size.
|
||||
|
||||
## [0.5.74] - 2026-05-27
|
||||
|
||||
### Fixed
|
||||
- Bundle `node-llama-cpp` inside the add-on image so the default local memory/embeddings provider works in HAOS without manual package installs.
|
||||
- Add `cmake` to the image so `node-llama-cpp` can fall back to a source build when a prebuilt binary is unavailable for the target architecture.
|
||||
|
||||
## [0.5.73] - 2026-05-26
|
||||
|
||||
### Added
|
||||
- New add-on-native `oc-gateway` helper for container-supervised runtime management:
|
||||
- `oc-gateway status` shows gateway state in the HA add-on model (`run.sh` supervisor, not systemd)
|
||||
- `oc-gateway restart` requests gateway self-restart via `SIGUSR1` without full add-on restart
|
||||
|
||||
### Changed
|
||||
- Troubleshooting and setup docs now use `oc-gateway status` / `oc-gateway restart` in add-on contexts to avoid confusing systemd-related CLI output.
|
||||
|
||||
## [0.5.72] - 2026-05-04
|
||||
|
||||
### Fixed
|
||||
- Repair startup when a persisted OpenClaw config still selects the unavailable `tools.web.search.provider=brave` provider. The add-on now clears that provider before launching the gateway so OpenClaw can start; users can reinstall/enable the Brave provider later if they want web search through Brave.
|
||||
|
||||
## [0.5.71] - 2026-05-03
|
||||
|
||||
### Changed
|
||||
- Bump OpenClaw through the 2026.4.29 and 2026.5.2 upstream releases.
|
||||
|
||||
## [0.5.70] - 2026-04-30
|
||||
|
||||
### Changed
|
||||
- Bump OpenClaw to 2026.4.27.
|
||||
|
||||
## [0.5.69] - 2026-04-27
|
||||
|
||||
### Changed
|
||||
- Bump OpenClaw through the 2026.4.23 and 2026.4.24 upstream releases.
|
||||
|
||||
## [0.5.68] - 2026-04-25
|
||||
|
||||
### Changed
|
||||
- Bump OpenClaw through the 2026.4.14, 2026.4.15, 2026.4.21, and 2026.4.22 upstream releases.
|
||||
|
||||
## [0.5.67] - 2026-04-25
|
||||
|
||||
### Changed
|
||||
- Bump OpenClaw through the 2026.4.5, 2026.4.8, 2026.4.9, 2026.4.10, 2026.4.11, and 2026.4.12 upstream releases.
|
||||
|
||||
## [0.5.66] - 2026-04-04
|
||||
|
||||
### Fixed
|
||||
@@ -22,6 +77,11 @@ All notable changes to the OpenClaw Assistant Home Assistant Add-on will be docu
|
||||
### Fixed
|
||||
- **Gateway restart loop** (issue #95): `openclaw gateway run` is a thin wrapper that spawns `openclaw-gateway` as a long-running daemon then exits immediately. On self-restart (SIGUSR1 / `openclaw gateway restart`), the old daemon forks a new one and exits — the new PID is not a child of run.sh. The supervisor now uses a 3-tier daemon detection function (`find_gateway_daemon_pid`): (1) port ownership via `ss -tlnp`, (2) process title via `pgrep -f "openclaw-gateway"`, (3) `/proc/*/cmdline` scan for "openclaw" (catches the daemon immediately after fork, even before process.title or port bind — critical on Pi/eMMC where initialization takes 20-30 s). Detection retries up to 10 times with a final port-occupancy guard before any supervisor-initiated restart. Non-child PIDs are monitored with `kill -0` polling instead of `wait`. The loopback relay (tailnet mode) is stopped/restarted around gateway restarts to prevent port conflicts.
|
||||
|
||||
## [0.5.61] - 2026-03-10
|
||||
|
||||
### Fixed
|
||||
- **Gateway restart loop** (issue #95): stop the tailnet loopback relay before supervisor-initiated gateway restarts and start it again after the new daemon is launched, preventing the relay from holding the local port and trapping the add-on in an `already listening` restart loop.
|
||||
|
||||
## [0.5.60] - 2026-03-10
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -18,6 +18,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
xz-utils \
|
||||
file \
|
||||
python3 \
|
||||
cmake \
|
||||
nginx \
|
||||
gnupg \
|
||||
build-essential \
|
||||
@@ -113,8 +114,10 @@ RUN if [ -x /home/linuxbrew/.linuxbrew/bin/brew ]; then \
|
||||
USER root
|
||||
|
||||
# Install OpenClaw globally
|
||||
# Bundle node-llama-cpp in the image so the default local memory/embeddings
|
||||
# provider works in HAOS without requiring manual npm installs in /usr/lib.
|
||||
RUN npm config set fund false && npm config set audit false \
|
||||
&& npm install -g openclaw@2026.4.24
|
||||
&& npm install -g openclaw@2026.7.1 node-llama-cpp@3.18.1
|
||||
|
||||
# Shell aliases and color options for interactive use
|
||||
RUN tee -a /etc/bash.bashrc <<'EOF'
|
||||
@@ -138,10 +141,11 @@ COPY run.sh /run.sh
|
||||
COPY oc_config_helper.py /oc_config_helper.py
|
||||
COPY render_nginx.py /render_nginx.py
|
||||
COPY oc-cleanup.sh /usr/local/bin/oc-cleanup
|
||||
COPY oc-gateway /usr/local/bin/oc-gateway
|
||||
COPY openclaw-proxy-shim.cjs /usr/local/lib/openclaw-proxy-shim.cjs
|
||||
COPY nginx.conf.tpl /etc/nginx/nginx.conf.tpl
|
||||
COPY landing.html.tpl /etc/nginx/landing.html.tpl
|
||||
RUN chmod +x /run.sh /oc_config_helper.py /render_nginx.py /usr/local/bin/oc-cleanup \
|
||||
RUN chmod +x /run.sh /oc_config_helper.py /render_nginx.py /usr/local/bin/oc-cleanup /usr/local/bin/oc-gateway \
|
||||
&& mkdir -p /run/nginx
|
||||
|
||||
CMD [ "/run.sh" ]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: OpenClaw Assistant
|
||||
version: "0.5.69"
|
||||
version: "0.5.81"
|
||||
slug: openclaw_assistant
|
||||
description: Run OpenClaw Assistant (OpenClaw-compatible) as a Home Assistant add-on.
|
||||
url: https://github.com/techartdev/OpenClawHomeAssistant
|
||||
@@ -56,6 +56,11 @@ options:
|
||||
clean_session_locks_on_start: true
|
||||
clean_session_locks_on_exit: true
|
||||
|
||||
# Persist heavy optional tooling across add-on rebuilds.
|
||||
# Disabled by default to keep Home Assistant backups small.
|
||||
persist_node_global: false
|
||||
persist_brew_tools: false
|
||||
|
||||
# Gateway mode:
|
||||
# - local: Run gateway locally (recommended for most users)
|
||||
# - remote: Connect to a remote gateway
|
||||
@@ -153,6 +158,8 @@ schema:
|
||||
|
||||
clean_session_locks_on_start: bool?
|
||||
clean_session_locks_on_exit: bool?
|
||||
persist_node_global: bool?
|
||||
persist_brew_tools: bool?
|
||||
gateway_mode: list(local|remote)?
|
||||
gateway_remote_url: str?
|
||||
gateway_bind_mode: list(loopback|lan|tailnet)?
|
||||
|
||||
Executable
+133
@@ -0,0 +1,133 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cmd="${1:-status}"
|
||||
shift || true
|
||||
|
||||
find_gateway_pid() {
|
||||
local port="${1:-18789}"
|
||||
local pid=""
|
||||
|
||||
# 1) Port owner (most accurate)
|
||||
if command -v ss >/dev/null 2>&1; then
|
||||
pid=$(ss -tlnp 2>/dev/null \
|
||||
| grep ":${port} " \
|
||||
| sed -n 's/.*pid=\([0-9]*\).*/\1/p' \
|
||||
| head -1 || true)
|
||||
if [ -n "$pid" ] && [ -r "/proc/$pid/cmdline" ]; then
|
||||
local cmdline
|
||||
cmdline=$(tr '\0' ' ' < "/proc/$pid/cmdline" 2>/dev/null || true)
|
||||
if echo "$cmdline" | grep -qi "openclaw\|node"; then
|
||||
echo "$pid"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# 2) Process title
|
||||
pid=$(pgrep -f "openclaw-gateway" 2>/dev/null | head -1 || true)
|
||||
if [ -n "$pid" ]; then
|
||||
echo "$pid"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 3) /proc cmdline fallback
|
||||
for f in /proc/[0-9]*/cmdline; do
|
||||
[ -r "$f" ] || continue
|
||||
if tr '\0' ' ' < "$f" 2>/dev/null | grep -qi "openclaw"; then
|
||||
echo "${f#/proc/}" | cut -d/ -f1
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
get_gateway_port() {
|
||||
python3 - <<'PY'
|
||||
import json, os
|
||||
p = os.environ.get('OPENCLAW_CONFIG_PATH', '/config/.openclaw/openclaw.json')
|
||||
try:
|
||||
with open(p, 'r', encoding='utf-8') as f:
|
||||
cfg = json.load(f)
|
||||
print(int(cfg.get('gateway', {}).get('port', 18789)))
|
||||
except Exception:
|
||||
print(18789)
|
||||
PY
|
||||
}
|
||||
|
||||
status_cmd() {
|
||||
local port pid
|
||||
port="$(get_gateway_port)"
|
||||
pid="$(find_gateway_pid "$port" || true)"
|
||||
|
||||
echo "OpenClaw add-on gateway status"
|
||||
echo "Supervisor: run.sh (not systemd)"
|
||||
echo "Configured port: ${port}"
|
||||
|
||||
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
|
||||
echo "Gateway process: running (PID ${pid})"
|
||||
if command -v ss >/dev/null 2>&1 && ss -tlnp 2>/dev/null | grep -q ":${port} "; then
|
||||
echo "Listener: active on :${port}"
|
||||
else
|
||||
echo "Listener: process found, port bind not detected yet"
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Gateway process: not detected"
|
||||
echo "Tip: Check add-on logs in Home Assistant for startup errors."
|
||||
exit 1
|
||||
}
|
||||
|
||||
restart_cmd() {
|
||||
local port pid
|
||||
port="$(get_gateway_port)"
|
||||
pid="$(find_gateway_pid "$port" || true)"
|
||||
|
||||
if [ -z "$pid" ] || ! kill -0 "$pid" 2>/dev/null; then
|
||||
echo "No running gateway process found to restart."
|
||||
echo "Tip: If startup failed, inspect add-on logs."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Requesting gateway self-restart via SIGUSR1 (PID ${pid})..."
|
||||
kill -USR1 "$pid"
|
||||
|
||||
for _ in $(seq 1 20); do
|
||||
sleep 1
|
||||
local new_pid
|
||||
new_pid="$(find_gateway_pid "$port" || true)"
|
||||
if [ -n "$new_pid" ] && kill -0 "$new_pid" 2>/dev/null; then
|
||||
echo "Gateway active (PID ${new_pid})"
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Restart signal sent; gateway may still be reinitializing."
|
||||
echo "Run 'oc-gateway status' again in a few seconds."
|
||||
exit 0
|
||||
}
|
||||
|
||||
case "$cmd" in
|
||||
status)
|
||||
status_cmd
|
||||
;;
|
||||
restart|reload)
|
||||
restart_cmd
|
||||
;;
|
||||
help|-h|--help)
|
||||
cat <<'EOF'
|
||||
Usage: oc-gateway <status|restart|reload>
|
||||
|
||||
status Show add-on-native gateway status (run.sh-supervised)
|
||||
restart Request gateway self-restart via SIGUSR1
|
||||
reload Alias of restart
|
||||
EOF
|
||||
;;
|
||||
*)
|
||||
echo "Unknown command: $cmd" >&2
|
||||
echo "Run: oc-gateway help" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
@@ -256,6 +256,43 @@ def set_control_ui_origins(origins_csv: str, additional_origins_csv: str = "", d
|
||||
return False
|
||||
|
||||
|
||||
def repair_known_invalid_settings():
|
||||
"""Repair known config values that prevent OpenClaw from starting."""
|
||||
cfg = read_config()
|
||||
if cfg is None:
|
||||
return True
|
||||
|
||||
tools = cfg.get("tools")
|
||||
if not isinstance(tools, dict):
|
||||
return True
|
||||
|
||||
web = tools.get("web")
|
||||
if not isinstance(web, dict):
|
||||
return True
|
||||
|
||||
search = web.get("search")
|
||||
if not isinstance(search, dict):
|
||||
return True
|
||||
|
||||
provider = search.get("provider")
|
||||
changes = []
|
||||
|
||||
if provider == "brave":
|
||||
del search["provider"]
|
||||
changes.append("removed unavailable tools.web.search.provider=brave")
|
||||
|
||||
if not changes:
|
||||
print("INFO: No known invalid OpenClaw config settings found")
|
||||
return True
|
||||
|
||||
if write_config(cfg):
|
||||
print(f"INFO: Repaired OpenClaw config: {', '.join(changes)}")
|
||||
return True
|
||||
|
||||
print("ERROR: Failed to write config")
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
"""CLI entry point for use by run.sh"""
|
||||
if len(sys.argv) < 2:
|
||||
@@ -300,6 +337,13 @@ def main():
|
||||
success = set_control_ui_origins(origins_csv, additional_origins_csv, disable_device_auth)
|
||||
sys.exit(0 if success else 1)
|
||||
|
||||
elif cmd == "repair-known-invalid-settings":
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: oc_config_helper.py repair-known-invalid-settings")
|
||||
sys.exit(1)
|
||||
success = repair_known_invalid_settings()
|
||||
sys.exit(0 if success else 1)
|
||||
|
||||
elif cmd == "set":
|
||||
if len(sys.argv) != 4:
|
||||
print("Usage: oc_config_helper.py set <key> <value>")
|
||||
|
||||
+79
-39
@@ -44,6 +44,8 @@ ROUTER_KEY=$(jq -r '.router_ssh_key_path // "/data/keys/router_ssh"' "$OPTIONS_F
|
||||
# Optional: allow disabling lock cleanup if you ever need to debug
|
||||
CLEAN_LOCKS_ON_START=$(jq -r '.clean_session_locks_on_start // true' "$OPTIONS_FILE")
|
||||
CLEAN_LOCKS_ON_EXIT=$(jq -r '.clean_session_locks_on_exit // true' "$OPTIONS_FILE")
|
||||
PERSIST_NODE_GLOBAL=$(jq -r '.persist_node_global // false' "$OPTIONS_FILE")
|
||||
PERSIST_BREW_TOOLS=$(jq -r '.persist_brew_tools // false' "$OPTIONS_FILE")
|
||||
|
||||
# Gateway configuration
|
||||
GATEWAY_MODE=$(jq -r '.gateway_mode // "local"' "$OPTIONS_FILE")
|
||||
@@ -149,6 +151,15 @@ export XDG_CONFIG_HOME=/config
|
||||
|
||||
mkdir -p /config/.openclaw /config/.openclaw/identity /config/clawd /config/keys /config/secrets
|
||||
|
||||
warn_legacy_persistent_dir() {
|
||||
local path="$1"
|
||||
local label="$2"
|
||||
if [ -e "$path" ]; then
|
||||
echo "WARN: Found legacy persistent ${label} at ${path}, but persistence is disabled."
|
||||
echo "WARN: It will still inflate Home Assistant backups until you remove or archive it manually."
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Sync built-in OpenClaw skills from image to persistent storage
|
||||
# On each startup, copy new/updated built-in skills so they survive rebuilds.
|
||||
@@ -180,21 +191,33 @@ else
|
||||
fi
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Persist user-installed node skills across Docker image rebuilds
|
||||
# Redirect npm/pnpm global installs to /config/.node_global (persistent storage)
|
||||
# so that skills installed via the dashboard survive container rebuilds.
|
||||
# Optional persistence for user-installed node skills across Docker image rebuilds.
|
||||
# When enabled, redirect npm/pnpm global installs to /config/.node_global so
|
||||
# dashboard-installed skills survive image updates. Disabled by default to keep
|
||||
# Home Assistant backups smaller.
|
||||
# NOTE: This MUST come after the skills sync above (which needs the original npm root -g).
|
||||
# ------------------------------------------------------------------------------
|
||||
PERSISTENT_NODE_GLOBAL="/config/.node_global"
|
||||
mkdir -p "$PERSISTENT_NODE_GLOBAL"
|
||||
npm config set prefix "$PERSISTENT_NODE_GLOBAL" 2>/dev/null || true
|
||||
export PATH="${PERSISTENT_NODE_GLOBAL}/bin:${PATH}"
|
||||
export NODE_PATH="${PERSISTENT_NODE_GLOBAL}/lib/node_modules:${NODE_PATH:-}"
|
||||
if [ "$PERSIST_NODE_GLOBAL" = "true" ] || [ "$PERSIST_NODE_GLOBAL" = "1" ]; then
|
||||
mkdir -p "$PERSISTENT_NODE_GLOBAL"
|
||||
npm config set prefix "$PERSISTENT_NODE_GLOBAL" 2>/dev/null || true
|
||||
export PATH="${PERSISTENT_NODE_GLOBAL}/bin:${PATH}"
|
||||
export NODE_PATH="${PERSISTENT_NODE_GLOBAL}/lib/node_modules:${NODE_PATH:-}"
|
||||
|
||||
# Also configure pnpm global dir to persistent storage
|
||||
export PNPM_HOME="${PERSISTENT_NODE_GLOBAL}/pnpm"
|
||||
mkdir -p "$PNPM_HOME"
|
||||
export PATH="${PNPM_HOME}:${PATH}"
|
||||
# Also configure pnpm global dir to persistent storage
|
||||
export PNPM_HOME="${PERSISTENT_NODE_GLOBAL}/pnpm"
|
||||
mkdir -p "$PNPM_HOME"
|
||||
export PATH="${PNPM_HOME}:${PATH}"
|
||||
echo "INFO: persist_node_global=true; user-installed npm skills will survive add-on rebuilds."
|
||||
else
|
||||
npm config delete prefix 2>/dev/null || true
|
||||
export npm_config_prefix="/usr/local"
|
||||
export PNPM_HOME="/tmp/.pnpm-home"
|
||||
mkdir -p "$PNPM_HOME"
|
||||
export PATH="${PNPM_HOME}:${PATH}"
|
||||
warn_legacy_persistent_dir "$PERSISTENT_NODE_GLOBAL" "node global tool/skill data"
|
||||
echo "INFO: persist_node_global=false; npm/pnpm global installs are ephemeral and excluded from HA backups."
|
||||
fi
|
||||
|
||||
# Protect critical runtime variables from accidental override via gateway_env_vars.
|
||||
is_reserved_gateway_env_var() {
|
||||
@@ -331,42 +354,48 @@ elif [ "$GW_ENV_VARS_TYPE" != "null" ]; then
|
||||
fi
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Persist Linuxbrew/Homebrew across Docker image rebuilds
|
||||
# Homebrew installs to /home/linuxbrew/.linuxbrew/ which is ephemeral.
|
||||
# We sync it to /config/.linuxbrew and symlink back so brew-installed CLI
|
||||
# tools (gog, gh, bw, etc.) survive add-on updates.
|
||||
# Optional persistence for Linuxbrew/Homebrew across Docker image rebuilds.
|
||||
# When enabled, sync /home/linuxbrew/.linuxbrew to /config/.linuxbrew so
|
||||
# brew-installed CLI tools survive image updates. Disabled by default to keep
|
||||
# Home Assistant backups smaller.
|
||||
# ------------------------------------------------------------------------------
|
||||
IMAGE_BREW_DIR="/home/linuxbrew/.linuxbrew"
|
||||
PERSISTENT_BREW_DIR="/config/.linuxbrew"
|
||||
|
||||
if [ -d "$IMAGE_BREW_DIR" ] && [ ! -L "$IMAGE_BREW_DIR" ]; then
|
||||
# Image has a real Homebrew install — sync to persistent storage
|
||||
if [ -d "$PERSISTENT_BREW_DIR" ]; then
|
||||
# Persistent copy exists: sync new/updated files from image (upgrades),
|
||||
# but preserve user-installed packages already in persistent storage.
|
||||
if command -v rsync >/dev/null 2>&1; then
|
||||
rsync -a --update "$IMAGE_BREW_DIR/" "$PERSISTENT_BREW_DIR/" 2>/dev/null || true
|
||||
if [ "$PERSIST_BREW_TOOLS" = "true" ] || [ "$PERSIST_BREW_TOOLS" = "1" ]; then
|
||||
if [ -d "$IMAGE_BREW_DIR" ] && [ ! -L "$IMAGE_BREW_DIR" ]; then
|
||||
# Image has a real Homebrew install — sync to persistent storage
|
||||
if [ -d "$PERSISTENT_BREW_DIR" ]; then
|
||||
# Persistent copy exists: sync new/updated files from image (upgrades),
|
||||
# but preserve user-installed packages already in persistent storage.
|
||||
if command -v rsync >/dev/null 2>&1; then
|
||||
rsync -a --update "$IMAGE_BREW_DIR/" "$PERSISTENT_BREW_DIR/" 2>/dev/null || true
|
||||
else
|
||||
cp -ru "$IMAGE_BREW_DIR/"* "$PERSISTENT_BREW_DIR/" 2>/dev/null || true
|
||||
fi
|
||||
echo "INFO: Synced Homebrew updates to persistent storage"
|
||||
else
|
||||
cp -ru "$IMAGE_BREW_DIR/"* "$PERSISTENT_BREW_DIR/" 2>/dev/null || true
|
||||
# First time: copy entire Homebrew install to persistent storage
|
||||
cp -a "$IMAGE_BREW_DIR" "$PERSISTENT_BREW_DIR" 2>/dev/null || true
|
||||
echo "INFO: Copied Homebrew to persistent storage at $PERSISTENT_BREW_DIR"
|
||||
fi
|
||||
echo "INFO: Synced Homebrew updates to persistent storage"
|
||||
# Replace image dir with symlink to persistent copy
|
||||
rm -rf "$IMAGE_BREW_DIR"
|
||||
ln -sf "$PERSISTENT_BREW_DIR" "$IMAGE_BREW_DIR"
|
||||
elif [ -L "$IMAGE_BREW_DIR" ]; then
|
||||
echo "INFO: Homebrew already linked to persistent storage"
|
||||
elif [ -d "$PERSISTENT_BREW_DIR" ]; then
|
||||
# Image doesn't have Homebrew (failed install?) but persistent copy exists
|
||||
mkdir -p "$(dirname "$IMAGE_BREW_DIR")"
|
||||
ln -sf "$PERSISTENT_BREW_DIR" "$IMAGE_BREW_DIR"
|
||||
echo "INFO: Restored Homebrew symlink from persistent storage"
|
||||
else
|
||||
# First time: copy entire Homebrew install to persistent storage
|
||||
cp -a "$IMAGE_BREW_DIR" "$PERSISTENT_BREW_DIR" 2>/dev/null || true
|
||||
echo "INFO: Copied Homebrew to persistent storage at $PERSISTENT_BREW_DIR"
|
||||
echo "INFO: Homebrew not available (install may have failed during image build)"
|
||||
fi
|
||||
# Replace image dir with symlink to persistent copy
|
||||
rm -rf "$IMAGE_BREW_DIR"
|
||||
ln -sf "$PERSISTENT_BREW_DIR" "$IMAGE_BREW_DIR"
|
||||
elif [ -L "$IMAGE_BREW_DIR" ]; then
|
||||
echo "INFO: Homebrew already linked to persistent storage"
|
||||
elif [ -d "$PERSISTENT_BREW_DIR" ]; then
|
||||
# Image doesn't have Homebrew (failed install?) but persistent copy exists
|
||||
mkdir -p "$(dirname "$IMAGE_BREW_DIR")"
|
||||
ln -sf "$PERSISTENT_BREW_DIR" "$IMAGE_BREW_DIR"
|
||||
echo "INFO: Restored Homebrew symlink from persistent storage"
|
||||
echo "INFO: persist_brew_tools=true; brew-installed tools will survive add-on rebuilds."
|
||||
else
|
||||
echo "INFO: Homebrew not available (install may have failed during image build)"
|
||||
warn_legacy_persistent_dir "$PERSISTENT_BREW_DIR" "Homebrew data"
|
||||
echo "INFO: persist_brew_tools=false; Homebrew installs stay ephemeral and excluded from HA backups."
|
||||
fi
|
||||
|
||||
# Back-compat: some docs/scripts assume /data; point it at /config.
|
||||
@@ -562,9 +591,20 @@ fi
|
||||
|
||||
if [ -f "$OPENCLAW_CONFIG_PATH" ]; then
|
||||
if [ -f "$HELPER_PATH" ]; then
|
||||
if python3 "$HELPER_PATH" repair-known-invalid-settings; then
|
||||
:
|
||||
else
|
||||
rc=$?
|
||||
echo "ERROR: Failed to repair known invalid OpenClaw config settings via oc_config_helper.py (exit code ${rc})."
|
||||
echo "ERROR: Gateway configuration may be invalid; aborting startup."
|
||||
exit "${rc}"
|
||||
fi
|
||||
|
||||
# In lan_https mode the gateway uses an internal port; nginx owns the external one.
|
||||
EFFECTIVE_GW_PORT="$GATEWAY_INTERNAL_PORT"
|
||||
if ! python3 "$HELPER_PATH" apply-gateway-settings "$GATEWAY_MODE" "$GATEWAY_REMOTE_URL" "$GATEWAY_BIND_MODE" "$EFFECTIVE_GW_PORT" "$ENABLE_OPENAI_API" "$GATEWAY_AUTH_MODE" "$GATEWAY_TRUSTED_PROXIES"; then
|
||||
if python3 "$HELPER_PATH" apply-gateway-settings "$GATEWAY_MODE" "$GATEWAY_REMOTE_URL" "$GATEWAY_BIND_MODE" "$EFFECTIVE_GW_PORT" "$ENABLE_OPENAI_API" "$GATEWAY_AUTH_MODE" "$GATEWAY_TRUSTED_PROXIES"; then
|
||||
:
|
||||
else
|
||||
rc=$?
|
||||
echo "ERROR: Failed to apply gateway settings via oc_config_helper.py (exit code ${rc})."
|
||||
echo "ERROR: Gateway configuration may be incorrect; aborting startup."
|
||||
|
||||
@@ -42,6 +42,14 @@ configuration:
|
||||
clean_session_locks_on_exit:
|
||||
name: Изчистване на заключвания при изход
|
||||
description: Изчистване на заключващи файлове на сесии при нормално спиране на добавката
|
||||
|
||||
persist_node_global:
|
||||
name: Запазване на npm глобални умения
|
||||
description: Когато е ВКЛ., съхранява инсталираните от потребителя npm умения и глобални пакети в /config/.node_global, за да оцелеят при преизграждане на добавката. По подразбиране е ИЗКЛ. за по-малки HA архиви.
|
||||
|
||||
persist_brew_tools:
|
||||
name: Запазване на Homebrew инструменти
|
||||
description: Когато е ВКЛ., съхранява Homebrew и инсталираните с brew CLI инструменти в /config/.linuxbrew, за да оцелеят при преизграждане на добавката. По подразбиране е ИЗКЛ. за по-малки HA архиви.
|
||||
|
||||
gateway_mode:
|
||||
name: Режим на Gateway
|
||||
|
||||
@@ -42,6 +42,14 @@ configuration:
|
||||
clean_session_locks_on_exit:
|
||||
name: Sitzungssperren beim Beenden bereinigen
|
||||
description: Sitzungssperrdateien beim ordnungsgemäßen Stoppen des Add-ons bereinigen
|
||||
|
||||
persist_node_global:
|
||||
name: npm-Globale Skills dauerhaft speichern
|
||||
description: Wenn EIN, werden benutzerinstallierte npm-Skills und globale Pakete unter /config/.node_global gespeichert und über Add-on-Neubuilds hinweg behalten. Standard ist AUS, um Home-Assistant-Backups klein zu halten.
|
||||
|
||||
persist_brew_tools:
|
||||
name: Homebrew-Tools dauerhaft speichern
|
||||
description: Wenn EIN, werden Homebrew und per brew installierte CLI-Tools unter /config/.linuxbrew gespeichert und über Add-on-Neubuilds hinweg behalten. Standard ist AUS, um Home-Assistant-Backups klein zu halten.
|
||||
|
||||
gateway_mode:
|
||||
name: Gateway-Modus
|
||||
|
||||
@@ -42,6 +42,14 @@ configuration:
|
||||
clean_session_locks_on_exit:
|
||||
name: Clean Session Locks on Exit
|
||||
description: Cleanup session lock files when add-on stops gracefully
|
||||
|
||||
persist_node_global:
|
||||
name: Persist npm Global Skills
|
||||
description: When ON, store user-installed npm skills and global packages under /config/.node_global so they survive add-on rebuilds. Default OFF to keep Home Assistant backups smaller.
|
||||
|
||||
persist_brew_tools:
|
||||
name: Persist Homebrew Tools
|
||||
description: When ON, store Homebrew and brew-installed CLI tools under /config/.linuxbrew so they survive add-on rebuilds. Default OFF to keep Home Assistant backups smaller.
|
||||
|
||||
gateway_mode:
|
||||
name: Gateway Mode
|
||||
|
||||
@@ -42,6 +42,14 @@ configuration:
|
||||
clean_session_locks_on_exit:
|
||||
name: Limpiar bloqueos de sesión al salir
|
||||
description: Limpiar archivos de bloqueo de sesión cuando el complemento se detiene correctamente
|
||||
|
||||
persist_node_global:
|
||||
name: Conservar habilidades globales de npm
|
||||
description: Cuando está activado, guarda las habilidades npm instaladas por el usuario y los paquetes globales en /config/.node_global para que sobrevivan a reconstrucciones del complemento. Por defecto está desactivado para mantener pequeñas las copias de seguridad de Home Assistant.
|
||||
|
||||
persist_brew_tools:
|
||||
name: Conservar herramientas de Homebrew
|
||||
description: Cuando está activado, guarda Homebrew y las herramientas CLI instaladas con brew en /config/.linuxbrew para que sobrevivan a reconstrucciones del complemento. Por defecto está desactivado para mantener pequeñas las copias de seguridad de Home Assistant.
|
||||
|
||||
gateway_mode:
|
||||
name: Modo del Gateway
|
||||
|
||||
@@ -42,6 +42,14 @@ configuration:
|
||||
clean_session_locks_on_exit:
|
||||
name: Wyczyść blokady sesji przy wyjściu
|
||||
description: Usuń pliki blokad sesji gdy dodatek zatrzymuje się poprawnie
|
||||
|
||||
persist_node_global:
|
||||
name: Zachowuj globalne umiejętności npm
|
||||
description: Po włączeniu zapisuje umiejętności npm instalowane przez użytkownika i pakiety globalne w /config/.node_global, aby przetrwały przebudowę dodatku. Domyślnie wyłączone, aby kopie zapasowe Home Assistant były mniejsze.
|
||||
|
||||
persist_brew_tools:
|
||||
name: Zachowuj narzędzia Homebrew
|
||||
description: Po włączeniu zapisuje Homebrew i narzędzia CLI instalowane przez brew w /config/.linuxbrew, aby przetrwały przebudowę dodatku. Domyślnie wyłączone, aby kopie zapasowe Home Assistant były mniejsze.
|
||||
|
||||
gateway_remote_url:
|
||||
name: URL zdalnego Gateway
|
||||
|
||||
@@ -42,6 +42,14 @@ configuration:
|
||||
clean_session_locks_on_exit:
|
||||
name: Limpar Bloqueios de Sessão ao Sair
|
||||
description: Limpar arquivos de bloqueio de sessão quando o add-on parar normalmente
|
||||
|
||||
persist_node_global:
|
||||
name: Persistir skills globais do npm
|
||||
description: Quando ativado, armazena skills npm instaladas pelo usuário e pacotes globais em /config/.node_global para sobreviverem a reconstruções do add-on. O padrão é desativado para manter menores os backups do Home Assistant.
|
||||
|
||||
persist_brew_tools:
|
||||
name: Persistir ferramentas do Homebrew
|
||||
description: Quando ativado, armazena o Homebrew e ferramentas CLI instaladas via brew em /config/.linuxbrew para sobreviverem a reconstruções do add-on. O padrão é desativado para manter menores os backups do Home Assistant.
|
||||
|
||||
gateway_mode:
|
||||
name: Modo do Gateway
|
||||
|
||||
Reference in New Issue
Block a user