Skip to content

Commit 11d8ecb

Browse files
author
root
committed
feat(gateway): add IP:port configuration and helper script
- Bump version to 0.5.35 - Add gateway_bind_ip and gateway_port options - Create oc_config_helper.py for safe config management - Update DOCS.md with new LAN mode configuration options - Support prepopulation from existing config
1 parent a7d66c3 commit 11d8ecb

4 files changed

Lines changed: 212 additions & 40 deletions

File tree

DOCS.md

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,22 @@ You have two common setups:
6565
If your Home Assistant is already exposed via HTTPS (Nabu Casa, reverse proxy, etc.), use that.
6666
This avoids browser security issues.
6767

68-
#### Option 2: LAN access (http://192.168.x.x)
69-
If you want to open it directly on your LAN, you must ensure OpenClaw binds to LAN.
70-
In the terminal:
68+
#### Option 2: LAN access (http://192.168.x.x) — using add-on options (recommended)
69+
The easiest way to enable LAN access is via the add-on configuration:
70+
71+
1. Go to Home Assistant → **Settings → Add-ons → OpenClaw Assistant → Configuration**
72+
2. Set the following options:
73+
- `gateway_lan_mode`: **true** (enables LAN binding)
74+
- `gateway_bind_ip`: **"0.0.0.0"** (binds to all interfaces) or a specific IP like **"192.168.1.10"**
75+
- `gateway_port`: **18789** (or your preferred port)
76+
3. Restart the add-on
77+
78+
The add-on will automatically update OpenClaw's configuration on startup.
79+
80+
**Pre-population**: If you previously configured OpenClaw manually, the add-on will detect and respect those settings. You can still override them via the add-on options.
81+
82+
#### Option 3: LAN access — manual configuration (advanced)
83+
If you prefer to configure manually via terminal:
7184

7285
```sh
7386
openclaw config set gateway.bind lan
@@ -132,10 +145,25 @@ This allows using the Control UI over LAN HTTP.
132145

133146
## 5) Add-on options (custom / HA-specific)
134147

135-
This add-on intentionally keeps options minimal. See `openclaw_assistant_dev/config.yaml` (DEV repo).
148+
This add-on keeps options minimal but practical. See `openclaw_assistant_dev/config.yaml` for the full schema.
149+
150+
### Gateway LAN Mode (NEW)
151+
Control how the OpenClaw gateway binds to the network:
152+
153+
- **`gateway_lan_mode`** (bool, default **false**)
154+
- **false**: Bind to loopback only (127.0.0.1) — secure, local access only
155+
- **true**: Bind to LAN — accessible from your local network
156+
157+
When `gateway_lan_mode` is **true**:
158+
- **`gateway_bind_ip`** (string, default **"0.0.0.0"**)
159+
- IP address to bind to. Use `"0.0.0.0"` for all interfaces, or a specific IP like `"192.168.1.10"`
160+
- **`gateway_port`** (int, default **18789**)
161+
- Port number for the gateway to listen on
162+
163+
These settings are applied automatically on add-on startup. No need to run `openclaw config` commands.
136164

137165
### Terminal
138-
- `enable_terminal` (default **true**)
166+
- `enable_terminal` (bool, default **true**)
139167

140168
Security note: the terminal gives shell access inside the add-on container.
141169

@@ -155,6 +183,10 @@ How to provide the key:
155183
- Put the private key file under the add-on config directory so it appears in-container at `/data/keys/...`
156184
- Recommended permissions: `chmod 600`
157185

186+
### Session cleanup
187+
- `clean_session_locks_on_start` (bool, default **true**) — Remove stale lock files on startup
188+
- `clean_session_locks_on_exit` (bool, default **true**) — Remove stale lock files on shutdown
189+
158190
---
159191

160192
## Troubleshooting

openclaw_assistant_dev/config.yaml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: OpenClaw Assistant (DEV)
2-
version: "0.5.34"
2+
version: "0.5.35"
33
slug: openclaw_assistant_dev
44
description: Run OpenClaw Assistant (OpenClaw-compatible) as a Home Assistant add-on.
55
url: https://github.com/techartdev/OpenClawHomeAssistant
@@ -48,11 +48,17 @@ options:
4848
clean_session_locks_on_exit: true
4949

5050
# Gateway network bind mode:
51-
# - true: bind to LAN (accessible from local network, e.g., 0.0.0.0 or LAN IP)
51+
# - true: bind to LAN (accessible from local network)
5252
# - false: bind to loopback only (127.0.0.1, local access only)
5353
# Default is false for security. Toggle this on if you need external access.
5454
gateway_lan_mode: false
5555

56+
# Gateway bind configuration (used when gateway_lan_mode is true)
57+
# IP address to bind to. Use "0.0.0.0" for all interfaces, or specific IP like "192.168.1.10"
58+
gateway_bind_ip: "0.0.0.0"
59+
# Port to listen on
60+
gateway_port: 18789
61+
5662

5763
schema:
5864
timezone: str
@@ -67,4 +73,6 @@ schema:
6773
clean_session_locks_on_start: bool?
6874
clean_session_locks_on_exit: bool?
6975
gateway_lan_mode: bool?
76+
gateway_bind_ip: str?
77+
gateway_port: int(1,65535)?
7078

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
#!/usr/bin/env python3
2+
"""
3+
OpenClaw config helper for Home Assistant add-on.
4+
Safely reads/writes openclaw.json without corrupting it.
5+
"""
6+
7+
import json
8+
import os
9+
import sys
10+
from pathlib import Path
11+
12+
CONFIG_PATH = Path(os.environ.get("OPENCLAW_CONFIG_PATH", "/config/.openclaw/openclaw.json"))
13+
14+
15+
def read_config():
16+
"""Read and parse openclaw.json."""
17+
if not CONFIG_PATH.exists():
18+
return None
19+
try:
20+
return json.loads(CONFIG_PATH.read_text(encoding="utf-8"))
21+
except (json.JSONDecodeError, IOError) as e:
22+
print(f"ERROR: Failed to read config: {e}", file=sys.stderr)
23+
return None
24+
25+
26+
def write_config(cfg):
27+
"""Write config back to file with nice formatting."""
28+
try:
29+
CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True)
30+
CONFIG_PATH.write_text(json.dumps(cfg, indent=2) + "\n", encoding="utf-8")
31+
return True
32+
except IOError as e:
33+
print(f"ERROR: Failed to write config: {e}", file=sys.stderr)
34+
return False
35+
36+
37+
def get_gateway_setting(key, default=None):
38+
"""Get a gateway setting from config."""
39+
cfg = read_config()
40+
if cfg is None:
41+
return default
42+
return cfg.get("gateway", {}).get(key, default)
43+
44+
45+
def set_gateway_setting(key, value):
46+
"""Set a gateway setting, preserving other config."""
47+
cfg = read_config()
48+
if cfg is None:
49+
cfg = {}
50+
51+
if "gateway" not in cfg:
52+
cfg["gateway"] = {}
53+
54+
cfg["gateway"][key] = value
55+
return write_config(cfg)
56+
57+
58+
def apply_lan_mode_settings(lan_mode: bool, bind_ip: str, port: int):
59+
"""
60+
Apply LAN mode settings to OpenClaw config.
61+
62+
Args:
63+
lan_mode: True for LAN access, False for loopback only
64+
bind_ip: IP address to bind to (e.g., "0.0.0.0" or "192.168.1.10")
65+
port: Port number to listen on
66+
"""
67+
cfg = read_config()
68+
if cfg is None:
69+
cfg = {}
70+
71+
if "gateway" not in cfg:
72+
cfg["gateway"] = {}
73+
74+
gateway = cfg["gateway"]
75+
76+
# Determine bind value
77+
if lan_mode:
78+
desired_bind = bind_ip if bind_ip else "0.0.0.0"
79+
else:
80+
desired_bind = "loopback"
81+
82+
current_bind = gateway.get("bind", "")
83+
current_port = gateway.get("port", 18789)
84+
85+
changes = []
86+
87+
if current_bind != desired_bind:
88+
gateway["bind"] = desired_bind
89+
changes.append(f"bind: {current_bind} -> {desired_bind}")
90+
91+
if current_port != port:
92+
gateway["port"] = port
93+
changes.append(f"port: {current_port} -> {port}")
94+
95+
if changes:
96+
if write_config(cfg):
97+
print(f"INFO: Updated gateway settings: {', '.join(changes)}")
98+
return True
99+
else:
100+
print("ERROR: Failed to write config")
101+
return False
102+
else:
103+
print(f"INFO: Gateway settings already correct (bind={desired_bind}, port={port})")
104+
return True
105+
106+
107+
def main():
108+
"""CLI entry point for use by run.sh"""
109+
if len(sys.argv) < 2:
110+
print("Usage: oc_config_helper.py <command> [args...]")
111+
sys.exit(1)
112+
113+
cmd = sys.argv[1]
114+
115+
if cmd == "apply-lan-mode":
116+
if len(sys.argv) != 5:
117+
print("Usage: oc_config_helper.py apply-lan-mode <true|false> <bind_ip> <port>")
118+
sys.exit(1)
119+
lan_mode = sys.argv[2].lower() == "true"
120+
bind_ip = sys.argv[3]
121+
port = int(sys.argv[4])
122+
success = apply_lan_mode_settings(lan_mode, bind_ip, port)
123+
sys.exit(0 if success else 1)
124+
125+
elif cmd == "get":
126+
if len(sys.argv) != 3:
127+
print("Usage: oc_config_helper.py get <key>")
128+
sys.exit(1)
129+
key = sys.argv[2]
130+
value = get_gateway_setting(key)
131+
if value is not None:
132+
print(value)
133+
sys.exit(0)
134+
135+
elif cmd == "set":
136+
if len(sys.argv) != 4:
137+
print("Usage: oc_config_helper.py set <key> <value>")
138+
sys.exit(1)
139+
key = sys.argv[2]
140+
value = sys.argv[3]
141+
# Try to convert to int if it looks like a number
142+
try:
143+
value = int(value)
144+
except ValueError:
145+
pass
146+
success = set_gateway_setting(key, value)
147+
sys.exit(0 if success else 1)
148+
149+
else:
150+
print(f"Unknown command: {cmd}")
151+
sys.exit(1)
152+
153+
154+
if __name__ == "__main__":
155+
main()

openclaw_assistant_dev/run.sh

Lines changed: 10 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ CLEAN_LOCKS_ON_EXIT=$(jq -r '.clean_session_locks_on_exit // true' "$OPTIONS_FIL
2929

3030
# Gateway LAN mode toggle (default false for security)
3131
GATEWAY_LAN_MODE=$(jq -r '.gateway_lan_mode // false' "$OPTIONS_FILE")
32+
GATEWAY_BIND_IP=$(jq -r '.gateway_bind_ip // "0.0.0.0"' "$OPTIONS_FILE")
33+
GATEWAY_PORT=$(jq -r '.gateway_port // 18789' "$OPTIONS_FILE")
3234

3335
export TZ="$TZNAME"
3436

@@ -186,42 +188,17 @@ PY
186188
fi
187189

188190
# ------------------------------------------------------------------------------
189-
# Apply gateway LAN mode setting safely (non-destructive config patch)
190-
# This updates gateway.bind without touching other settings (auth token, etc.)
191+
# Apply gateway LAN mode settings safely using helper script
192+
# This updates gateway.bind and gateway.port without touching other settings
191193
# ------------------------------------------------------------------------------
192-
LAN_MODE="${GATEWAY_LAN_MODE}"
193-
if [ -f "$OPENCLAW_CONFIG_PATH" ]; then
194-
python3 - <<PY
195-
import json
196-
from pathlib import Path
197-
import os
194+
ADDON_DIR="$(cd "$(dirname "$0")" && pwd)"
195+
export OPENCLAW_CONFIG_PATH="/config/.openclaw/openclaw.json"
198196

199-
cfg_path = Path(os.environ['OPENCLAW_CONFIG_PATH'])
200-
lan_mode = os.environ.get('GATEWAY_LAN_MODE', 'false').lower() == 'true'
201-
202-
# Read existing config (preserve formatting as much as possible)
203-
text = cfg_path.read_text(encoding='utf-8')
204-
cfg = json.loads(text)
205-
206-
# Determine desired bind value
207-
desired_bind = "lan" if lan_mode else "loopback"
208-
209-
current_bind = cfg.get("gateway", {}).get("bind", "")
210-
211-
if current_bind != desired_bind:
212-
# Ensure gateway section exists
213-
if "gateway" not in cfg:
214-
cfg["gateway"] = {}
215-
cfg["gateway"]["bind"] = desired_bind
216-
217-
# Write back with nice formatting
218-
cfg_path.write_text(json.dumps(cfg, indent=2) + "\n", encoding='utf-8')
219-
print(f"INFO: Updated gateway.bind to '{desired_bind}' (gateway_lan_mode={lan_mode})")
220-
else:
221-
print(f"INFO: gateway.bind already '{desired_bind}', no change needed")
222-
PY
197+
if [ -f "$OPENCLAW_CONFIG_PATH" ]; then
198+
python3 "${ADDON_DIR}/oc_config_helper.py" apply-lan-mode "$GATEWAY_LAN_MODE" "$GATEWAY_BIND_IP" "$GATEWAY_PORT"
223199
else
224-
echo "WARN: OpenClaw config not found at $OPENCLAW_CONFIG_PATH, cannot apply gateway_lan_mode"
200+
echo "WARN: OpenClaw config not found at $OPENCLAW_CONFIG_PATH, cannot apply gateway settings"
201+
echo "INFO: Run 'openclaw onboard' first, then restart the add-on"
225202
fi
226203

227204
echo "Starting OpenClaw Assistant gateway (openclaw)..."

0 commit comments

Comments
 (0)