revert: Switch back to tsc for compiling.

This commit is contained in:
cpojer
2026-01-31 18:31:49 +09:00
parent e25fedf932
commit 76361ae3ab
36 changed files with 527 additions and 843 deletions

View File

@@ -57,7 +57,7 @@ primary_region = "iad"
NODE_OPTIONS = "--max-old-space-size=1536"
[processes]
app = "node dist/index.mjs gateway --allow-unconfigured --port 3000 --bind lan"
app = "node dist/index.js gateway --allow-unconfigured --port 3000 --bind lan"
[http_service]
internal_port = 3000
@@ -78,13 +78,13 @@ primary_region = "iad"
**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 |
## 3) Set secrets
@@ -104,6 +104,7 @@ fly secrets set DISCORD_BOT_TOKEN=MTQ...
```
**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.
@@ -117,12 +118,14 @@ fly deploy
First deploy builds the Docker image (~2-3 minutes). Subsequent deploys are faster.
After deployment, verify:
```bash
fly status
fly logs
```
You should see:
```
[gateway] listening on ws://0.0.0.0:3000 (PID xxx)
[discord] logged in to discord as xxx
@@ -137,6 +140,7 @@ fly ssh console
```
Create the config directory and file:
```bash
mkdir -p /data
cat > /data/openclaw.json << 'EOF'
@@ -194,12 +198,14 @@ EOF
**Note:** With `OPENCLAW_STATE_DIR=/data`, the config path is `/data/openclaw.json`.
**Note:** The Discord token can come from either:
- 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.
Restart to apply:
```bash
exit
fly machine restart <machine-id>
@@ -210,6 +216,7 @@ fly machine restart <machine-id>
### Control UI
Open in browser:
```bash
fly open
```
@@ -250,12 +257,14 @@ Fly can't reach the gateway on the configured port.
Container keeps restarting or getting killed. Signs: `SIGABRT`, `v8::internal::Runtime_AllocateInYoungGeneration`, or silent restarts.
**Fix:** Increase memory in `fly.toml`:
```toml
[[vm]]
memory = "2048mb"
```
Or update an existing machine:
```bash
fly machine update <machine-id> --vm-memory 2048 -y
```
@@ -269,6 +278,7 @@ Gateway refuses to start with "already running" errors.
This happens when the container restarts but the PID lock file persists on the volume.
**Fix:** Delete the lock file:
```bash
fly ssh console --command "rm -f /data/gateway.*.lock"
fly machine restart <machine-id>
@@ -281,6 +291,7 @@ The lock file is at `/data/gateway.*.lock` (not in a subdirectory).
If using `--allow-unconfigured`, the gateway creates a minimal config. Your custom config at `/data/openclaw.json` should be read on restart.
Verify the config exists:
```bash
fly ssh console --command "cat /data/openclaw.json"
```
@@ -299,6 +310,7 @@ fly sftp shell
```
**Note:** `fly sftp` may fail if the file already exists. Delete first:
```bash
fly ssh console --command "rm /data/openclaw.json"
```
@@ -332,10 +344,10 @@ If you need to change the startup command without a full redeploy:
fly machines list
# Update command
fly machine update <machine-id> --command "node dist/index.mjs gateway --port 3000 --bind lan" -y
fly machine update <machine-id> --command "node dist/index.js gateway --port 3000 --bind lan" -y
# Or with memory increase
fly machine update <machine-id> --vm-memory 2048 --command "node dist/index.mjs gateway --port 3000 --bind lan" -y
fly machine update <machine-id> --vm-memory 2048 --command "node dist/index.js gateway --port 3000 --bind lan" -y
```
**Note:** After `fly deploy`, the machine command may reset to what's in `fly.toml`. If you made manual changes, re-apply them after deploy.
@@ -381,6 +393,7 @@ fly ips allocate-v6 --private -a my-openclaw
```
After this, `fly ips list` should show only a `private` type IP:
```
VERSION IP TYPE REGION
v6 fdaa:x:x:x:x::x private global
@@ -391,6 +404,7 @@ v6 fdaa:x:x:x:x::x private global
Since there's no public URL, use one of these methods:
**Option 1: Local proxy (simplest)**
```bash
# Forward local port 3000 to the app
fly proxy 3000:3000 -a my-openclaw
@@ -399,6 +413,7 @@ fly proxy 3000:3000 -a my-openclaw
```
**Option 2: WireGuard VPN**
```bash
# Create WireGuard config (one-time)
fly wireguard create
@@ -408,6 +423,7 @@ fly wireguard create
```
**Option 3: SSH only**
```bash
fly ssh console -a my-openclaw
```
@@ -421,6 +437,7 @@ If you need webhook callbacks (Twilio, Telnyx, etc.) without public exposure:
3. **Outbound-only** - Some providers (Twilio) work fine for outbound calls without webhooks
Example voice-call config with ngrok:
```json
{
"plugins": {
@@ -441,12 +458,12 @@ The ngrok tunnel runs inside the container and provides a public webhook URL wit
### Security benefits
| Aspect | Public | Private |
|--------|--------|---------|
| Internet scanners | Discoverable | Hidden |
| Direct attacks | Possible | Blocked |
| Control UI access | Browser | Proxy/VPN |
| Webhook delivery | Direct | Via tunnel |
| Aspect | Public | Private |
| ----------------- | ------------ | ---------- |
| Internet scanners | Discoverable | Hidden |
| Direct attacks | Possible | Blocked |
| Control UI access | Browser | Proxy/VPN |
| Webhook delivery | Direct | Via tunnel |
## Notes
@@ -459,6 +476,7 @@ The ngrok tunnel runs inside the container and provides a public webhook URL wit
## Cost
With the recommended config (`shared-cpu-2x`, 2GB RAM):
- ~$10-15/month depending on usage
- Free tier includes some allowance

View File

@@ -1,5 +1,5 @@
---
summary: "Run OpenClaw Gateway 24/7 on a GCP Compute Engine VM (Docker) with durable state"
summary: 'Run OpenClaw Gateway 24/7 on a GCP Compute Engine VM (Docker) with durable state'
read_when:
- You want OpenClaw running 24/7 on GCP
- You want a production-grade, always-on Gateway on your own VM
@@ -25,6 +25,7 @@ Pricing varies by machine type and region; pick the smallest VM that fits your w
- Access the Control UI from your laptop via an SSH tunnel
The Gateway can be accessed via:
- SSH port forwarding from your laptop
- Direct port exposure if you manage firewalling and tokens yourself
@@ -36,14 +37,14 @@ For the generic Docker flow, see [Docker](/install/docker).
## Quick path (experienced operators)
1) Create GCP project + enable Compute Engine API
2) Create Compute Engine VM (e2-small, Debian 12, 20GB)
3) SSH into the VM
4) Install Docker
5) Clone OpenClaw repository
6) Create persistent host directories
7) Configure `.env` and `docker-compose.yml`
8) Bake required binaries, build, and launch
1. Create GCP project + enable Compute Engine API
2. Create Compute Engine VM (e2-small, Debian 12, 20GB)
3. SSH into the VM
4. Install Docker
5. Clone OpenClaw repository
6. Create persistent host directories
7. Configure `.env` and `docker-compose.yml`
8. Bake required binaries, build, and launch
---
@@ -112,9 +113,9 @@ gcloud services enable compute.googleapis.com
**Machine types:**
| Type | Specs | Cost | Notes |
|------|-------|------|-------|
| e2-small | 2 vCPU, 2GB RAM | ~$12/mo | Recommended |
| Type | Specs | Cost | Notes |
| -------- | ------------------------ | ------------------ | ------------------ |
| e2-small | 2 vCPU, 2GB RAM | ~$12/mo | Recommended |
| e2-micro | 2 vCPU (shared), 1GB RAM | Free tier eligible | May OOM under load |
**CLI:**
@@ -263,20 +264,20 @@ services:
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"
- '127.0.0.1:${OPENCLAW_GATEWAY_PORT}:18789'
# Optional: only if you run iOS/Android nodes against this VM and need Canvas host.
# If you expose this publicly, read /gateway/security and firewall accordingly.
# - "18793:18793"
command:
[
"node",
"dist/index.mjs",
"gateway",
"--bind",
"${OPENCLAW_GATEWAY_BIND}",
"--port",
"${OPENCLAW_GATEWAY_PORT}"
'node',
'dist/index.js',
'gateway',
'--bind',
'${OPENCLAW_GATEWAY_BIND}',
'--port',
'${OPENCLAW_GATEWAY_PORT}',
]
```
@@ -290,6 +291,7 @@ Anything installed at runtime will be lost on restart.
All external binaries required by skills must be installed at image build time.
The examples below show three common binaries only:
- `gog` for Gmail access
- `goplaces` for Google Places
- `wacli` for WhatsApp
@@ -298,6 +300,7 @@ These are examples, not a complete list.
You may install as many binaries as needed using the same pattern.
If you add new skills later that depend on additional binaries, you must:
1. Update the Dockerfile
2. Rebuild the image
3. Restart the containers
@@ -338,7 +341,7 @@ RUN pnpm ui:build
ENV NODE_ENV=production
CMD ["node","dist/index.mjs"]
CMD ["node","dist/index.js"]
```
---
@@ -403,18 +406,18 @@ Paste your gateway token.
OpenClaw runs in Docker, but Docker is not the source of truth.
All long-lived state must survive restarts, rebuilds, and reboots.
| Component | Location | Persistence mechanism | Notes |
|---|---|---|---|
| Gateway config | `/home/node/.openclaw/` | Host volume mount | Includes `openclaw.json`, tokens |
| Model auth profiles | `/home/node/.openclaw/` | Host volume mount | OAuth tokens, API keys |
| Skill configs | `/home/node/.openclaw/skills/` | Host volume mount | Skill-level state |
| Agent workspace | `/home/node/.openclaw/workspace/` | Host volume mount | Code and agent artifacts |
| WhatsApp session | `/home/node/.openclaw/` | Host volume mount | Preserves QR login |
| Gmail keyring | `/home/node/.openclaw/` | Host volume + password | Requires `GOG_KEYRING_PASSWORD` |
| External binaries | `/usr/local/bin/` | Docker image | Must be baked at build time |
| Node runtime | Container filesystem | Docker image | Rebuilt every image build |
| OS packages | Container filesystem | Docker image | Do not install at runtime |
| Docker container | Ephemeral | Restartable | Safe to destroy |
| Component | Location | Persistence mechanism | Notes |
| ------------------- | --------------------------------- | ---------------------- | -------------------------------- |
| Gateway config | `/home/node/.openclaw/` | Host volume mount | Includes `openclaw.json`, tokens |
| Model auth profiles | `/home/node/.openclaw/` | Host volume mount | OAuth tokens, API keys |
| Skill configs | `/home/node/.openclaw/skills/` | Host volume mount | Skill-level state |
| Agent workspace | `/home/node/.openclaw/workspace/` | Host volume mount | Code and agent artifacts |
| WhatsApp session | `/home/node/.openclaw/` | Host volume mount | Preserves QR login |
| Gmail keyring | `/home/node/.openclaw/` | Host volume + password | Requires `GOG_KEYRING_PASSWORD` |
| External binaries | `/usr/local/bin/` | Docker image | Must be baked at build time |
| Node runtime | Container filesystem | Docker image | Rebuilt every image build |
| OS packages | Container filesystem | Docker image | Do not install at runtime |
| Docker container | Ephemeral | Restartable | Safe to destroy |
---
@@ -473,6 +476,7 @@ For personal use, your default user account works fine.
For automation or CI/CD pipelines, create a dedicated service account with minimal permissions:
1. Create a service account:
```bash
gcloud iam service-accounts create openclaw-deploy \
--display-name="OpenClaw Deployment"

View File

@@ -1,5 +1,5 @@
---
summary: "Run OpenClaw Gateway 24/7 on a cheap Hetzner VPS (Docker) with durable state and baked-in binaries"
summary: 'Run OpenClaw Gateway 24/7 on a cheap Hetzner VPS (Docker) with durable state and baked-in binaries'
read_when:
- You want OpenClaw running 24/7 on a cloud VPS (not your laptop)
- You want a production-grade, always-on Gateway on your own VPS
@@ -10,6 +10,7 @@ read_when:
# OpenClaw on Hetzner (Docker, Production VPS Guide)
## Goal
Run a persistent OpenClaw Gateway on a Hetzner VPS using Docker, with durable state, baked-in binaries, and safe restart behavior.
If you want “OpenClaw 24/7 for ~$5”, this is the simplest reliable setup.
@@ -24,6 +25,7 @@ Hetzner pricing changes; pick the smallest Debian/Ubuntu VPS and scale up if you
- Access the Control UI from your laptop via an SSH tunnel
The Gateway can be accessed via:
- SSH port forwarding from your laptop
- Direct port exposure if you manage firewalling and tokens yourself
@@ -35,29 +37,29 @@ For the generic Docker flow, see [Docker](/install/docker).
## Quick path (experienced operators)
1) Provision Hetzner VPS
2) Install Docker
3) Clone OpenClaw repository
4) Create persistent host directories
5) Configure `.env` and `docker-compose.yml`
6) Bake required binaries into the image
7) `docker compose up -d`
8) Verify persistence and Gateway access
1. Provision Hetzner VPS
2. Install Docker
3. Clone OpenClaw repository
4. Create persistent host directories
5. Configure `.env` and `docker-compose.yml`
6. Bake required binaries into the image
7. `docker compose up -d`
8. Verify persistence and Gateway access
---
## What you need
- Hetzner VPS with root access
- SSH access from your laptop
- Basic comfort with SSH + copy/paste
- ~20 minutes
- Docker and Docker Compose
- Model auth credentials
- Optional provider credentials
- WhatsApp QR
- Telegram bot token
- Gmail OAuth
- Hetzner VPS with root access
- SSH access from your laptop
- Basic comfort with SSH + copy/paste
- ~20 minutes
- Docker and Docker Compose
- Model auth credentials
- Optional provider credentials
- WhatsApp QR
- Telegram bot token
- Gmail OAuth
---
@@ -175,20 +177,20 @@ services:
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"
- '127.0.0.1:${OPENCLAW_GATEWAY_PORT}:18789'
# Optional: only if you run iOS/Android nodes against this VPS and need Canvas host.
# If you expose this publicly, read /gateway/security and firewall accordingly.
# - "18793:18793"
command:
[
"node",
"dist/index.mjs",
"gateway",
"--bind",
"${OPENCLAW_GATEWAY_BIND}",
"--port",
"${OPENCLAW_GATEWAY_PORT}"
'node',
'dist/index.js',
'gateway',
'--bind',
'${OPENCLAW_GATEWAY_BIND}',
'--port',
'${OPENCLAW_GATEWAY_PORT}',
]
```
@@ -202,6 +204,7 @@ Anything installed at runtime will be lost on restart.
All external binaries required by skills must be installed at image build time.
The examples below show three common binaries only:
- `gog` for Gmail access
- `goplaces` for Google Places
- `wacli` for WhatsApp
@@ -210,6 +213,7 @@ These are examples, not a complete list.
You may install as many binaries as needed using the same pattern.
If you add new skills later that depend on additional binaries, you must:
1. Update the Dockerfile
2. Rebuild the image
3. Restart the containers
@@ -250,7 +254,7 @@ RUN pnpm ui:build
ENV NODE_ENV=production
CMD ["node","dist/index.mjs"]
CMD ["node","dist/index.js"]
```
---
@@ -311,15 +315,15 @@ Paste your gateway token.
OpenClaw runs in Docker, but Docker is not the source of truth.
All long-lived state must survive restarts, rebuilds, and reboots.
| Component | Location | Persistence mechanism | Notes |
|---|---|---|---|
| Gateway config | `/home/node/.openclaw/` | Host volume mount | Includes `openclaw.json`, tokens |
| Model auth profiles | `/home/node/.openclaw/` | Host volume mount | OAuth tokens, API keys |
| Skill configs | `/home/node/.openclaw/skills/` | Host volume mount | Skill-level state |
| Agent workspace | `/home/node/.openclaw/workspace/` | Host volume mount | Code and agent artifacts |
| WhatsApp session | `/home/node/.openclaw/` | Host volume mount | Preserves QR login |
| Gmail keyring | `/home/node/.openclaw/` | Host volume + password | Requires `GOG_KEYRING_PASSWORD` |
| External binaries | `/usr/local/bin/` | Docker image | Must be baked at build time |
| Node runtime | Container filesystem | Docker image | Rebuilt every image build |
| OS packages | Container filesystem | Docker image | Do not install at runtime |
| Docker container | Ephemeral | Restartable | Safe to destroy |
| Component | Location | Persistence mechanism | Notes |
| ------------------- | --------------------------------- | ---------------------- | -------------------------------- |
| Gateway config | `/home/node/.openclaw/` | Host volume mount | Includes `openclaw.json`, tokens |
| Model auth profiles | `/home/node/.openclaw/` | Host volume mount | OAuth tokens, API keys |
| Skill configs | `/home/node/.openclaw/skills/` | Host volume mount | Skill-level state |
| Agent workspace | `/home/node/.openclaw/workspace/` | Host volume mount | Code and agent artifacts |
| WhatsApp session | `/home/node/.openclaw/` | Host volume mount | Preserves QR login |
| Gmail keyring | `/home/node/.openclaw/` | Host volume + password | Requires `GOG_KEYRING_PASSWORD` |
| External binaries | `/usr/local/bin/` | Docker image | Must be baked at build time |
| Node runtime | Container filesystem | Docker image | Rebuilt every image build |
| OS packages | Container filesystem | Docker image | Do not install at runtime |
| Docker container | Ephemeral | Restartable | Safe to destroy |