| #!/bin/sh |
| |
| |
|
|
| |
| |
| |
| ts() { date -u +"%H:%M:%S"; } |
| log() { echo "[$(ts)] [entrypoint] $*"; } |
| warn() { echo "[$(ts)] [entrypoint] WARN: $*"; } |
|
|
| |
| |
| |
| |
| |
| OPENCLAW_HOME=/home/user |
| mkdir -p /home/user/.openclaw |
|
|
| RETRIES=5 |
| i=0 |
| while [ $i -lt $RETRIES ]; do |
| if [ -d /data ] && touch /data/.write-test 2>/dev/null; then |
| rm -f /data/.write-test |
| OPENCLAW_HOME=/data |
| mkdir -p /data/.openclaw |
| log "Storage bucket /data is writable - using persistent storage" |
| break |
| fi |
| i=$((i+1)) |
| if [ $i -lt $RETRIES ]; then |
| log "Waiting for /data mount... ($i/$RETRIES)" |
| sleep 1 |
| fi |
| done |
|
|
| if [ "$OPENCLAW_HOME" = "/home/user" ]; then |
| warn "/data not writable after ${RETRIES}s - using ephemeral /home/user" |
| fi |
|
|
| export OPENCLAW_HOME |
| log "OPENCLAW_HOME=$OPENCLAW_HOME" |
|
|
| |
| |
| |
| for VAR in $(env | cut -d= -f1); do |
| case "$VAR" in |
| OPENCLAW_*|SPACE_*|SYSTEM_*|HF_*|NODE_*|npm_*) continue ;; |
| esac |
| case "$VAR" in |
| *_API_KEY|*_SECRET_KEY|*_ACCESS_TOKEN|*_BOT_TOKEN|*_AUTH_TOKEN|*_APP_KEY) |
| VAL=$(printenv "$VAR" 2>/dev/null || true) |
| if [ -n "$VAL" ]; then |
| export "$VAR" |
| log "exported: $VAR" |
| fi |
| ;; |
| esac |
| done |
|
|
| export HF_TOKEN="${HF_TOKEN:-}" |
|
|
| |
| |
| |
| log "Running setup..." |
| node /app/spaces/huggingface/setup-hf-config.mjs || true |
| log "Setup done." |
|
|
| |
| |
| |
| if [ -f /app/security-check.sh ]; then |
| sh /app/security-check.sh || true |
| fi |
|
|
| |
| |
| |
| ( |
| DEVICES_DIR="$OPENCLAW_HOME/.openclaw/devices" |
| mkdir -p "$DEVICES_DIR" |
| log "Device auto-pairing watcher started" |
| while true; do |
| sleep 8 |
| PENDING="$DEVICES_DIR/pending.json" |
| PAIRED="$DEVICES_DIR/paired.json" |
| if [ -f "$PENDING" ]; then |
| node - << 'JSEOF' |
| const fs = require('fs'); |
| const dir = process.env.OPENCLAW_HOME + '/.openclaw/devices'; |
| const pend = dir + '/pending.json'; |
| const pair = dir + '/paired.json'; |
| try { |
| const raw = fs.readFileSync(pend, 'utf-8').trim(); |
| if (!raw || raw === '[]' || raw === '{}') process.exit(0); |
| let pending = JSON.parse(raw); |
| if (!Array.isArray(pending)) pending = Object.values(pending); |
| if (pending.length === 0) process.exit(0); |
| let paired = []; |
| try { paired = JSON.parse(fs.readFileSync(pair, 'utf-8')); } catch(e) {} |
| if (!Array.isArray(paired)) paired = []; |
| const ids = new Set(paired.map(function(d){ return d.id||d.deviceId||d.name; })); |
| const todo = pending.filter(function(d){ return !ids.has(d.id||d.deviceId||d.name); }); |
| if (todo.length === 0) process.exit(0); |
| const now = new Date().toISOString(); |
| paired = paired.concat(todo.map(function(d){ |
| return Object.assign({}, d, { approved: true, approvedAt: now }); |
| })); |
| fs.writeFileSync(pair, JSON.stringify(paired, null, 2)); |
| fs.writeFileSync(pend, '[]'); |
| console.log('[auto-pair] Approved ' + todo.length + ' device(s)'); |
| } catch(e) { /* ignore */ } |
| JSEOF |
| fi |
| done |
| ) & |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| log "Starting gateway loop..." |
|
|
| while true; do |
| log "Gateway starting..." |
|
|
| node /app/openclaw.mjs gateway \ |
| --allow-unconfigured \ |
| --bind lan \ |
| --port 7860 |
| CODE=$? |
|
|
| log "Gateway exited (code $CODE)" |
|
|
| |
| WAITED=0 |
| while nc -z 127.0.0.1 7860 2>/dev/null; do |
| if [ $WAITED -eq 0 ]; then |
| log "Port 7860 still held (spawned child running) - waiting..." |
| fi |
| sleep 2 |
| WAITED=$((WAITED + 2)) |
| if [ $WAITED -ge 90 ]; then |
| warn "Port 7860 still in use after 90s - forcing restart" |
| break |
| fi |
| done |
|
|
| if [ $WAITED -gt 0 ]; then |
| log "Port free after ${WAITED}s" |
| fi |
|
|
| sleep 1 |
| log "Restarting gateway..." |
| done |