Deploy OpenClaw securely on Google Cloud. Follow each step, mark it done, and you will have a running AI assistant with enterprise-grade security.
Create VM
gcloud compute instances create openclaw-$(date +%Y%m%d) \
--zone=us-central1-a \
--machine-type=e2-medium \
--image-family=ubuntu-2404-lts-amd64 \
--image-project=ubuntu-os-cloud \
--boot-disk-size=30GB \
--tags=openclaw-serverRun this from your local terminal or GCP Cloud Shell. Takes ~30 seconds.
Expected output:
You should see a table showing your new VM with its external IP address.Permission denied or project not set
Run: gcloud auth login && gcloud config set project YOUR_PROJECT_ID
Quota exceeded
Try a different zone (e.g., us-east1-b) or request a quota increase in the GCP Console.
Connect via SSH
gcloud compute ssh YOUR_VM_NAME --zone=us-central1-a --project=YOUR_PROJECT_IDReplace YOUR_VM_NAME and YOUR_PROJECT_ID with your actual values.
Expected output:
You should see the Ubuntu welcome message with system information. Your prompt will change to username@vm-name:~$Tip
Keep this terminal open — you will use it for the remaining steps.
Install Docker
sudo apt-get update && \
sudo apt-get install -y ca-certificates curl && \
sudo install -m 0755 -d /etc/apt/keyrings && \
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc && \
sudo chmod a+r /etc/apt/keyrings/docker.asc && \
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo \"\$VERSION_CODENAME\") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null && \
sudo apt-get update && \
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-pluginCopy and paste the entire block. It installs Docker from the official repository.
Verify Docker is installed
sudo docker --versionExpected output:
Docker version 27.x.x or similar.Upload ZIP (run on your local machine)
gcloud compute scp ~/Downloads/openclaw-deploy.zip YOUR_VM_NAME:~/ --zone=us-central1-aAdjust the path if your ZIP is saved somewhere else. Replace YOUR_VM_NAME.
Unzip on the VM (run on the VM)
sudo apt-get install -y unzip && unzip ~/openclaw-deploy.zip -d ~/This extracts the deployment files to your home directory.
Expected output:
You should see the extracted files: docker-compose.yml, openclaw-data/, scripts, etc.Tip
You can also upload via the GCP Console: Compute Engine > SSH > Upload File (gear icon in the SSH browser window).
Create directory and move config
mkdir -p ~/openclaw-data && cp ~/openclaw-deploy/openclaw-data/openclaw.json ~/openclaw-data/If your zip extracted to a different folder, adjust the path.
Copy remaining files
cp ~/openclaw-deploy/docker-compose.yml ~/ && cp ~/openclaw-deploy/*.sh ~/ && chmod +x ~/*.shRun secrets setup
./setup-secrets.shHave your OpenAI or Anthropic API key ready. The gateway password is auto-generated.
Expected output:
The script creates a .env file with your API key and gateway password. It also injects the password into openclaw.json.Tip
Your API key is stored in .env with restricted permissions (600). It is never saved in config files.
Permission denied
Run: chmod +x setup-secrets.sh && ./setup-secrets.sh
Start the stack
sudo docker compose up -dThe -d flag runs it in the background. Takes ~30 seconds to fully start.
Wait and check logs
sleep 15 && sudo docker logs openclaw --tail 20Expected output:
You should see: [gateway] listening on ws://0.0.0.0:18789 and [canvas] host mounted. A warning about "non-loopback address" is normal and expected.Permission denied on /home/node/.openclaw/canvas
Make sure you created the openclaw-data directory and mounted it correctly in docker-compose.yml.
Container keeps restarting
Check logs: sudo docker logs openclaw --tail 50. Common cause: invalid API key or missing .env file.
Open SSH tunnel (run on your local machine)
gcloud compute ssh YOUR_VM_NAME --zone=us-central1-a --project=YOUR_PROJECT_ID -- -L 18789:localhost:18789 -o ServerAliveInterval=30 -o ServerAliveCountMax=3The ServerAliveInterval keeps the tunnel from dropping. Replace YOUR_VM_NAME and YOUR_PROJECT_ID.
Open in browser
http://localhost:18789Open this URL in Chrome or Firefox. You should see the OpenClaw Control UI.
Tip
If the tunnel drops (laptop sleeps, network changes), kill it and reconnect: lsof -ti :18789 | xargs kill; then re-run the SSH command.
"Address already in use" error
A previous tunnel is still open. Kill it: lsof -ti :18789 | xargs kill
1. In the browser UI: Enter your gateway password and click Connect
2. On the VM: List pending devices
sudo docker exec openclaw openclaw devices list3. On the VM: Approve the device
sudo docker exec openclaw openclaw devices approve REQUEST_IDReplace REQUEST_ID with the ID shown in the pending devices list.
Expected output:
The UI should show Status: OK and Uptime. The chat should be functional — try sending "Hello!"1. Open Telegram (use VPN if blocked in your country)
2. Message @BotFather, send /newbot, give it a name and username
3. Copy the bot token and add it to the config
sudo python3 -c "
import json
with open('openclaw-data/openclaw.json') as f:
c = json.load(f)
c['channels']['telegram'] = {
'enabled': True,
'dmPolicy': 'pairing',
'botToken': 'YOUR_BOT_TOKEN'
}
with open('openclaw-data/openclaw.json', 'w') as f:
json.dump(c, f, indent=2)
"Replace YOUR_BOT_TOKEN with the token from BotFather.
4. Restart the stack
sudo docker compose down && sudo docker compose --env-file .env up -d5. Message your bot on Telegram, then approve the pairing
sudo docker exec openclaw openclaw pairing approve telegram PAIRING_CODEThe bot will respond with a pairing code when you first message it.
Tip
The Telegram bot runs 24/7 on the VM independently of your SSH tunnel. Users can message it even when your laptop is closed.
Run the health check
./health-check.shExpected output:
[PASS] Gateway bound to 127.0.0.1 (not 0.0.0.0)
[PASS] Authentication: gateway auth token configured
[PASS] Docker running as non-root (uid 1000)
[PASS] No credentials in openclaw-data/openclaw.json
[PASS] Firewall: enabled (GCP VPC firewall)
[PASS] No exposed ports on public interface
...
Score: 10/10 checks passed
Status: SECURETip
If any check fails, the output will tell you exactly what to fix. Most issues are one-command fixes.