Documentation Index
Fetch the complete documentation index at: https://docs.yourhq.ai/llms.txt
Use this file to discover all available pages before exploring further.
gateway/entrypoint.sh is the container’s entrypoint. It runs on every container start and is fully idempotent — steps that already completed on a prior boot are skipped.
Boot sequence
Step 0 — Resolve Supabase credentials
Three credential paths are tried in order: Path A: environment variables —SUPABASE_URL + SUPABASE_SERVICE_ROLE_KEY already set in env. Used immediately, no waiting.
Path B: gateway token exchange — For remote gateways installed via install-gateway.sh. If GATEWAY_TOKEN is set and $OPENCLAW_HOME/.token-consumed does not exist, the entrypoint calls consume_gateway_token() to exchange the one-time token for a gateway slug and UUID.
- Requires:
GATEWAY_TOKEN,SUPABASE_URL,SUPABASE_ANON_KEY - On success: writes the assigned slug to
.gateway-slugand marks the token consumed with.token-consumed - One-shot — the marker file prevents re-exchange on subsequent boots
- If it fails, the container exits (restart with a fresh token)
ui-config volume. The entrypoint polls /config/projects.json + /config/secrets.json every 5 seconds until creds appear. This lets the gateway start before the user has completed browser onboarding — it will wait indefinitely, logging a status line every 30 seconds.
On every subsequent boot, the pinned slug from .gateway-slug (if present) is restored into GATEWAY_ID so the gateway always registers as the same row in Supabase.
Step 1 — Seed git repo (first boot only)
If$OPENCLAW_HOME/repo.git does not exist:
- Creates a bare git repo with
defaultas the HEAD branch - Seeds it with agent template branches:
- From
TEMPLATES_SOURCE(if set, formatgit+<url>) - Otherwise from
/opt/templatesbundled in the image
- From
- Each template directory becomes a git branch:
defaultortemplate/<name>
Step 2 — Attach git remote (conditional)
IfGIT_REMOTE_URL is set (or synthesized from GITHUB_TOKEN + GITHUB_REPO_OWNER + GITHUB_REPO_NAME):
- Adds/updates the
originremote on the bare repo - Installs a
post-commithook that async-pushes every commit to origin - Fetches from origin to fast-forward any branches that moved while the gateway was down
Step 3 — OpenClaw onboard (first boot only)
If$OPENCLAW_HOME/openclaw.json does not exist, runs:
openclaw.json with baseline config. If it exits non-zero, the entrypoint logs a warning and continues — the next boot will retry.
Step 4 — Patch openclaw.json
Every boot (idempotent via //= defaults in jq):
- Sets
tools.profile = "full" - Sets Chrome executable and profile paths
- Enables Telegram channel with
pairingDM policy - Enables the
hq-bootstrapplugin and adds its path toplugins.load.paths
Step 5 — Install hq-bootstrap plugin
Copies*.json and *.ts files from /opt/openclaw-plugins/hq-bootstrap into $OPENCLAW_HOME/plugins/hq-bootstrap/. Runs every boot — safe to repeat.
Step 6 — VNC password
If$HOME/.vnc/passwd does not exist, generates a VNC password:
- Uses
VNC_PASSWORDenv if set - Otherwise generates a random 12-character password
- Saves the vncpasswd-encoded hash to
$HOME/.vnc/passwd - Saves plaintext to
$OPENCLAW_HOME/.vnc-password(readable inside thegateway-statevolume)
Step 7 — Start Xtigervnc + XFCE
Starts the virtual display and desktop:- Removes stale X lock files (
/tmp/.X1-lock,/tmp/.X11-unix/X1) from a crashed prior run - Starts Xtigervnc on
:1— combined X server + VNC server (RFB on port 5901, localhost-only) - Starts
autocutseltwice (CLIPBOARD → PRIMARY sync for noVNC clipboard passthrough) - Starts
dbus-daemonsession bus with a deterministic socket path - Starts
startxfce4
dbus-launch) because dbus-launch double-forks in a way that leaves XFCE components unable to find the bus address in container environments.
Step 8 — Start websockify (noVNC)
IfNOVNC_BIND != "off", starts:
0.0.0.0:6901. The Docker host port mapping (NOVNC_HOST_PORT) decides whether port 6901 is reachable from outside the host.
Set NOVNC_BIND=off to skip noVNC entirely (e.g. on a headless host where you never need remote desktop).
Step 9 — Register in Supabase
If Supabase creds are available, upserts a row in thegateways table with:
slug=GATEWAY_IDlabel=GATEWAY_LABELstatus=readylast_seen_at= nowmeta.reachable_urls= URLs built fromHOST_REACHABLE_URL+ port configmeta.networking_mode=NETWORKING_MODEtenant_id=TENANT_ID
(tenant_id, slug), so re-runs update the existing row.
Also resolves GATEWAY_DB_ID (the row’s UUID) and exports it so the hq-bootstrap plugin can tag agent_usage rows with the gateway that ran them.
Step 10 — Start files-API (conditional)
IfGATEWAY_AUTH_TOKEN is available (from env or /config/gateway-auth-token) AND FILES_API_BIND != "off":
Step 11 — Clear Chrome Singleton locks
Sweeps$HOME/.openclaw/browser/ for Singleton* files left behind by a crashed browser session. Without this, Chrome aborts launch on next boot reporting it’s already running.
Step 12 — Exec OpenClaw gateway
State directory layout
$OPENCLAW_HOME defaults to ~/.openclaw and is persisted in the gateway-state Docker volume.
| Path | Created | Purpose |
|---|---|---|
openclaw.json | First boot (onboard) | OpenClaw runtime config |
repo.git | First boot | Bare git repo for agent branches |
plugins/hq-bootstrap/ | Every boot | HQ plugin files |
shared-auth/auth-profiles.json | On first auth success | Shared auth profiles synced across agents |
.vnc-password | First boot | Plaintext VNC password |
.token-consumed | First boot (token exchange) | Prevents re-exchange of GATEWAY_TOKEN |
.gateway-slug | First boot (token exchange) | Pinned gateway slug restored on subsequent boots |
Desktop/ | First boot | XFCE desktop shortcuts (agent launch icons) |
$HOME/.vnc/passwd is the vncpasswd-encoded password hash read by Xtigervnc.