docs(hosting): fix unsafe deployment instructions

This commit is contained in:
Peter Steinberger
2026-08-12 20:38:51 -07:00
parent 2c3e537cb8
commit bf7196b370
22 changed files with 287 additions and 163 deletions
+1
View File
@@ -265,6 +265,7 @@ Set up an Azure Linux VM with the Azure CLI, apply Network Security Group (NSG)
After onboarding completes:
```bash
openclaw doctor --json
openclaw gateway status
```
+6 -2
View File
@@ -190,10 +190,14 @@ Create a bot with [@BotFather](https://t.me/botfather) (`/newbot`), copy the
token, then configure OpenClaw from the sandbox SSH session:
```bash
openclaw config set channels.telegram.enabled true
openclaw config set channels.telegram.botToken YOUR_BOT_TOKEN
export TELEGRAM_BOT_TOKEN="<bot-token>"
openclaw channels add --channel telegram --use-env
```
Also store `TELEGRAM_BOT_TOKEN=<bot-token>` in `~/.openclaw/.env` so the
background Gateway receives it after a restart. `--use-env` validates the token
without copying it into `openclaw.json`.
Restart the Gateway (see above), send your bot a DM, then approve the pairing
code it reports:
+10 -6
View File
@@ -75,11 +75,11 @@ DigitalOcean is a straightforward paid VPS path. For cheaper or free options:
<Step title="Add swap (recommended for 1 GB Droplets)">
```bash
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
```
</Step>
@@ -130,9 +130,13 @@ These survive Droplet reboots. To take a portable snapshot:
```bash
openclaw backup create
openclaw backup restore <archive.tar.gz> --target <fresh-directory>
```
DigitalOcean snapshots back up the whole Droplet; `openclaw backup create` is portable across hosts.
DigitalOcean snapshots back up the whole Droplet; `openclaw backup create` is
portable across hosts. Restore verifies and extracts into a fresh staging
directory; activation is a separate offline step. See [Restore a full archive](/install/backups#restore-a-full-archive)
for the rollback warnings and activation sequence.
## 1 GB RAM tips
+19 -50
View File
@@ -20,61 +20,30 @@ The examples below cover three binaries only, alphabetically:
- `goplaces` for Google Places
- `wacli` for WhatsApp
These are examples, not a complete list. Install as many binaries as your
skills need using the same pattern. When you add a skill that needs a new
binary later:
These are examples, not a complete list. Docker Compose builds the repo-root
`Dockerfile`, so extend that file rather than creating a standalone example or
replacing its contents. The repository Dockerfile has required
`workspace-deps`, build, runtime-assets, and final runtime stages. Its manifest
extraction covers the `packages/*` and selected `extensions/*` workspaces before
`pnpm install --frozen-lockfile`.
1. Update the Dockerfile.
2. Rebuild the image.
3. Restart the containers.
For Debian packages, prefer the existing build argument:
**Example Dockerfile**
```dockerfile
FROM node:24-bookworm
RUN apt-get update && apt-get install -y socat && rm -rf /var/lib/apt/lists/*
# Example binary 1: Gmail CLI (gogcli — installs as `gog`)
# Copy the current Linux asset URL from https://github.com/steipete/gogcli/releases
RUN curl -L https://github.com/steipete/gogcli/releases/latest/download/gogcli_linux_amd64.tar.gz \
| tar -xzO gog > /usr/local/bin/gog; \
chmod +x /usr/local/bin/gog
# Example binary 2: Google Places CLI
# Copy the current Linux asset URL from https://github.com/steipete/goplaces/releases
RUN curl -L https://github.com/steipete/goplaces/releases/latest/download/goplaces_linux_amd64.tar.gz \
| tar -xzO goplaces > /usr/local/bin/goplaces; \
chmod +x /usr/local/bin/goplaces
# Example binary 3: WhatsApp CLI
# Copy the current Linux asset URL from https://github.com/steipete/wacli/releases
RUN curl -L https://github.com/steipete/wacli/releases/latest/download/wacli-linux-amd64.tar.gz \
| tar -xzO wacli > /usr/local/bin/wacli; \
chmod +x /usr/local/bin/wacli
# Add more binaries below using the same pattern
WORKDIR /app
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./
COPY ui/package.json ./ui/package.json
COPY scripts ./scripts
RUN corepack enable
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
RUN pnpm ui:install
RUN pnpm ui:build
ENV NODE_ENV=production
CMD ["node","dist/index.js"]
```bash
export OPENCLAW_IMAGE_APT_PACKAGES="socat"
```
For downloaded release binaries such as `gog`, `goplaces`, or `wacli`, add the
download and install commands to the repo-root `Dockerfile` final runtime stage,
after its package-install blocks and before `USER node`. Preserve the existing
non-root uid 1000 setup, `tini` entrypoint, health check, and `openclaw` symlink.
Then rebuild and restart the containers.
<Note>
The URLs above are examples. For ARM-based VMs, choose the `arm64` assets. For reproducible builds, pin versioned release URLs.
The repository Dockerfile digest-pins its Node and Bun base images. Keep those
reviewed pins instead of changing them to floating `FROM node:24-bookworm`
references. For ARM-based VMs, choose `arm64` release assets for extra binaries;
for reproducible builds, use versioned asset URLs and verify their checksums.
</Note>
## Build and launch
+17 -18
View File
@@ -180,6 +180,13 @@ After doctor finishes, restart the gateway container with its default command.
In Kubernetes, run the same command in a one-off Job or debug pod mounted to the
same PVC, then restart the Deployment or StatefulSet.
After the container is running again, run the read-only deployment preflight
against the same mounted state:
```bash
docker compose run --rm openclaw-cli doctor --json
```
### Environment variables
Optional variables accepted by `scripts/docker/setup.sh` (and, for the gateway container, by `docker-compose.yml` directly):
@@ -514,25 +521,17 @@ If you installed from the older `scripts/shell-helpers/clawdock-helpers.sh` path
</Accordion>
<Accordion title="Faster rebuilds">
Order your Dockerfile so dependency layers are cached, avoiding a `pnpm install` rerun unless lockfiles change:
Use the repo-root `Dockerfile` instead of replacing it with a shortened
single-stage example. Its `workspace-deps` stage extracts the package
manifests required by `pnpm-workspace.yaml`, then the build stage copies
those manifests before `pnpm install --frozen-lockfile`. This keeps the
dependency layer cacheable without omitting `packages/*`, selected
`extensions/*`, or other required workspace metadata.
```dockerfile
FROM node:24-bookworm
RUN curl -fsSL https://bun.sh/install | bash
ENV PATH="/root/.bun/bin:${PATH}"
RUN corepack enable
WORKDIR /app
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./
COPY ui/package.json ./ui/package.json
COPY scripts ./scripts
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
RUN pnpm ui:install
RUN pnpm ui:build
ENV NODE_ENV=production
CMD ["node","dist/index.js"]
```
The same Dockerfile preserves the production runtime contract: digest-pinned
Node and Bun bases, non-root uid 1000, `tini`, the built-in health check, and
the `/usr/local/bin/openclaw` symlink. Dependabot refreshes the reviewed base
digests; do not replace them with floating `FROM node:24-bookworm` tags.
</Accordion>
+17 -1
View File
@@ -28,7 +28,7 @@ This guide assumes exe.dev's default **exeuntu** image. Map packages accordingly
Shelley, exe.dev's agent, can install OpenClaw from a prompt:
```text
Set up OpenClaw (https://docs.openclaw.ai/install) on this VM. Use the non-interactive and accept-risk flags for openclaw onboarding. Add the supplied auth or token as needed. Configure nginx to forward from the default port 18789 to the root location on the default enabled site config, making sure to enable Websocket support. Pairing is done by "openclaw devices list" and "openclaw devices approve <request id>". Make sure the dashboard shows that OpenClaw's health is OK. exe.dev handles forwarding from port 8000 to port 80/443 and HTTPS for us, so the final "reachable" should be <vm-name>.exe.xyz, without port specification.
Set up OpenClaw (https://docs.openclaw.ai/install) on this VM. Use the non-interactive and accept-risk flags for openclaw onboarding. Add the supplied auth or token as needed. Configure nginx to forward from the default port 18789 to the root location on the default enabled site config, making sure to enable Websocket support. Set gateway.controlUi.allowedOrigins to the exact https://<vm-name>.exe.xyz origin, and set gateway.trustedProxies to ["127.0.0.1"] because nginx connects to the Gateway over loopback and overwrites X-Forwarded-For. Pairing is done by "openclaw devices list" and "openclaw devices approve <request id>". Make sure the dashboard shows that OpenClaw's health is OK. exe.dev handles forwarding from port 8000 to port 80/443 and HTTPS for us, so the final "reachable" should be <vm-name>.exe.xyz, without port specification.
```
## Manual installation
@@ -103,6 +103,22 @@ Set up OpenClaw (https://docs.openclaw.ai/install) on this VM. Use the non-inter
</Step>
<Step title="Trust nginx and allow the public browser origin">
Configure the exact public origin and trust only the loopback nginx hop:
```bash
openclaw config set gateway.controlUi.allowedOrigins '["https://<vm-name>.exe.xyz"]' --strict-json
openclaw config set gateway.trustedProxies '["127.0.0.1"]' --strict-json
openclaw gateway restart
```
The browser origin check is fail-closed for public hostnames. The proxy
allowlist lets OpenClaw use nginx's overwritten `X-Forwarded-For` value
instead of treating every request as if it originated from the loopback
proxy. Keep this list limited to proxies you control.
</Step>
<Step title="Access OpenClaw and approve devices">
Open `https://<vm-name>.exe.xyz/` (see the Control UI output from onboarding). If it prompts for auth, paste the configured shared secret from the VM.
+43 -9
View File
@@ -180,15 +180,19 @@ This guide uses Debian on GCP Compute Engine. Ubuntu also works; map packages ac
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
HOME: /home/node
NODE_ENV: production
TERM: xterm-256color
OPENCLAW_STATE_DIR: /home/node/.openclaw
OPENCLAW_CONFIG_PATH: /home/node/.openclaw/openclaw.json
OPENCLAW_CONFIG_DIR: /home/node/.openclaw
OPENCLAW_WORKSPACE_DIR: /home/node/.openclaw/workspace
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
@@ -207,10 +211,40 @@ This guide uses Debian on GCP Compute Engine. Ubuntu also works; map packages ac
"${OPENCLAW_GATEWAY_PORT}",
"--allow-unconfigured",
]
openclaw-cli:
image: ${OPENCLAW_IMAGE}
network_mode: "service:openclaw-gateway"
env_file:
- .env
environment:
HOME: /home/node
TERM: xterm-256color
OPENCLAW_STATE_DIR: /home/node/.openclaw
OPENCLAW_CONFIG_PATH: /home/node/.openclaw/openclaw.json
OPENCLAW_CONFIG_DIR: /home/node/.openclaw
OPENCLAW_WORKSPACE_DIR: /home/node/.openclaw/workspace
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
stdin_open: true
tty: true
init: true
entrypoint: ["node", "dist/index.js"]
depends_on:
- openclaw-gateway
```
`--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.
The `.env` paths are host-side bind-mount sources. Both services override
those variables with `/home/node/...` paths inside the container so the
non-root `node` user never tries to write to a host-only path.
</Step>
<Step title="Shared Docker VM runtime steps">
+17 -9
View File
@@ -137,15 +137,19 @@ This guide assumes Ubuntu or Debian on Hetzner. On another Linux VPS, map packag
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
HOME: /home/node
NODE_ENV: production
TERM: xterm-256color
OPENCLAW_STATE_DIR: /home/node/.openclaw
OPENCLAW_CONFIG_PATH: /home/node/.openclaw/openclaw.json
OPENCLAW_CONFIG_DIR: /home/node/.openclaw
OPENCLAW_WORKSPACE_DIR: /home/node/.openclaw/workspace
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
@@ -166,6 +170,10 @@ This guide assumes Ubuntu or Debian on Hetzner. On another Linux VPS, map packag
]
```
The `.env` paths are host-side bind-mount sources. The service overrides
them with `/home/node/...` paths inside the container so the non-root
`node` user never tries to write to a host-only path.
`--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.
</Step>
+25 -13
View File
@@ -151,21 +151,24 @@ curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install.sh | bash -s -
### Containers and package managers
<CardGroup cols={2}>
<Card title="Docker" href="/install/docker" icon="container">
Containerized or headless deployments.
</Card>
<Card title="Podman" href="/install/podman" icon="container">
Rootless container alternative to Docker.
</Card>
<Card title="Nix" href="/install/nix" icon="snowflake">
Declarative install via Nix flake.
</Card>
<Card title="Ansible" href="/install/ansible" icon="server">
Automated fleet provisioning.
</Card>
<Card title="Bun" href="/install/bun" icon="zap">
Optional dependency installer and package-script runner.
</Card>
<Card title="ClawDock" href="/install/clawdock" icon="container">
Community Docker Compose setup and shell helpers.
</Card>
<Card title="Docker" href="/install/docker" icon="container">
Containerized or headless deployments.
</Card>
<Card title="Nix" href="/install/nix" icon="snowflake">
Declarative install via Nix flake.
</Card>
<Card title="Podman" href="/install/podman" icon="container">
Rootless container alternative to Docker.
</Card>
</CardGroup>
## Verify the install
@@ -194,20 +197,29 @@ template.
<Card title="Cloudflare" href="/install/cloudflare">
Experimental Worker + Container deployment.
</Card>
<Card title="VPS" href="/vps">
Pick a provider.
</Card>
<Card title="Docker VM" href="/install/docker-vm-runtime">
Shared Docker steps.
</Card>
<Card title="Kubernetes" href="/install/kubernetes">
K8s deployment.
</Card>
<Card title="macOS VM" href="/install/macos-vm">
Isolated local or hosted macOS deployment.
</Card>
<Card title="Upstash Box" href="/install/upstash">
Managed Linux host with SSH-tunneled access.
</Card>
<Card title="VPS" href="/vps">
Pick a provider.
</Card>
</CardGroup>
## Update, migrate, or uninstall
## Back up, update, migrate, or uninstall
<CardGroup cols={3}>
<Card title="Backups" href="/install/backups" icon="archive">
Create, verify, and restore state archives.
</Card>
<Card title="Updating" href="/install/updating" icon="refresh-cw">
Keep OpenClaw up to date.
</Card>
+2
View File
@@ -256,7 +256,9 @@ by default, plus git-checkout installs under the same prefix flow.
| `--npm` | Shortcut for npm method |
| `--git \| --github` | Shortcut for git method |
| `--git-dir \| --dir <path>` | Git checkout directory (default: `~/openclaw`) |
| `--no-git-update` | Skip `git pull` for an existing git checkout |
| `--version <ver>` | OpenClaw version or dist-tag (default: `latest`) |
| `--compatible-with <ver>` | Refuse a CLI that cannot modify config written by `<ver>` |
| `--node-version <ver>` | Node version (default: `24.15.0`; `22.22.3` on Linux ARMv7) |
| `--json` | Emit NDJSON events |
| `--onboard` | Run `openclaw onboard` after install |
+2 -2
View File
@@ -26,7 +26,7 @@ export <PROVIDER>_API_KEY="..."
./scripts/k8s/deploy.sh
kubectl port-forward svc/openclaw 18789:18789 -n openclaw
open http://localhost:18789
open http://127.0.0.1:18789
```
`deploy.sh` creates token auth by default. Retrieve the generated gateway token for the Control UI:
@@ -76,7 +76,7 @@ Add `--show-token` to either command to print the token to stdout for local test
```bash
kubectl port-forward svc/openclaw 18789:18789 -n openclaw
open http://localhost:18789
open http://127.0.0.1:18789
```
## What gets deployed
+10 -20
View File
@@ -127,32 +127,22 @@ Follow the onboarding prompts to set up your model provider (Anthropic, OpenAI,
## 7) Configure channels
Edit the config file:
Keep the Telegram token in the Gateway environment rather than copying it into
`openclaw.json`. Add `TELEGRAM_BOT_TOKEN=<bot-token>` to
`~/.openclaw/.env`, then load it in the current shell and add the channel:
```bash
nano ~/.openclaw/openclaw.json
export TELEGRAM_BOT_TOKEN="<bot-token>"
openclaw channels add --channel telegram --use-env
```
Add your channels:
```json5
{
channels: {
telegram: {
botToken: "YOUR_BOT_TOKEN",
},
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+15551234567"],
},
},
}
```
Then log in to WhatsApp (scan QR):
The managed Gateway reads the same state-directory `.env` after restart. For
WhatsApp, configure your allowlist and then scan the login QR code:
```bash
openclaw channels login
openclaw config set channels.whatsapp.dmPolicy allowlist
openclaw config set channels.whatsapp.allowFrom '["+15551234567"]' --strict-json
openclaw channels login --channel whatsapp
```
## 8) Run the VM headlessly
+23 -9
View File
@@ -42,15 +42,19 @@ Run `openclaw status` on the old machine to confirm your state directory path. C
<Steps>
<Step title="Stop the gateway and back up">
On the **old** machine, stop the gateway so files are not changing mid-copy, then archive:
On the **old** machine, stop the Gateway, then create and verify a portable
archive:
```bash
openclaw gateway stop
cd ~
tar -czf openclaw-state.tgz .openclaw
mkdir -p ~/Backups/openclaw
openclaw backup create --output ~/Backups/openclaw --verify
```
If you use multiple profiles (for example `~/.openclaw-work`), archive each separately.
Stop the Gateway before taking a machine-move snapshot. A raw copy of a
changing SQLite database can capture mismatched database and WAL files;
quiescing the Gateway also keeps the rest of the state tree stable. If you
use multiple profiles, run the command once with each profile selected.
</Step>
@@ -58,15 +62,25 @@ Run `openclaw status` on the old machine to confirm your state directory path. C
[Install](/install) the CLI (and Node if needed) on the new machine. It is fine if onboarding creates a fresh `~/.openclaw/` — you overwrite it next.
</Step>
<Step title="Copy state directory and workspace">
Transfer the archive via `scp`, `rsync -a`, or an external drive, then extract:
<Step title="Transfer and restore to staging">
Transfer the generated `.tar.gz` archive via `scp`, an external drive, or
another protected channel. On the new machine, restore it to a fresh
staging directory:
```bash
cd ~
tar -xzf openclaw-state.tgz
openclaw backup restore <archive.tar.gz> --target ~/openclaw-restored
```
Confirm hidden directories were included and file ownership matches the user that will run the gateway.
Restore never activates in place. With the Gateway stopped, use the
restored `manifest.json` mapping to move the state and workspace assets to
their recorded destinations, or point `OPENCLAW_STATE_DIR` at the restored
state asset. Confirm ownership matches the user that will run the Gateway.
<Warning>
Restoring older channel state can desynchronize ratcheting credentials such
as WhatsApp. Approvals and delivery/dedupe state also roll back, and plugin
`node_modules` trees must be reinstalled. See [Restore a full archive](/install/backups#restore-a-full-archive).
</Warning>
</Step>
+10 -1
View File
@@ -13,12 +13,21 @@ Deploy OpenClaw on Northflank with a one-click template and access it through th
1. Click [Deploy OpenClaw](https://northflank.com/stacks/deploy-openclaw) to open the template.
2. Create an [account on Northflank](https://app.northflank.com/signup) if you don't already have one.
3. Click **Deploy OpenClaw now**.
4. Set the required environment variable: `OPENCLAW_GATEWAY_TOKEN` (use a strong random value).
4. Set these required environment variables:
- `OPENCLAW_GATEWAY_TOKEN` (use a strong random value)
- `OPENCLAW_STATE_DIR=/data/.openclaw`
- `OPENCLAW_WORKSPACE_DIR=/data/workspace`
5. Click **Deploy stack** to build and run the OpenClaw template.
6. Wait for the deployment to complete, then click **View resources**.
7. Open the OpenClaw service.
8. Open the public OpenClaw URL at `/openclaw` and connect using the configured shared secret. This template uses `OPENCLAW_GATEWAY_TOKEN` by default; if you replace it with password auth, use that password instead.
From the Northflank shell, run the read-only deployment preflight:
```bash
openclaw doctor --json
```
## What you get
- Hosted OpenClaw Gateway + Control UI
+6
View File
@@ -91,6 +91,7 @@ Run a persistent OpenClaw Gateway on Oracle Cloud's **Always Free** ARM tier (up
openclaw config set gateway.tailscale.mode serve
openclaw config set gateway.trustedProxies '["127.0.0.1"]'
openclaw gateway install
systemctl --user restart openclaw-gateway.service
```
@@ -183,8 +184,13 @@ These survive reboots. To take a portable snapshot:
```bash
openclaw backup create
openclaw backup restore <archive.tar.gz> --target <fresh-directory>
```
Restore verifies and extracts into a fresh staging directory; activation is a
separate offline step. See [Restore a full archive](/install/backups#restore-a-full-archive)
for the rollback warnings and activation sequence.
## Fallback: SSH tunnel
If Tailscale Serve is not working, use an SSH tunnel from your local machine:
+8
View File
@@ -190,6 +190,14 @@ podman run --rm -it \
On SELinux hosts, add `,Z` to both bind mounts if Podman blocks access to the
mounted state.
After restarting the Gateway with the updated image, run the read-only
deployment preflight through the container-aware host CLI:
```bash
export OPENCLAW_CONTAINER=openclaw
openclaw doctor --json
```
## Useful commands
- **Container logs:** `podman logs -f openclaw`
+12 -3
View File
@@ -28,8 +28,8 @@ Deploy OpenClaw on Railway with a one-click template and access it through the w
- `OPENCLAW_GATEWAY_PORT=8080` (required -- must match the port in Public Networking)
- `OPENCLAW_GATEWAY_TOKEN` (required; treat as an admin secret)
- `OPENCLAW_STATE_DIR=/data/.openclaw` (recommended)
- `OPENCLAW_WORKSPACE_DIR=/data/workspace` (recommended)
- `OPENCLAW_STATE_DIR=/data/.openclaw` (required for persistent state)
- `OPENCLAW_WORKSPACE_DIR=/data/workspace` (required for a persistent workspace)
</Step>
@@ -45,6 +45,12 @@ Deploy OpenClaw on Railway with a one-click template and access it through the w
</Step>
</Steps>
From the Railway shell, run the read-only deployment preflight:
```bash
openclaw doctor --json
```
## What you get
- Hosted OpenClaw Gateway + Control UI
@@ -64,9 +70,12 @@ Export your state, config, auth profiles, and workspace:
```bash
openclaw backup create
openclaw backup restore <archive.tar.gz> --target <fresh-directory>
```
This creates a portable backup archive with OpenClaw state plus any configured workspace. See [Backup](/cli/backup) for details.
Restore verifies and extracts into a fresh staging directory; activation is a
separate offline step. See [Restore a full archive](/install/backups#restore-a-full-archive)
for the rollback warnings and activation sequence.
## Next steps
+5
View File
@@ -203,8 +203,13 @@ These survive reboots and benefit from SSD over SD card for both performance and
```bash
openclaw backup create
openclaw backup restore <archive.tar.gz> --target <fresh-directory>
```
Restore verifies and extracts into a fresh staging directory; activation is a
separate offline step. See [Restore a full archive](/install/backups#restore-a-full-archive)
for the rollback warnings and activation sequence.
## Troubleshooting
**Out of memory** -- Verify swap is active with `free -h`. Disable unused services (`sudo systemctl disable cups bluetooth avahi-daemon`). Use API-based models only.
+4 -1
View File
@@ -101,9 +101,12 @@ From the Render Dashboard shell, export state, config, auth profiles, and worksp
```bash
openclaw backup create
openclaw backup restore <archive.tar.gz> --target <fresh-directory>
```
This creates a portable backup archive. See [Backup](/cli/backup).
Restore verifies and extracts into a fresh staging directory; activation is a
separate offline step. See [Restore a full archive](/install/backups#restore-a-full-archive)
for the rollback warnings and activation sequence.
## Troubleshooting
+21 -8
View File
@@ -36,7 +36,10 @@ npx -y openclaw uninstall --all --yes --non-interactive
Flags: `--service`, `--state`, `--workspace`, `--app` select individual scopes; `--all` selects all four.
Manual steps (same result):
Manual steps provide a complete removal path, but a raw state-directory deletion
does not have the built-in uninstaller's workspace-preservation behavior. If
you want the equivalent of `openclaw uninstall --state`, preserve every
configured workspace before deleting state.
1. Stop the gateway service:
@@ -50,22 +53,32 @@ openclaw gateway stop
openclaw gateway uninstall
```
3. Delete state + config:
3. Decide whether to preserve the workspace.
`openclaw uninstall --state` deliberately preserves configured workspace
directories, including the default `~/.openclaw/workspace`. Before using the
manual `rm -rf` below, move any workspace you want to keep outside the state
directory. If you want to remove it too, no separate deletion is needed when it
lives inside the state directory.
4. Delete state + config:
```bash
rm -rf "${OPENCLAW_STATE_DIR:-$HOME/.openclaw}"
```
If you set `OPENCLAW_CONFIG_PATH` to a custom location outside the state dir, delete that file too.
If you want to keep a workspace inside the state dir, such as `~/.openclaw/workspace`, move it aside before running `rm -rf` or delete state contents selectively.
Restore any preserved workspace to its configured path after recreating the
parent directory, or update the workspace path in your next installation.
4. Delete your workspace (optional, removes agent files):
5. Delete a workspace stored outside the state directory only if you want to
remove its agent files too:
```bash
rm -rf ~/.openclaw/workspace
rm -rf /path/to/external/workspace
```
5. Remove the CLI install (pick the one you used):
6. Remove the CLI install (pick the one you used):
```bash
npm rm -g openclaw
@@ -73,7 +86,7 @@ pnpm remove -g openclaw
bun remove -g openclaw
```
6. If you installed the macOS app:
7. If you installed the macOS app:
```bash
rm -rf /Applications/OpenClaw.app
@@ -81,7 +94,7 @@ rm -rf /Applications/OpenClaw.app
Notes:
- If you used profiles (`--profile` / `OPENCLAW_PROFILE`), repeat step 3 for each state dir (defaults are `~/.openclaw-<profile>`).
- If you used profiles (`--profile` / `OPENCLAW_PROFILE`), repeat steps 3-4 for each state dir (defaults are `~/.openclaw-<profile>`).
- In remote mode, the state dir lives on the **gateway host**, so run steps 1-4 there too.
## Manual service removal (CLI not installed)
+18 -6
View File
@@ -481,12 +481,24 @@ Gateway and restore the verified pre-update filesystem, volume, or VM snapshot.
Preserve the current state separately before restoring because this removes
changes made after the snapshot.
Broad `openclaw backup create` archives support creation and verification, but
not in-place whole-archive activation. Extract a broad archive into a staging
directory and use its `manifest.json` source-to-archive mapping for an offline
restore. `openclaw backup sqlite restore` likewise writes a verified database
to a fresh target; activating that target remains an explicit offline operator
step.
Restore a broad archive to a fresh staging directory with the current CLI:
```bash
openclaw backup restore <archive.tar.gz> --target <fresh-directory>
```
The command verifies the archive and its SQLite databases before extraction.
Activation remains an explicit offline step: stop the Gateway, move the
restored asset tree into place or point `OPENCLAW_STATE_DIR` at the restored
state asset, run `openclaw doctor`, then restart.
Treat a state restore as time travel. Ratcheting channel credentials, especially
WhatsApp, can desynchronize and require relinking. Approvals and
delivery/dedupe state roll back too, and plugin `node_modules` trees are not
archived. See [Restore a full archive](/install/backups#restore-a-full-archive)
for the complete activation and recovery sequence. `openclaw backup sqlite
restore` likewise writes a verified database to a fresh target; activating that
target remains an explicit offline operator step.
### Verify the rollback
+11 -5
View File
@@ -48,18 +48,20 @@ sudo npm install -g openclaw
## Run onboarding
```bash
openclaw onboard --install-daemon
openclaw onboard --no-install-daemon
```
Follow the prompts. Copy the dashboard URL and token when onboarding finishes.
## Start the Gateway
Configure the Gateway for the Box network and start it in the background:
Keep the Gateway on loopback for the SSH tunnel, then start one unsupervised
process in the background:
```bash
openclaw config set gateway.bind lan
nohup openclaw gateway > gateway.log 2>&1 &
openclaw config set gateway.bind loopback
nohup openclaw gateway run > gateway.log 2>&1 &
openclaw doctor --json
```
With the SSH tunnel active, open the dashboard URL locally:
@@ -74,9 +76,13 @@ Set this command as the Box init script so the Gateway restarts when the Box
starts:
```bash
nohup openclaw gateway > gateway.log 2>&1 &
nohup openclaw gateway run > gateway.log 2>&1 &
```
Onboarding deliberately skips daemon installation in this guide. The Box init
script is the single owner of Gateway startup, so two processes do not contend
for the same lock and port.
## Troubleshooting
If SSH freezes during onboarding, reconnect with a clean SSH config and