Run a persistent CoderClaw Gateway on a Hetzner VPS using Docker, with durable state, baked-in binaries, and safe restart behavior.
If you want “CoderClaw 24/7 for ~$5”, this is the simplest reliable setup. Hetzner pricing changes; pick the smallest Debian/Ubuntu VPS and scale up if you hit OOMs.
~/.coderclaw + ~/.coderclaw/workspace on the host (survives restarts/rebuilds)The Gateway can be accessed via:
This guide assumes Ubuntu or Debian on Hetzner.
If you are on another Linux VPS, map packages accordingly.
For the generic Docker flow, see Docker.
.env and docker-compose.ymldocker compose up -dCreate an Ubuntu or Debian VPS in Hetzner.
Connect as root:
ssh root@YOUR_VPS_IP
This guide assumes the VPS is stateful. Do not treat it as disposable infrastructure.
apt-get update
apt-get install -y git curl ca-certificates
curl -fsSL https://get.docker.com | sh
Verify:
docker --version
docker compose version
git clone https://github.com/SeanHogg/coderClaw.git
cd coderClaw
This guide assumes you will build a custom image to guarantee binary persistence.
Docker containers are ephemeral. All long-lived state must live on the host.
mkdir -p /root/.coderclaw/workspace
# Set ownership to the container user (uid 1000):
chown -R 1000:1000 /root/.coderclaw
Create .env in the repository root.
CODERCLAW_IMAGE=coderclaw:latest
CODERCLAW_GATEWAY_TOKEN=change-me-now
CODERCLAW_GATEWAY_BIND=lan
CODERCLAW_GATEWAY_PORT=18789
CODERCLAW_CONFIG_DIR=/root/.coderclaw
CODERCLAW_WORKSPACE_DIR=/root/.coderclaw/workspace
GOG_KEYRING_PASSWORD=change-me-now
XDG_CONFIG_HOME=/home/node/.coderclaw
Generate strong secrets:
openssl rand -hex 32
Do not commit this file.
Create or update docker-compose.yml.
services:
coderclaw-gateway:
image: ${CODERCLAW_IMAGE}
build: .
restart: unless-stopped
env_file:
- .env
environment:
- HOME=/home/node
- NODE_ENV=production
- TERM=xterm-256color
- CODERCLAW_GATEWAY_BIND=${CODERCLAW_GATEWAY_BIND}
- CODERCLAW_GATEWAY_PORT=${CODERCLAW_GATEWAY_PORT}
- CODERCLAW_GATEWAY_TOKEN=${CODERCLAW_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:
- ${CODERCLAW_CONFIG_DIR}:/home/node/.coderclaw
- ${CODERCLAW_WORKSPACE_DIR}:/home/node/.coderclaw/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:${CODERCLAW_GATEWAY_PORT}:18789"
command:
[
"node",
"dist/index.js",
"gateway",
"--bind",
"${CODERCLAW_GATEWAY_BIND}",
"--port",
"${CODERCLAW_GATEWAY_PORT}",
"--allow-unconfigured",
]
--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.
Installing binaries inside a running container is a trap. 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 accessgoplaces for Google Placeswacli for WhatsAppThese 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:
Example Dockerfile
FROM node:22-bookworm
RUN apt-get update && apt-get install -y socat && rm -rf /var/lib/apt/lists/*
# Example binary 1: Gmail CLI
RUN curl -L https://github.com/steipete/gog/releases/latest/download/gog_Linux_x86_64.tar.gz \
| tar -xz -C /usr/local/bin && chmod +x /usr/local/bin/gog
# Example binary 2: Google Places CLI
RUN curl -L https://github.com/steipete/goplaces/releases/latest/download/goplaces_Linux_x86_64.tar.gz \
| tar -xz -C /usr/local/bin && chmod +x /usr/local/bin/goplaces
# Example binary 3: WhatsApp CLI
RUN curl -L https://github.com/steipete/wacli/releases/latest/download/wacli_Linux_x86_64.tar.gz \
| tar -xz -C /usr/local/bin && 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"]
docker compose build
docker compose up -d coderclaw-gateway
Verify binaries:
docker compose exec coderclaw-gateway which gog
docker compose exec coderclaw-gateway which goplaces
docker compose exec coderclaw-gateway which wacli
Expected output:
/usr/local/bin/gog
/usr/local/bin/goplaces
/usr/local/bin/wacli
docker compose logs -f coderclaw-gateway
Success:
[gateway] listening on ws://0.0.0.0:18789
From your laptop:
ssh -N -L 18789:127.0.0.1:18789 root@YOUR_VPS_IP
Open:
http://127.0.0.1:18789/
Paste your gateway token.
CoderClaw 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/.coderclaw/ |
Host volume mount | Includes coderclaw.json, tokens |
| Model auth profiles | /home/node/.coderclaw/ |
Host volume mount | OAuth tokens, API keys |
| Skill configs | /home/node/.coderclaw/skills/ |
Host volume mount | Skill-level state |
| Agent workspace | /home/node/.coderclaw/workspace/ |
Host volume mount | Code and agent artifacts |
| WhatsApp session | /home/node/.coderclaw/ |
Host volume mount | Preserves QR login |
| Gmail keyring | /home/node/.coderclaw/ |
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 |
For teams preferring infrastructure-as-code workflows, a community-maintained Terraform setup provides:
Repositories:
This approach complements the Docker setup above with reproducible deployments, version-controlled infrastructure, and automated disaster recovery.
Note: Community-maintained. For issues or contributions, see the repository links above.