docs/install/gcp.md
Run a persistent OpenClaw Gateway on a GCP Compute Engine VM using Docker, with durable state, baked-in binaries, and safe restart behavior.
Pricing varies by machine type and region; pick the smallest VM that fits your workload and scale up if you hit OOMs.
The Gateway can be accessed via SSH port forwarding from your laptop, or via direct port exposure if you manage firewalling and tokens yourself.
This guide uses Debian on GCP Compute Engine. Ubuntu also works; map packages accordingly. For the generic Docker flow, see Docker.
e2-micro is free-tier eligible)gcloud CLI, or the Cloud Consolee2-small, Debian 12, 20GB).env and docker-compose.yml```bash
gcloud init
gcloud auth login
```
Or do every step below through the [Cloud Console](https://console.cloud.google.com) web UI instead.
Enable billing at [console.cloud.google.com/billing](https://console.cloud.google.com/billing) (required for Compute Engine).
Console equivalent: IAM & Admin > Create Project, enable billing, then APIs & Services > Enable APIs > "Compute Engine API" > Enable.
```bash
gcloud compute instances create openclaw-gateway \
--zone=us-central1-a \
--machine-type=e2-small \
--boot-disk-size=20GB \
--image-family=debian-12 \
--image-project=debian-cloud
```
Console: click "SSH" next to the VM in the Compute Engine dashboard.
SSH key propagation can take 1-2 minutes after VM creation; wait and retry if connection is refused.
Log out and back in for the group change to take effect, then SSH back in:
```bash
exit
```
```bash
gcloud compute ssh openclaw-gateway --zone=us-central1-a
```
Verify:
```bash
docker --version
docker compose version
```
This guide builds a custom image so any binaries you bake in survive restarts.
```bash
mkdir -p ~/.openclaw
mkdir -p ~/.openclaw/workspace
```
```bash
OPENCLAW_IMAGE=openclaw:latest
OPENCLAW_GATEWAY_TOKEN=
OPENCLAW_GATEWAY_BIND=lan
OPENCLAW_GATEWAY_PORT=18789
OPENCLAW_CONFIG_DIR=/home/$USER/.openclaw
OPENCLAW_WORKSPACE_DIR=/home/$USER/.openclaw/workspace
GOG_KEYRING_PASSWORD=
XDG_CONFIG_HOME=/home/node/.openclaw
```
Set `OPENCLAW_GATEWAY_TOKEN` to manage the stable gateway token through
`.env`; otherwise configure `gateway.auth.token` before relying on clients
across restarts. If neither is set, OpenClaw uses a runtime-only token for
that startup. Generate a keyring password for `GOG_KEYRING_PASSWORD`:
```bash
openssl rand -hex 32
```
**Do not commit this file.** It holds container/runtime env such as
`OPENCLAW_GATEWAY_TOKEN`. Stored provider OAuth/API-key auth lives in the
mounted `~/.openclaw/agents/<agentId>/agent/auth-profiles.json`.
```yaml
services:
openclaw-gateway:
image: ${OPENCLAW_IMAGE}
build: .
restart: unless-stopped
env_file:
- .env
environment:
- HOME=/home/node
- NODE_ENV=production
- TERM=xterm-256color
- OPENCLAW_GATEWAY_BIND=${OPENCLAW_GATEWAY_BIND}
- OPENCLAW_GATEWAY_PORT=${OPENCLAW_GATEWAY_PORT}
- OPENCLAW_GATEWAY_TOKEN=${OPENCLAW_GATEWAY_TOKEN}
- GOG_KEYRING_PASSWORD=${GOG_KEYRING_PASSWORD}
- XDG_CONFIG_HOME=${XDG_CONFIG_HOME}
- PATH=/home/linuxbrew/.linuxbrew/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
volumes:
- ${OPENCLAW_CONFIG_DIR}:/home/node/.openclaw
- ${OPENCLAW_WORKSPACE_DIR}:/home/node/.openclaw/workspace
ports:
# Recommended: keep the Gateway loopback-only on the VM; access via SSH tunnel.
# To expose it publicly, remove the `127.0.0.1:` prefix and firewall accordingly.
- "127.0.0.1:${OPENCLAW_GATEWAY_PORT}:18789"
command:
[
"node",
"dist/index.js",
"gateway",
"--bind",
"${OPENCLAW_GATEWAY_BIND}",
"--port",
"${OPENCLAW_GATEWAY_PORT}",
"--allow-unconfigured",
]
```
`--allow-unconfigured` is only for bootstrap convenience, not a substitute for real gateway configuration. Still set auth (`gateway.auth.token` or password) and a safe bind mode for your deployment.
- [Bake required binaries into the image](/install/docker-vm-runtime#bake-required-binaries-into-the-image)
- [Build and launch](/install/docker-vm-runtime#build-and-launch)
- [What persists where](/install/docker-vm-runtime#what-persists-where)
- [Updates](/install/docker-vm-runtime#updates)
When binding to LAN (`OPENCLAW_GATEWAY_BIND=lan`), configure a trusted browser origin before continuing:
```bash
docker compose run --rm openclaw-cli config set gateway.controlUi.allowedOrigins '["http://127.0.0.1:18789"]' --strict-json
```
Replace `18789` with your configured port if you changed it.
```bash
gcloud compute ssh openclaw-gateway --zone=us-central1-a -- -L 18789:127.0.0.1:18789
```
Open `http://127.0.0.1:18789/` in your browser.
Reprint a clean dashboard link:
```bash
docker compose run --rm openclaw-cli dashboard --no-open
```
If the UI prompts for shared-secret auth, paste the configured token or
password into Control UI settings (this Docker flow writes a token by
default; use your configured password instead if you switched to password
auth).
If Control UI shows `unauthorized` or `disconnected (1008): pairing required`, approve the browser device:
```bash
docker compose run --rm openclaw-cli devices list
docker compose run --rm openclaw-cli devices approve <requestId>
```
See [Docker VM Runtime](/install/docker-vm-runtime#what-persists-where) for the shared persistence map and [update flow](/install/docker-vm-runtime#updates).
SSH connection refused
SSH key propagation can take 1-2 minutes after VM creation. Wait and retry.
OS Login issues
Check your OS Login profile:
gcloud compute os-login describe-profile
Ensure your account has the required IAM permissions (Compute OS Login or Compute OS Admin Login).
Out of memory (OOM)
If the Docker build fails with Killed and exit code 137, the VM was OOM-killed:
# Stop the VM first
gcloud compute instances stop openclaw-gateway --zone=us-central1-a
# Change machine type
gcloud compute instances set-machine-type openclaw-gateway \
--zone=us-central1-a \
--machine-type=e2-small
# Start the VM
gcloud compute instances start openclaw-gateway --zone=us-central1-a
For personal use, your default user account works fine. For automation or CI/CD, create a dedicated service account with minimal permissions:
gcloud iam service-accounts create openclaw-deploy \
--display-name="OpenClaw Deployment"
gcloud projects add-iam-policy-binding my-openclaw-project \
--member="serviceAccount:[email protected]" \
--role="roles/compute.instanceAdmin.v1"
Avoid the Owner role for automation; use the narrowest role that works. See Understanding roles.