fix: resolve open docker and gateway-optional regressions (#291)
This commit is contained in:
parent
44aaf150c2
commit
a18240381c
|
|
@ -6,4 +6,5 @@ node_modules
|
||||||
*.md
|
*.md
|
||||||
.github
|
.github
|
||||||
ops
|
ops
|
||||||
scripts
|
scripts/*
|
||||||
|
!scripts/check-node-version.mjs
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,9 @@ NEXT_PUBLIC_GATEWAY_URL=
|
||||||
# Keep gateway auth secrets server-side only (OPENCLAW_GATEWAY_TOKEN / GATEWAY_TOKEN).
|
# Keep gateway auth secrets server-side only (OPENCLAW_GATEWAY_TOKEN / GATEWAY_TOKEN).
|
||||||
# Gateway client id used in websocket handshake (role=operator UI client).
|
# Gateway client id used in websocket handshake (role=operator UI client).
|
||||||
NEXT_PUBLIC_GATEWAY_CLIENT_ID=openclaw-control-ui
|
NEXT_PUBLIC_GATEWAY_CLIENT_ID=openclaw-control-ui
|
||||||
|
# Gateway optional mode: set to 'true' if deploying on VPS with firewall blocking WebSocket ports.
|
||||||
|
# In optional mode, Mission Control runs standalone; core CRUD features work but live gateway events do not.
|
||||||
|
# NEXT_PUBLIC_GATEWAY_OPTIONAL=false
|
||||||
|
|
||||||
# === Data Paths (all optional, defaults to .data/ in project root) ===
|
# === Data Paths (all optional, defaults to .data/ in project root) ===
|
||||||
# MISSION_CONTROL_DATA_DIR=.data
|
# MISSION_CONTROL_DATA_DIR=.data
|
||||||
|
|
|
||||||
26
README.md
26
README.md
|
|
@ -73,6 +73,32 @@ pnpm dev # http://localhost:3000
|
||||||
Initial login is seeded from `AUTH_USER` / `AUTH_PASS` on first run.
|
Initial login is seeded from `AUTH_USER` / `AUTH_PASS` on first run.
|
||||||
If `AUTH_PASS` contains `#`, quote it (e.g. `AUTH_PASS="my#password"`) or use `AUTH_PASS_B64`.
|
If `AUTH_PASS` contains `#`, quote it (e.g. `AUTH_PASS="my#password"`) or use `AUTH_PASS_B64`.
|
||||||
|
|
||||||
|
## Gateway Optional Mode (Standalone Deployment)
|
||||||
|
|
||||||
|
Mission Control can run in standalone mode without a gateway connection. This is useful when:
|
||||||
|
|
||||||
|
- Deploying on a VPS with firewall rules blocking non-standard WebSocket ports (18789/18790)
|
||||||
|
- Testing UI/core workflows without a running gateway
|
||||||
|
- Running Mission Control primarily for project/task operations
|
||||||
|
|
||||||
|
Enable with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
NEXT_PUBLIC_GATEWAY_OPTIONAL=true
|
||||||
|
```
|
||||||
|
|
||||||
|
When enabled, the HUD status shows `Gateway Optional (Standalone)` instead of `Disconnected`.
|
||||||
|
|
||||||
|
Works without gateway:
|
||||||
|
- Task board, projects, agents, sessions, scheduler, webhooks, alerts, activity/audit, cost tracking
|
||||||
|
|
||||||
|
Requires active gateway:
|
||||||
|
- Real-time session updates
|
||||||
|
- Agent-to-agent messaging
|
||||||
|
- Gateway log streaming
|
||||||
|
|
||||||
|
For production VPS setups, you can also proxy gateway WebSockets over 443. See `docs/deployment.md`.
|
||||||
|
|
||||||
### Docker Hardening (Production)
|
### Docker Hardening (Production)
|
||||||
|
|
||||||
For production deployments, use the hardened compose overlay:
|
For production deployments, use the hardened compose overlay:
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,12 @@ services:
|
||||||
- NET_BIND_SERVICE
|
- NET_BIND_SERVICE
|
||||||
security_opt:
|
security_opt:
|
||||||
- no-new-privileges:true
|
- no-new-privileges:true
|
||||||
pids_limit: 256
|
|
||||||
deploy:
|
deploy:
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
memory: 512M
|
memory: 512M
|
||||||
cpus: '1.0'
|
cpus: '1.0'
|
||||||
|
pids: 256
|
||||||
networks:
|
networks:
|
||||||
- mc-net
|
- mc-net
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
|
||||||
|
|
@ -175,3 +175,36 @@ Then restart the gateway and reconnect from Mission Control.
|
||||||
|
|
||||||
Device identity signing uses WebCrypto and requires a secure browser context.
|
Device identity signing uses WebCrypto and requires a secure browser context.
|
||||||
Open Mission Control over HTTPS (or localhost), then reconnect.
|
Open Mission Control over HTTPS (or localhost), then reconnect.
|
||||||
|
|
||||||
|
### "Gateway shows offline on VPS deployment"
|
||||||
|
|
||||||
|
Browser WebSocket connections to non-standard ports (like 18789/18790) are often blocked by VPS firewall/provider rules.
|
||||||
|
|
||||||
|
Quick option:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
NEXT_PUBLIC_GATEWAY_OPTIONAL=true
|
||||||
|
```
|
||||||
|
|
||||||
|
This runs Mission Control in standalone mode (core features available, live gateway streams unavailable).
|
||||||
|
|
||||||
|
Production option: reverse-proxy gateway WebSocket over 443.
|
||||||
|
|
||||||
|
nginx example:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
location /gateway-ws {
|
||||||
|
proxy_pass http://127.0.0.1:18789;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_read_timeout 86400;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then point UI to:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
NEXT_PUBLIC_GATEWAY_URL=wss://your-domain.com/gateway-ws
|
||||||
|
```
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,12 @@ export function ConnectionStatus({
|
||||||
}: ConnectionStatusProps) {
|
}: ConnectionStatusProps) {
|
||||||
const { connection } = useMissionControl()
|
const { connection } = useMissionControl()
|
||||||
const displayUrl = connection.url || 'ws://<gateway-host>:<gateway-port>'
|
const displayUrl = connection.url || 'ws://<gateway-host>:<gateway-port>'
|
||||||
|
const isGatewayOptional = process.env.NEXT_PUBLIC_GATEWAY_OPTIONAL === 'true'
|
||||||
|
|
||||||
const getStatusColor = () => {
|
const getStatusColor = () => {
|
||||||
if (isConnected) return 'bg-green-500 animate-pulse'
|
if (isConnected) return 'bg-green-500 animate-pulse'
|
||||||
if (connection.reconnectAttempts > 0) return 'bg-yellow-500'
|
if (connection.reconnectAttempts > 0) return 'bg-yellow-500'
|
||||||
|
if (isGatewayOptional && !isConnected) return 'bg-blue-500'
|
||||||
return 'bg-red-500'
|
return 'bg-red-500'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,6 +34,9 @@ export function ConnectionStatus({
|
||||||
if (connection.reconnectAttempts > 0) {
|
if (connection.reconnectAttempts > 0) {
|
||||||
return `Reconnecting... (${connection.reconnectAttempts}/10)`
|
return `Reconnecting... (${connection.reconnectAttempts}/10)`
|
||||||
}
|
}
|
||||||
|
if (isGatewayOptional && !isConnected) {
|
||||||
|
return 'Gateway Optional (Standalone)'
|
||||||
|
}
|
||||||
return 'Disconnected'
|
return 'Disconnected'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue