Docker configuration and application setup for OpenClaw. Companion repository to openclaw-terraform-hetzner.
Note: This is a minimal, generic configuration with only essential skills activated. You're encouraged to customize it by adding ClawHub skills or creating your own custom skills (see Working with Skills).
┌──────────────┐ ┌──────────────────────┐
│ Laptop │──── git push ─────────▶│ GitHub │
│ (develop) │ │ (openclaw-config) │
│ │ └──────────────────────┘
│ │ build-and-push.sh
│ │───────────────────────▶ ┌──────────────────────┐
│ │ │ GHCR │
│ │ │ :latest :abc1234 │
│ │ └──────────────────────┘
│ │
│ │ make push-config ┌──────────────────────┐
│ │ make push-env │ Hetzner VPS │
│ │──── (infra repo) ──────▶│ ┌────────────────┐ │
│ │ make deploy │ │ Docker │ │
└──────────────┘ │ │ openclaw-gw │ │
│ └────────────────┘ │
│ :18789 (loopback) │
└──────────────────────┘
- Docker and Docker Compose on the VPS
- SSH access to the VPS (
ssh openclaw@VPS_IP) - The infra repo (
openclaw-terraform-hetzner) set up withconfig/inputs.shpointingCONFIG_DIRto this repo - API keys (see
docker/.env.examplefor the full list; secrets live in the infra repo'ssecrets/openclaw.env)
This repo is not cloned on the VPS. Instead, the infra repo's scripts copy specific files from your local checkout to the VPS:
| What | Pushed by | Lands at (VPS) |
|---|---|---|
docker/docker-compose.yml |
make bootstrap (once) |
~/openclaw/docker-compose.yml |
config/* (openclaw.json, etc.) |
make push-config |
~/.openclaw/ |
| Docker image | make deploy (pulls from GHCR) |
Docker image cache |
| Secrets | make push-env |
~/openclaw/.env |
Provisioning and bootstrap are handled by the infra repo. See its README.
- In the infra repo, set
CONFIG_DIRinconfig/inputs.shto point to this repo's directory - Log in to GHCR (one-time, on your laptop):
echo "$GHCR_PAT" | docker login ghcr.io -u YOUR_GITHUB_USERNAME --password-stdin
- Build and push the Docker image:
bash scripts/build-and-push.sh
- Run
make bootstrapfrom the infra repo — copiesdocker-compose.yml, config, and secrets to VPS - Run
make deployfrom the infra repo — pulls the Docker image from GHCR and starts the container - Complete Telegram pairing: open Telegram, find your bot, send
/start
There are two types of changes, and they have different workflows:
Config files are pushed to the VPS via SCP — no image rebuild needed.
edit → validate → commit → push → make push-config (infra repo)
- Edit files in
config/,skills/, orhooks/ - Validate:
bash scripts/validate-config.sh - Commit and push to GitHub
- From the infra repo:
make push-config(SCPs config to VPS and restarts)
Image changes require a rebuild and push to GHCR.
edit → commit → push → build-and-push.sh → make deploy (infra repo)
- Edit
docker/Dockerfile(e.g. bumpOPENCLAW_VERSION, add a binary) - Commit and push to GitHub
- Build and push image:
bash scripts/build-and-push.sh - From the infra repo:
make deploy(pulls new image from GHCR and restarts)
This repository includes a minimal set of generic skills in config/skills-manifest.txt. You can extend OpenClaw by adding ClawHub skills or creating custom skills.
ClawHub is the community skill registry for OpenClaw. To add a ClawHub skill:
- Find the skill at clawhub.ai (e.g.,
pdf,ms-office-suite,jira) - Add to manifest: Edit
config/skills-manifest.txtand add the skill name# PDF processing pdf - Rebuild and deploy:
bash scripts/build-and-push.sh # Then from infra repo: make deploy
The entrypoint.sh script auto-installs skills from the manifest on container startup via clawhub install.
Custom skills are user-defined commands or workflows. To create one:
-
Create the skill directory:
mkdir -p skills/my-skill
-
Write the skill manifest (
skills/my-skill/skill.json):{ "name": "my-skill", "version": "1.0.0", "description": "My custom skill", "commands": { "my-command": { "handler": "my-command.sh" } } } -
Write the handler (
skills/my-skill/my-command.sh):#!/bin/bash # Your custom logic here echo "Hello from my-skill!"
-
Make it executable:
chmod +x skills/my-skill/my-command.sh
-
Push to VPS:
# From the infra repo: make push-configCustom skills in
skills/are copied to~/.openclaw/workspace/skills/on the VPS. -
Use in OpenClaw:
- Via chat: "Run my-command"
- Via Telegram:
/my-command
OpenClaw skills can include:
- Slash commands — callable via
/command-name - Hooks — triggered on events (e.g., before tool execution)
- Templates — prompt templates for common workflows
- Tools — custom tool definitions
For detailed skill development documentation, see the OpenClaw Skill Development Guide.
The default configuration includes these generic ClawHub skills:
| Skill | Description | Use Case |
|---|---|---|
yt |
YouTube transcript fetching and video search | "Get transcript for youtube.com/watch?v=..." |
agent-browser |
Headless browser for JavaScript-heavy/paywalled pages | Access dynamic content |
system-monitor |
CPU/RAM/GPU status check | "What's my server's CPU usage?" |
conventional-commits |
Format commit messages per convention | Standardized commit messages |
These are intentionally minimal — add your own skills based on your workflows.
Back up your ~/.openclaw/workspace directory to a private GitHub repo automatically. Runs as a Docker sidecar container with built-in cron, pushing to a configurable branch (default: auto). You can then manually merge auto into main via PR whenever you want.
- Create a private GitHub repo (e.g.
your-username/openclaw-workspace) - Create a GitHub PAT at github.com/settings/tokens with
reposcope - Add to your
.env(or infra repo'ssecrets/openclaw.env):GIT_WORKSPACE_REPO=your-username/openclaw-workspace GIT_WORKSPACE_BRANCH=auto GIT_WORKSPACE_TOKEN=ghp_your_personal_access_token GIT_WORKSPACE_SYNC_SCHEDULE=0 4 * * * - Deploy — the sidecar auto-enables when
GIT_WORKSPACE_REPOis set:# From infra repo: make push-env && make deploy
The sidecar runs an initial sync on startup, then syncs on the configured cron schedule (default: daily at 4 AM UTC).
# From infra repo:
make workspace-syncRemove or clear GIT_WORKSPACE_REPO from your .env and redeploy.
The gateway binds to loopback only (127.0.0.1:18789). Access it via SSH tunnel:
ssh -N -L 18789:127.0.0.1:18789 openclaw@VPS_IPThen open http://localhost:18789 in your browser.
Secrets (API keys, tokens) are managed by the infra repo, not this repo.
This repo only contains docker/.env.example as documentation of what
variables are required.
In the infra repo:
- Edit
secrets/openclaw.env - Run
make push-envto push to VPS and restart
Images are built locally and pushed to GHCR via scripts/build-and-push.sh:
ghcr.io/YOUR_USERNAME/openclaw-docker-config/openclaw-gateway:latest— main gateway imageghcr.io/YOUR_USERNAME/openclaw-docker-config/workspace-sync:latest— workspace git sync sidecar- Both images also get a
:<sha>tag pinned to the git commit
One-time GHCR login (laptop):
# Create a PAT at github.com/settings/tokens with write:packages scope
echo "$GHCR_PAT" | docker login ghcr.io -u YOUR_GITHUB_USERNAME --password-stdinRollback to a previous version:
# On the VPS, in ~/openclaw/:
# Edit docker-compose.yml, change :latest to the SHA tag (e.g. :abc1234)
docker compose pull && docker compose up -dUpgrade OpenClaw itself: bump OPENCLAW_VERSION in docker/Dockerfile, commit, push, then run scripts/build-and-push.sh followed by make deploy from the infra repo.
# From the infra repo:
make logs
# Or SSH in:
cd ~/openclaw && docker compose logs openclaw-gatewayCheck for missing environment variables or invalid config JSON.
Ensure the host directories exist and are owned by the correct user:
sudo mkdir -p /home/openclaw/.openclaw/workspace
sudo chown -R 1000:1000 /home/openclaw/.openclaw- Check secrets:
make push-envfrom infra repo to re-push - Check that no other process is polling the same bot token
- Restart:
make deployfrom infra repo
bash scripts/validate-config.shCommon causes:
- Invalid JSON syntax (missing comma, trailing comma)
- Raw API key accidentally pasted into
openclaw.json
# From the infra repo:
make statusTo activate the pre-commit validation hook:
git config core.hooksPath .githooks