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_TOKEN" | docker login ghcr.io -u $GHCR_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 git remote 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.
Supports GitHub, GitLab, Bitbucket, and any git remote that accepts HTTPS push with inline authentication.
Choose one of the two options below — do not set both.
- 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_TOKEN=ghp_your_personal_access_token
The token is passed to git via GIT_ASKPASS at runtime and is not embedded in the remote URL or persisted to .git/config.
- Build the remote URL with inline authentication for your provider:
- GitLab:
https://user:token@gitlab.com/username/repo.git - Bitbucket:
https://x-token-auth:token@bitbucket.org/username/repo.git
- GitLab:
- Add to your
.env(or infra repo'ssecrets/openclaw.env):GIT_WORKSPACE_REMOTE=https://user:token@gitlab.com/username/openclaw-workspace.git
Note: With this option, the URL (including credentials) is stored in
.git/configinside the workspace volume. The token is already present in the.envfile on the VPS, so this does not increase the attack surface.
GIT_WORKSPACE_BRANCH=auto
GIT_WORKSPACE_SYNC_SCHEDULE=0 4 * * *
Deploy — the sidecar auto-enables when either GIT_WORKSPACE_REPO or GIT_WORKSPACE_REMOTE is set:
# From infra repo:
make push-env && make deployThe 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 / GIT_WORKSPACE_REMOTE 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 "$GH_TOKEN" | docker login ghcr.io -u $GHCR_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