Running OpenClaw on your own VPS gives you full control over your AI agent gateway. No dependencies on third-party hosted services, no usage limits you did not choose, and complete data sovereignty. This guide covers a clean Docker-based deployment on a fresh Ubuntu VPS — from first SSH login to a working gateway with Telegram or Discord integration.
If you want the fastest possible path to a running gateway, see our 30-minute quick-start. For a deeper walkthrough with security hardening, check the step-by-step deployment guide. This post sits in the middle: complete enough to follow without guessing, concise enough to finish in one sitting.
What You Need Before Starting
Gather these before you open a terminal:
- A VPS with at least 2 vCPUs, 4 GB RAM, and 20 GB SSD (Ubuntu 22.04 or 24.04 LTS)
- A domain or subdomain with DNS A record pointing to your VPS IP
- Docker Engine 24.x+ and Docker Compose v2 installed
- A valid TLS certificate (Let's Encrypt via certbot works)
- At least one AI provider API key (OpenAI, Anthropic, or a local Ollama instance)
- Optional: Telegram bot token or Discord bot token for messaging channels
OpenClaw builds from source during setup if you do not use a pre-built image. The build process can consume significant RAM, so the 4 GB minimum is not negotiable.
Server Preparation and Docker Setup
Start with a clean server. Update packages, install Docker, and add your user to the docker group:
sudo apt update && sudo apt upgrade -y
sudo apt install -y ca-certificates curl gnupg
# Add Docker's official GPG key and repository
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# Add current user to docker group
sudo usermod -aG docker $USER
newgrp docker
Verify Docker is working before proceeding:
docker --version
docker compose version
docker run --rm hello-world
Cloning and Building OpenClaw
Create a directory for OpenClaw and clone the repository:
sudo mkdir -p /opt/openclaw
sudo chown $USER:$USER /opt/openclaw
cd /opt/openclaw
git clone https://github.com/openclaw/openclaw.git .
git checkout main
Run the Docker setup script. It builds the gateway image, runs onboarding, and starts the container:
./scripts/docker/setup.sh
If you prefer a pre-built image instead of building locally:
export OPENCLAW_IMAGE="ghcr.io/openclaw/openclaw:latest"
./scripts/docker/setup.sh
The setup script prompts for your AI provider API key, generates a gateway token, and writes configuration to .env. Keep that token secure — it is your admin access to the Control UI.
Domain Configuration and Reverse Proxy
The gateway listens on port 18789 by default. For production, put it behind a reverse proxy with HTTPS. Here is a minimal NGINX configuration:
server {
listen 80;
server_name openclaw.example.com;
return 301 https://\$server_name\$request_uri;
}
server {
listen 443 ssl http2;
server_name openclaw.example.com;
ssl_certificate /etc/letsencrypt/live/openclaw.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/openclaw.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:18789;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_buffering off;
proxy_read_timeout 300s;
}
location /ws {
proxy_pass http://127.0.0.1:18789;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Obtain certificates and reload NGINX:
sudo certbot --nginx -d openclaw.example.com
sudo systemctl reload nginx
Now open https://openclaw.example.com in your browser and paste the gateway token from .env into the Settings panel.
Configuring Messaging Channels
OpenClaw supports WhatsApp, Telegram, and Discord out of the box. Use the CLI container to add channels without touching config files directly.
Telegram
docker compose run --rm openclaw-cli channels add \
--channel telegram \
--token "YOUR_BOT_TOKEN"
Discord
docker compose run --rm openclaw-cli channels add \
--channel discord \
--token "YOUR_BOT_TOKEN"
After adding a channel, send a test message to verify the bot responds. Check logs if messages are not reaching the gateway:
docker compose logs --tail 50 openclaw-gateway
Health Checks and Monitoring
OpenClaw exposes unauthenticated health endpoints for container orchestration:
curl -fsS http://127.0.0.1:18789/healthz # liveness
curl -fsS http://127.0.0.1:18789/readyz # readiness
The Docker image includes a built-in HEALTHCHECK that pings /healthz. If the gateway becomes unresponsive, Docker marks the container unhealthy and can trigger automatic restarts.
For deeper diagnostics, run the authenticated health snapshot:
docker compose exec openclaw-gateway \
node dist/index.js health \
--token "$OPENCLAW_GATEWAY_TOKEN"
Tips and Troubleshooting
Build fails with exit 137
This is an out-of-memory kill. The local build needs at least 2 GB free RAM during pnpm install and the TypeScript compilation step. Upgrade your VPS or use a pre-built image:
export OPENCLAW_IMAGE="ghcr.io/openclaw/openclaw:latest"
./scripts/docker/setup.sh
Cannot reach the Control UI from outside the server
Verify the gateway bind mode. The setup script defaults to lan, which publishes port 18789 on all interfaces. If you changed it to loopback, only processes inside the container can reach it directly. Check .env for OPENCLAW_GATEWAY_BIND.
Local AI providers are unreachable
Inside the Docker container, 127.0.0.1 refers to the container itself, not the host. Use host.docker.internal for Ollama or LM Studio running on the host:
# For Ollama on the host
OLLAMA_HOST=0.0.0.0:11434 ollama serve
# In OpenClaw config, use
# http://host.docker.internal:11434
Channel messages are not received
Confirm your bot token is valid and the bot has permissions to read messages in the target channel. For Telegram, start a conversation with the bot first — it cannot message users who have not interacted with it.
Config changes do not persist after restart
Ensure the OPENCLAW_CONFIG_DIR and OPENCLAW_HOME_VOLUME mounts are active. Without a named volume or bind mount, container restarts wipe all state. The setup script configures these by default, but custom Compose files may omit them.
Logs are growing without bound
Configure Docker log rotation to prevent disk exhaustion:
# /etc/docker/daemon.json
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
Next Steps
You now have a self-hosted OpenClaw gateway running on your VPS with Docker, accessible over HTTPS, and connected to messaging channels. From here you can add custom agents, integrate additional AI providers, and build automated workflows that run entirely on your infrastructure.
For more detailed guidance, explore our related posts:
- OpenClaw Docker VPS Deploy: Run Your Own AI Agent Gateway in Under 30 Minutes
- OpenClaw Docker VPS Deploy: A Developer's Step-by-Step Guide
- How to Deploy OpenClaw on a VPS with Docker (Step-by-Step Guide)
Need help with production hardening, multi-agent orchestration, or integrating OpenClaw with your existing infrastructure? Contact our team for enterprise OpenClaw consulting and managed deployment services.