docs: convert Fly, Hetzner, GCP, Azure hosting pages to Mintlify Steps

This commit is contained in:
Vincent Koc
2026-03-19 11:56:49 -07:00
parent 7187d1da06
commit e466b55661
4 changed files with 591 additions and 586 deletions

View File

@@ -27,139 +27,148 @@ Youll need:
- An Azure subscription with permission to create compute and network resources
- Azure CLI installed (see [Azure CLI install steps](https://learn.microsoft.com/cli/azure/install-azure-cli) if needed)
## 1) Sign in to Azure CLI
<Steps>
<Step title="Sign in to Azure CLI">
```bash
az login # Sign in and select your Azure subscription
az extension add -n ssh # Extension required for Azure Bastion SSH management
```
</Step>
```bash
az login # Sign in and select your Azure subscription
az extension add -n ssh # Extension required for Azure Bastion SSH management
```
<Step title="Register required resource providers (one-time)">
```bash
az provider register --namespace Microsoft.Compute
az provider register --namespace Microsoft.Network
```
## 2) Register required resource providers (one-time)
Verify Azure resource provider registration. Wait until both show `Registered`.
```bash
az provider register --namespace Microsoft.Compute
az provider register --namespace Microsoft.Network
```
```bash
az provider show --namespace Microsoft.Compute --query registrationState -o tsv
az provider show --namespace Microsoft.Network --query registrationState -o tsv
```
Verify Azure resource provider registration. Wait until both show `Registered`.
</Step>
```bash
az provider show --namespace Microsoft.Compute --query registrationState -o tsv
az provider show --namespace Microsoft.Network --query registrationState -o tsv
```
<Step title="Set deployment variables">
```bash
RG="rg-openclaw"
LOCATION="westus2"
TEMPLATE_URI="https://raw.githubusercontent.com/openclaw/openclaw/main/infra/azure/templates/azuredeploy.json"
PARAMS_URI="https://raw.githubusercontent.com/openclaw/openclaw/main/infra/azure/templates/azuredeploy.parameters.json"
```
</Step>
## 3) Set deployment variables
<Step title="Select SSH key">
Use your existing public key if you have one:
```bash
RG="rg-openclaw"
LOCATION="westus2"
TEMPLATE_URI="https://raw.githubusercontent.com/openclaw/openclaw/main/infra/azure/templates/azuredeploy.json"
PARAMS_URI="https://raw.githubusercontent.com/openclaw/openclaw/main/infra/azure/templates/azuredeploy.parameters.json"
```
```bash
SSH_PUB_KEY="$(cat ~/.ssh/id_ed25519.pub)"
```
## 4) Select SSH key
If you dont have an SSH key yet, run the following:
Use your existing public key if you have one:
```bash
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519 -C "you@example.com"
SSH_PUB_KEY="$(cat ~/.ssh/id_ed25519.pub)"
```
```bash
SSH_PUB_KEY="$(cat ~/.ssh/id_ed25519.pub)"
```
</Step>
If you dont have an SSH key yet, run the following:
<Step title="Select VM size and OS disk size">
Set VM and disk sizing variables:
```bash
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519 -C "you@example.com"
SSH_PUB_KEY="$(cat ~/.ssh/id_ed25519.pub)"
```
```bash
VM_SIZE="Standard_B2as_v2"
OS_DISK_SIZE_GB=64
```
## 5) Select VM size and OS disk size
Choose a VM size and OS disk size that are available in your Azure subscription/region and matches your workload:
Set VM and disk sizing variables:
- Start smaller for light usage and scale up later
- Use more vCPU/RAM/OS disk size for heavier automation, more channels, or larger model/tool workloads
- If a VM size is unavailable in your region or subscription quota, pick the closest available SKU
```bash
VM_SIZE="Standard_B2as_v2"
OS_DISK_SIZE_GB=64
```
List VM sizes available in your target region:
Choose a VM size and OS disk size that are available in your Azure subscription/region and matches your workload:
```bash
az vm list-skus --location "${LOCATION}" --resource-type virtualMachines -o table
```
- Start smaller for light usage and scale up later
- Use more vCPU/RAM/OS disk size for heavier automation, more channels, or larger model/tool workloads
- If a VM size is unavailable in your region or subscription quota, pick the closest available SKU
Check your current VM vCPU and OS disk size usage/quota:
List VM sizes available in your target region:
```bash
az vm list-usage --location "${LOCATION}" -o table
```
```bash
az vm list-skus --location "${LOCATION}" --resource-type virtualMachines -o table
```
</Step>
Check your current VM vCPU and OS disk size usage/quota:
<Step title="Create the resource group">
```bash
az group create -n "${RG}" -l "${LOCATION}"
```
</Step>
```bash
az vm list-usage --location "${LOCATION}" -o table
```
<Step title="Deploy resources">
This command applies your selected SSH key, VM size, and OS disk size.
## 6) Create the resource group
```bash
az deployment group create \
-g "${RG}" \
--template-uri "${TEMPLATE_URI}" \
--parameters "${PARAMS_URI}" \
--parameters location="${LOCATION}" \
--parameters vmSize="${VM_SIZE}" \
--parameters osDiskSizeGb="${OS_DISK_SIZE_GB}" \
--parameters sshPublicKey="${SSH_PUB_KEY}"
```
```bash
az group create -n "${RG}" -l "${LOCATION}"
```
</Step>
## 7) Deploy resources
<Step title="SSH into the VM through Azure Bastion">
```bash
RG="rg-openclaw"
VM_NAME="vm-openclaw"
BASTION_NAME="bas-openclaw"
ADMIN_USERNAME="openclaw"
VM_ID="$(az vm show -g "${RG}" -n "${VM_NAME}" --query id -o tsv)"
This command applies your selected SSH key, VM size, and OS disk size.
az network bastion ssh \
--name "${BASTION_NAME}" \
--resource-group "${RG}" \
--target-resource-id "${VM_ID}" \
--auth-type ssh-key \
--username "${ADMIN_USERNAME}" \
--ssh-key ~/.ssh/id_ed25519
```
```bash
az deployment group create \
-g "${RG}" \
--template-uri "${TEMPLATE_URI}" \
--parameters "${PARAMS_URI}" \
--parameters location="${LOCATION}" \
--parameters vmSize="${VM_SIZE}" \
--parameters osDiskSizeGb="${OS_DISK_SIZE_GB}" \
--parameters sshPublicKey="${SSH_PUB_KEY}"
```
</Step>
## 8) SSH into the VM through Azure Bastion
<Step title="Install OpenClaw (in the VM shell)">
```bash
curl -fsSL https://openclaw.ai/install.sh -o /tmp/openclaw-install.sh
bash /tmp/openclaw-install.sh
rm -f /tmp/openclaw-install.sh
openclaw --version
```
```bash
RG="rg-openclaw"
VM_NAME="vm-openclaw"
BASTION_NAME="bas-openclaw"
ADMIN_USERNAME="openclaw"
VM_ID="$(az vm show -g "${RG}" -n "${VM_NAME}" --query id -o tsv)"
The installer script handles Node detection/installation and runs onboarding by default.
az network bastion ssh \
--name "${BASTION_NAME}" \
--resource-group "${RG}" \
--target-resource-id "${VM_ID}" \
--auth-type ssh-key \
--username "${ADMIN_USERNAME}" \
--ssh-key ~/.ssh/id_ed25519
```
</Step>
## 9) Install OpenClaw (in the VM shell)
<Step title="Verify the Gateway">
After onboarding completes:
```bash
curl -fsSL https://openclaw.ai/install.sh -o /tmp/openclaw-install.sh
bash /tmp/openclaw-install.sh
rm -f /tmp/openclaw-install.sh
openclaw --version
```
```bash
openclaw gateway status
```
The installer script handles Node detection/installation and runs onboarding by default.
Most enterprise Azure teams already have GitHub Copilot licenses. If that is your case, we recommend choosing the GitHub Copilot provider in the OpenClaw onboarding wizard. See [GitHub Copilot provider](/providers/github-copilot).
## 10) Verify the Gateway
The included ARM template uses Ubuntu image `version: "latest"` for convenience. If you need reproducible builds, pin a specific image version in `infra/azure/templates/azuredeploy.json` (you can list versions with `az vm image list --publisher Canonical --offer ubuntu-24_04-lts --sku server --all -o table`).
After onboarding completes:
```bash
openclaw gateway status
```
Most enterprise Azure teams already have GitHub Copilot licenses. If that is your case, we recommend choosing the GitHub Copilot provider in the OpenClaw onboarding wizard. See [GitHub Copilot provider](/providers/github-copilot).
The included ARM template uses Ubuntu image `version: "latest"` for convenience. If you need reproducible builds, pin a specific image version in `infra/azure/templates/azuredeploy.json` (you can list versions with `az vm image list --publisher Canonical --offer ubuntu-24_04-lts --sku server --all -o table`).
</Step>
</Steps>
## Next steps

View File

@@ -25,220 +25,228 @@ read_when:
3. Deploy with `fly deploy`
4. SSH in to create config or use Control UI
## 1) Create the Fly app
<Steps>
<Step title="Create the Fly app">
```bash
# Clone the repo
git clone https://github.com/openclaw/openclaw.git
cd openclaw
```bash
# Clone the repo
git clone https://github.com/openclaw/openclaw.git
cd openclaw
# Create a new Fly app (pick your own name)
fly apps create my-openclaw
# Create a new Fly app (pick your own name)
fly apps create my-openclaw
# Create a persistent volume (1GB is usually enough)
fly volumes create openclaw_data --size 1 --region iad
```
# Create a persistent volume (1GB is usually enough)
fly volumes create openclaw_data --size 1 --region iad
```
**Tip:** Choose a region close to you. Common options: `lhr` (London), `iad` (Virginia), `sjc` (San Jose).
**Tip:** Choose a region close to you. Common options: `lhr` (London), `iad` (Virginia), `sjc` (San Jose).
</Step>
## 2) Configure fly.toml
<Step title="Configure fly.toml">
Edit `fly.toml` to match your app name and requirements.
Edit `fly.toml` to match your app name and requirements.
**Security note:** The default config exposes a public URL. For a hardened deployment with no public IP, see [Private Deployment](#private-deployment-hardened) or use `fly.private.toml`.
**Security note:** The default config exposes a public URL. For a hardened deployment with no public IP, see [Private Deployment](#private-deployment-hardened) or use `fly.private.toml`.
```toml
app = "my-openclaw" # Your app name
primary_region = "iad"
```toml
app = "my-openclaw" # Your app name
primary_region = "iad"
[build]
dockerfile = "Dockerfile"
[build]
dockerfile = "Dockerfile"
[env]
NODE_ENV = "production"
OPENCLAW_PREFER_PNPM = "1"
OPENCLAW_STATE_DIR = "/data"
NODE_OPTIONS = "--max-old-space-size=1536"
[env]
NODE_ENV = "production"
OPENCLAW_PREFER_PNPM = "1"
OPENCLAW_STATE_DIR = "/data"
NODE_OPTIONS = "--max-old-space-size=1536"
[processes]
app = "node dist/index.js gateway --allow-unconfigured --port 3000 --bind lan"
[processes]
app = "node dist/index.js gateway --allow-unconfigured --port 3000 --bind lan"
[http_service]
internal_port = 3000
force_https = true
auto_stop_machines = false
auto_start_machines = true
min_machines_running = 1
processes = ["app"]
[http_service]
internal_port = 3000
force_https = true
auto_stop_machines = false
auto_start_machines = true
min_machines_running = 1
processes = ["app"]
[[vm]]
size = "shared-cpu-2x"
memory = "2048mb"
[[vm]]
size = "shared-cpu-2x"
memory = "2048mb"
[mounts]
source = "openclaw_data"
destination = "/data"
```
[mounts]
source = "openclaw_data"
destination = "/data"
```
**Key settings:**
**Key settings:**
| Setting | Why |
| ------------------------------ | --------------------------------------------------------------------------- |
| `--bind lan` | Binds to `0.0.0.0` so Fly's proxy can reach the gateway |
| `--allow-unconfigured` | Starts without a config file (you'll create one after) |
| `internal_port = 3000` | Must match `--port 3000` (or `OPENCLAW_GATEWAY_PORT`) for Fly health checks |
| `memory = "2048mb"` | 512MB is too small; 2GB recommended |
| `OPENCLAW_STATE_DIR = "/data"` | Persists state on the volume |
| Setting | Why |
| ------------------------------ | --------------------------------------------------------------------------- |
| `--bind lan` | Binds to `0.0.0.0` so Fly's proxy can reach the gateway |
| `--allow-unconfigured` | Starts without a config file (you'll create one after) |
| `internal_port = 3000` | Must match `--port 3000` (or `OPENCLAW_GATEWAY_PORT`) for Fly health checks |
| `memory = "2048mb"` | 512MB is too small; 2GB recommended |
| `OPENCLAW_STATE_DIR = "/data"` | Persists state on the volume |
</Step>
## 3) Set secrets
<Step title="Set secrets">
```bash
# Required: Gateway token (for non-loopback binding)
fly secrets set OPENCLAW_GATEWAY_TOKEN=$(openssl rand -hex 32)
```bash
# Required: Gateway token (for non-loopback binding)
fly secrets set OPENCLAW_GATEWAY_TOKEN=$(openssl rand -hex 32)
# Model provider API keys
fly secrets set ANTHROPIC_API_KEY=sk-ant-...
# Model provider API keys
fly secrets set ANTHROPIC_API_KEY=sk-ant-...
# Optional: Other providers
fly secrets set OPENAI_API_KEY=sk-...
fly secrets set GOOGLE_API_KEY=...
# Optional: Other providers
fly secrets set OPENAI_API_KEY=sk-...
fly secrets set GOOGLE_API_KEY=...
# Channel tokens
fly secrets set DISCORD_BOT_TOKEN=MTQ...
```
# Channel tokens
fly secrets set DISCORD_BOT_TOKEN=MTQ...
```
**Notes:**
**Notes:**
- Non-loopback binds (`--bind lan`) require `OPENCLAW_GATEWAY_TOKEN` for security.
- Treat these tokens like passwords.
- **Prefer env vars over config file** for all API keys and tokens. This keeps secrets out of `openclaw.json` where they could be accidentally exposed or logged.
- Non-loopback binds (`--bind lan`) require `OPENCLAW_GATEWAY_TOKEN` for security.
- Treat these tokens like passwords.
- **Prefer env vars over config file** for all API keys and tokens. This keeps secrets out of `openclaw.json` where they could be accidentally exposed or logged.
</Step>
## 4) Deploy
<Step title="Deploy">
```bash
fly deploy
```
```bash
fly deploy
```
First deploy builds the Docker image (~2-3 minutes). Subsequent deploys are faster.
First deploy builds the Docker image (~2-3 minutes). Subsequent deploys are faster.
After deployment, verify:
After deployment, verify:
```bash
fly status
fly logs
```
```bash
fly status
fly logs
```
You should see:
You should see:
```
[gateway] listening on ws://0.0.0.0:3000 (PID xxx)
[discord] logged in to discord as xxx
```
```
[gateway] listening on ws://0.0.0.0:3000 (PID xxx)
[discord] logged in to discord as xxx
```
</Step>
## 5) Create config file
<Step title="Create config file">
SSH into the machine to create a proper config:
SSH into the machine to create a proper config:
```bash
fly ssh console
```
```bash
fly ssh console
```
Create the config directory and file:
Create the config directory and file:
```bash
mkdir -p /data
cat > /data/openclaw.json << 'EOF'
{
"agents": {
"defaults": {
"model": {
"primary": "anthropic/claude-opus-4-6",
"fallbacks": ["anthropic/claude-sonnet-4-6", "openai/gpt-4o"]
},
"maxConcurrent": 4
},
"list": [
{
"id": "main",
"default": true
}
]
},
"auth": {
"profiles": {
"anthropic:default": { "mode": "token", "provider": "anthropic" },
"openai:default": { "mode": "token", "provider": "openai" }
}
},
"bindings": [
```bash
mkdir -p /data
cat > /data/openclaw.json << 'EOF'
{
"agentId": "main",
"match": { "channel": "discord" }
}
],
"channels": {
"discord": {
"enabled": true,
"groupPolicy": "allowlist",
"guilds": {
"YOUR_GUILD_ID": {
"channels": { "general": { "allow": true } },
"requireMention": false
"agents": {
"defaults": {
"model": {
"primary": "anthropic/claude-opus-4-6",
"fallbacks": ["anthropic/claude-sonnet-4-6", "openai/gpt-4o"]
},
"maxConcurrent": 4
},
"list": [
{
"id": "main",
"default": true
}
]
},
"auth": {
"profiles": {
"anthropic:default": { "mode": "token", "provider": "anthropic" },
"openai:default": { "mode": "token", "provider": "openai" }
}
}
},
"bindings": [
{
"agentId": "main",
"match": { "channel": "discord" }
}
],
"channels": {
"discord": {
"enabled": true,
"groupPolicy": "allowlist",
"guilds": {
"YOUR_GUILD_ID": {
"channels": { "general": { "allow": true } },
"requireMention": false
}
}
}
},
"gateway": {
"mode": "local",
"bind": "auto"
},
"meta": {}
}
},
"gateway": {
"mode": "local",
"bind": "auto"
},
"meta": {}
}
EOF
```
EOF
```
**Note:** With `OPENCLAW_STATE_DIR=/data`, the config path is `/data/openclaw.json`.
**Note:** With `OPENCLAW_STATE_DIR=/data`, the config path is `/data/openclaw.json`.
**Note:** The Discord token can come from either:
**Note:** The Discord token can come from either:
- Environment variable: `DISCORD_BOT_TOKEN` (recommended for secrets)
- Config file: `channels.discord.token`
- Environment variable: `DISCORD_BOT_TOKEN` (recommended for secrets)
- Config file: `channels.discord.token`
If using env var, no need to add token to config. The gateway reads `DISCORD_BOT_TOKEN` automatically.
If using env var, no need to add token to config. The gateway reads `DISCORD_BOT_TOKEN` automatically.
Restart to apply:
Restart to apply:
```bash
exit
fly machine restart <machine-id>
```
```bash
exit
fly machine restart <machine-id>
```
## 6) Access the Gateway
</Step>
### Control UI
<Step title="Access the Gateway">
### Control UI
Open in browser:
Open in browser:
```bash
fly open
```
```bash
fly open
```
Or visit `https://my-openclaw.fly.dev/`
Or visit `https://my-openclaw.fly.dev/`
Paste your gateway token (the one from `OPENCLAW_GATEWAY_TOKEN`) to authenticate.
Paste your gateway token (the one from `OPENCLAW_GATEWAY_TOKEN`) to authenticate.
### Logs
### Logs
```bash
fly logs # Live logs
fly logs --no-tail # Recent logs
```
```bash
fly logs # Live logs
fly logs --no-tail # Recent logs
```
### SSH Console
### SSH Console
```bash
fly ssh console
```
```bash
fly ssh console
```
</Step>
</Steps>
## Troubleshooting

View File

@@ -65,277 +65,271 @@ For the generic Docker flow, see [Docker](/install/docker).
---
## 1) Install gcloud CLI (or use Console)
<Steps>
<Step title="Install gcloud CLI (or use Console)">
**Option A: gcloud CLI** (recommended for automation)
**Option A: gcloud CLI** (recommended for automation)
Install from [https://cloud.google.com/sdk/docs/install](https://cloud.google.com/sdk/docs/install)
Install from [https://cloud.google.com/sdk/docs/install](https://cloud.google.com/sdk/docs/install)
Initialize and authenticate:
Initialize and authenticate:
```bash
gcloud init
gcloud auth login
```
```bash
gcloud init
gcloud auth login
```
**Option B: Cloud Console**
**Option B: Cloud Console**
All steps can be done via the web UI at [https://console.cloud.google.com](https://console.cloud.google.com)
All steps can be done via the web UI at [https://console.cloud.google.com](https://console.cloud.google.com)
</Step>
---
<Step title="Create a GCP project">
**CLI:**
## 2) Create a GCP project
```bash
gcloud projects create my-openclaw-project --name="OpenClaw Gateway"
gcloud config set project my-openclaw-project
```
**CLI:**
Enable billing at [https://console.cloud.google.com/billing](https://console.cloud.google.com/billing) (required for Compute Engine).
```bash
gcloud projects create my-openclaw-project --name="OpenClaw Gateway"
gcloud config set project my-openclaw-project
```
Enable the Compute Engine API:
Enable billing at [https://console.cloud.google.com/billing](https://console.cloud.google.com/billing) (required for Compute Engine).
```bash
gcloud services enable compute.googleapis.com
```
Enable the Compute Engine API:
**Console:**
```bash
gcloud services enable compute.googleapis.com
```
1. Go to IAM & Admin > Create Project
2. Name it and create
3. Enable billing for the project
4. Navigate to APIs & Services > Enable APIs > search "Compute Engine API" > Enable
**Console:**
</Step>
1. Go to IAM & Admin > Create Project
2. Name it and create
3. Enable billing for the project
4. Navigate to APIs & Services > Enable APIs > search "Compute Engine API" > Enable
<Step title="Create the VM">
**Machine types:**
---
| Type | Specs | Cost | Notes |
| --------- | ------------------------ | ------------------ | -------------------------------------------- |
| e2-medium | 2 vCPU, 4GB RAM | ~$25/mo | Most reliable for local Docker builds |
| e2-small | 2 vCPU, 2GB RAM | ~$12/mo | Minimum recommended for Docker build |
| e2-micro | 2 vCPU (shared), 1GB RAM | Free tier eligible | Often fails with Docker build OOM (exit 137) |
## 3) Create the VM
**CLI:**
**Machine types:**
```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
```
| Type | Specs | Cost | Notes |
| --------- | ------------------------ | ------------------ | -------------------------------------------- |
| e2-medium | 2 vCPU, 4GB RAM | ~$25/mo | Most reliable for local Docker builds |
| e2-small | 2 vCPU, 2GB RAM | ~$12/mo | Minimum recommended for Docker build |
| e2-micro | 2 vCPU (shared), 1GB RAM | Free tier eligible | Often fails with Docker build OOM (exit 137) |
**Console:**
**CLI:**
1. Go to Compute Engine > VM instances > Create instance
2. Name: `openclaw-gateway`
3. Region: `us-central1`, Zone: `us-central1-a`
4. Machine type: `e2-small`
5. Boot disk: Debian 12, 20GB
6. Create
```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
```
</Step>
**Console:**
<Step title="SSH into the VM">
**CLI:**
1. Go to Compute Engine > VM instances > Create instance
2. Name: `openclaw-gateway`
3. Region: `us-central1`, Zone: `us-central1-a`
4. Machine type: `e2-small`
5. Boot disk: Debian 12, 20GB
6. Create
```bash
gcloud compute ssh openclaw-gateway --zone=us-central1-a
```
---
**Console:**
## 4) SSH into the VM
Click the "SSH" button next to your VM in the Compute Engine dashboard.
**CLI:**
Note: SSH key propagation can take 1-2 minutes after VM creation. If connection is refused, wait and retry.
```bash
gcloud compute ssh openclaw-gateway --zone=us-central1-a
```
</Step>
**Console:**
<Step title="Install Docker (on the VM)">
```bash
sudo apt-get update
sudo apt-get install -y git curl ca-certificates
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER
```
Click the "SSH" button next to your VM in the Compute Engine dashboard.
Log out and back in for the group change to take effect:
Note: SSH key propagation can take 1-2 minutes after VM creation. If connection is refused, wait and retry.
```bash
exit
```
---
Then SSH back in:
## 5) Install Docker (on the VM)
```bash
gcloud compute ssh openclaw-gateway --zone=us-central1-a
```
```bash
sudo apt-get update
sudo apt-get install -y git curl ca-certificates
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER
```
Verify:
Log out and back in for the group change to take effect:
```bash
docker --version
docker compose version
```
```bash
exit
```
</Step>
Then SSH back in:
<Step title="Clone the OpenClaw repository">
```bash
git clone https://github.com/openclaw/openclaw.git
cd openclaw
```
```bash
gcloud compute ssh openclaw-gateway --zone=us-central1-a
```
This guide assumes you will build a custom image to guarantee binary persistence.
Verify:
</Step>
```bash
docker --version
docker compose version
```
<Step title="Create persistent host directories">
Docker containers are ephemeral.
All long-lived state must live on the host.
---
```bash
mkdir -p ~/.openclaw
mkdir -p ~/.openclaw/workspace
```
## 6) Clone the OpenClaw repository
</Step>
```bash
git clone https://github.com/openclaw/openclaw.git
cd openclaw
```
<Step title="Configure environment variables">
Create `.env` in the repository root.
This guide assumes you will build a custom image to guarantee binary persistence.
```bash
OPENCLAW_IMAGE=openclaw:latest
OPENCLAW_GATEWAY_TOKEN=change-me-now
OPENCLAW_GATEWAY_BIND=lan
OPENCLAW_GATEWAY_PORT=18789
---
OPENCLAW_CONFIG_DIR=/home/$USER/.openclaw
OPENCLAW_WORKSPACE_DIR=/home/$USER/.openclaw/workspace
## 7) Create persistent host directories
GOG_KEYRING_PASSWORD=change-me-now
XDG_CONFIG_HOME=/home/node/.openclaw
```
Docker containers are ephemeral.
All long-lived state must live on the host.
Generate strong secrets:
```bash
mkdir -p ~/.openclaw
mkdir -p ~/.openclaw/workspace
```
```bash
openssl rand -hex 32
```
---
**Do not commit this file.**
## 8) Configure environment variables
</Step>
Create `.env` in the repository root.
<Step title="Docker Compose configuration">
Create or update `docker-compose.yml`.
```bash
OPENCLAW_IMAGE=openclaw:latest
OPENCLAW_GATEWAY_TOKEN=change-me-now
OPENCLAW_GATEWAY_BIND=lan
OPENCLAW_GATEWAY_PORT=18789
```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",
]
```
OPENCLAW_CONFIG_DIR=/home/$USER/.openclaw
OPENCLAW_WORKSPACE_DIR=/home/$USER/.openclaw/workspace
`--allow-unconfigured` is only for bootstrap convenience, it is not a replacement for a proper gateway configuration. Still set auth (`gateway.auth.token` or password) and use safe bind settings for your deployment.
GOG_KEYRING_PASSWORD=change-me-now
XDG_CONFIG_HOME=/home/node/.openclaw
```
</Step>
Generate strong secrets:
<Step title="Shared Docker VM runtime steps">
Use the shared runtime guide for the common Docker host flow:
```bash
openssl rand -hex 32
```
- [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)
**Do not commit this file.**
</Step>
---
<Step title="GCP-specific launch notes">
On GCP, if build fails with `Killed` or `exit code 137` during `pnpm install --frozen-lockfile`, the VM is out of memory. Use `e2-small` minimum, or `e2-medium` for more reliable first builds.
## 9) Docker Compose configuration
When binding to LAN (`OPENCLAW_GATEWAY_BIND=lan`), configure a trusted browser origin before continuing:
Create or update `docker-compose.yml`.
```bash
docker compose run --rm openclaw-cli config set gateway.controlUi.allowedOrigins '["http://127.0.0.1:18789"]' --strict-json
```
If you changed the gateway port, replace `18789` with your configured port.
```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",
]
```
</Step>
<Step title="Access from your laptop">
Create an SSH tunnel to forward the Gateway port:
`--allow-unconfigured` is only for bootstrap convenience, it is not a replacement for a proper gateway configuration. Still set auth (`gateway.auth.token` or password) and use safe bind settings for your deployment.
```bash
gcloud compute ssh openclaw-gateway --zone=us-central1-a -- -L 18789:127.0.0.1:18789
```
Open in your browser:
---
`http://127.0.0.1:18789/`
Fetch a fresh tokenized dashboard link:
## 10) Shared Docker VM runtime steps
```bash
docker compose run --rm openclaw-cli dashboard --no-open
```
Use the shared runtime guide for the common Docker host flow:
Paste the token from that URL.
If Control UI shows `unauthorized` or `disconnected (1008): pairing required`, approve the browser device:
- [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)
---
## 11) GCP-specific launch notes
On GCP, if build fails with `Killed` or `exit code 137` during `pnpm install --frozen-lockfile`, the VM is out of memory. Use `e2-small` minimum, or `e2-medium` for more reliable first builds.
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
```
If you changed the gateway port, replace `18789` with your configured port.
## 12) Access from your laptop
Create an SSH tunnel to forward the Gateway port:
```bash
gcloud compute ssh openclaw-gateway --zone=us-central1-a -- -L 18789:127.0.0.1:18789
```
Open in your browser:
`http://127.0.0.1:18789/`
Fetch a fresh tokenized dashboard link:
```bash
docker compose run --rm openclaw-cli dashboard --no-open
```
Paste the token from that URL.
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>
```
Need the shared persistence and update reference again?
See [Docker VM Runtime](/install/docker-vm-runtime#what-persists-where) and [Docker VM Runtime updates](/install/docker-vm-runtime#updates).
```bash
docker compose run --rm openclaw-cli devices list
docker compose run --rm openclaw-cli devices approve <requestId>
```
Need the shared persistence and update reference again?
See [Docker VM Runtime](/install/docker-vm-runtime#what-persists-where) and [Docker VM Runtime updates](/install/docker-vm-runtime#updates).
</Step>
</Steps>
---

View File

@@ -72,162 +72,156 @@ For the generic Docker flow, see [Docker](/install/docker).
---
## 1) Provision the VPS
<Steps>
<Step title="Provision the VPS">
Create an Ubuntu or Debian VPS in Hetzner.
Create an Ubuntu or Debian VPS in Hetzner.
Connect as root:
Connect as root:
```bash
ssh root@YOUR_VPS_IP
```
```bash
ssh root@YOUR_VPS_IP
```
This guide assumes the VPS is stateful.
Do not treat it as disposable infrastructure.
This guide assumes the VPS is stateful.
Do not treat it as disposable infrastructure.
</Step>
---
<Step title="Install Docker (on the VPS)">
```bash
apt-get update
apt-get install -y git curl ca-certificates
curl -fsSL https://get.docker.com | sh
```
## 2) Install Docker (on the VPS)
Verify:
```bash
apt-get update
apt-get install -y git curl ca-certificates
curl -fsSL https://get.docker.com | sh
```
```bash
docker --version
docker compose version
```
Verify:
</Step>
```bash
docker --version
docker compose version
```
<Step title="Clone the OpenClaw repository">
```bash
git clone https://github.com/openclaw/openclaw.git
cd openclaw
```
---
This guide assumes you will build a custom image to guarantee binary persistence.
## 3) Clone the OpenClaw repository
</Step>
```bash
git clone https://github.com/openclaw/openclaw.git
cd openclaw
```
<Step title="Create persistent host directories">
Docker containers are ephemeral.
All long-lived state must live on the host.
This guide assumes you will build a custom image to guarantee binary persistence.
```bash
mkdir -p /root/.openclaw/workspace
---
# Set ownership to the container user (uid 1000):
chown -R 1000:1000 /root/.openclaw
```
## 4) Create persistent host directories
</Step>
Docker containers are ephemeral.
All long-lived state must live on the host.
<Step title="Configure environment variables">
Create `.env` in the repository root.
```bash
mkdir -p /root/.openclaw/workspace
```bash
OPENCLAW_IMAGE=openclaw:latest
OPENCLAW_GATEWAY_TOKEN=change-me-now
OPENCLAW_GATEWAY_BIND=lan
OPENCLAW_GATEWAY_PORT=18789
# Set ownership to the container user (uid 1000):
chown -R 1000:1000 /root/.openclaw
```
OPENCLAW_CONFIG_DIR=/root/.openclaw
OPENCLAW_WORKSPACE_DIR=/root/.openclaw/workspace
---
GOG_KEYRING_PASSWORD=change-me-now
XDG_CONFIG_HOME=/home/node/.openclaw
```
## 5) Configure environment variables
Generate strong secrets:
Create `.env` in the repository root.
```bash
openssl rand -hex 32
```
```bash
OPENCLAW_IMAGE=openclaw:latest
OPENCLAW_GATEWAY_TOKEN=change-me-now
OPENCLAW_GATEWAY_BIND=lan
OPENCLAW_GATEWAY_PORT=18789
**Do not commit this file.**
OPENCLAW_CONFIG_DIR=/root/.openclaw
OPENCLAW_WORKSPACE_DIR=/root/.openclaw/workspace
</Step>
GOG_KEYRING_PASSWORD=change-me-now
XDG_CONFIG_HOME=/home/node/.openclaw
```
<Step title="Docker Compose configuration">
Create or update `docker-compose.yml`.
Generate strong secrets:
```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 VPS; 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",
]
```
```bash
openssl rand -hex 32
```
`--allow-unconfigured` is only for bootstrap convenience, it is not a replacement for a proper gateway configuration. Still set auth (`gateway.auth.token` or password) and use safe bind settings for your deployment.
**Do not commit this file.**
</Step>
---
<Step title="Shared Docker VM runtime steps">
Use the shared runtime guide for the common Docker host flow:
## 6) Docker Compose configuration
- [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)
Create or update `docker-compose.yml`.
</Step>
```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 VPS; 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",
]
```
<Step title="Hetzner-specific access">
After the shared build and launch steps, tunnel from your laptop:
`--allow-unconfigured` is only for bootstrap convenience, it is not a replacement for a proper gateway configuration. Still set auth (`gateway.auth.token` or password) and use safe bind settings for your deployment.
```bash
ssh -N -L 18789:127.0.0.1:18789 root@YOUR_VPS_IP
```
---
Open:
## 7) Shared Docker VM runtime steps
`http://127.0.0.1:18789/`
Use the shared runtime guide for the common Docker host flow:
Paste your gateway token.
- [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)
---
## 8) Hetzner-specific access
After the shared build and launch steps, tunnel from your laptop:
```bash
ssh -N -L 18789:127.0.0.1:18789 root@YOUR_VPS_IP
```
Open:
`http://127.0.0.1:18789/`
Paste your gateway token.
---
</Step>
</Steps>
The shared persistence map lives in [Docker VM Runtime](/install/docker-vm-runtime#what-persists-where).