VPS App installer

How to Install OpenClaw on a VPS

Most people rent their AI assistant from someone else. The conversations flow through a third-party server, the API keys live in someone else’s dashboard and the data never really belongs to you. OpenClaw flips that arrangement on its head. It’s a self-hosted personal AI gateway that routes your conversations through the messaging apps you already live in, while your server handles everything behind the scenes.

This guide walks you through deploying OpenClaw on a VPS using Docker and the official pre-built image. By the time you finish, you’ll have a live gateway secured behind Nginx and Let’s Encrypt SSL, connected to channels like Telegram, Discord, Slack, or WhatsApp. No subscriptions. No vendor lock-in. Your data stays yours.

What Is OpenClaw?

OpenClaw is a personal AI assistant gateway you run on your own hardware. Think of it as a control plane sitting in the middle of everything: on one side it speaks to AI providers like OpenAI or Anthropic and on the other side it answers you across every messaging platform you actually use.

The channel list is genuinely impressive. WhatsApp, Telegram, Slack, Discord, Signal, iMessage, Microsoft Teams, Matrix, IRC, LINE, Mattermost, Nextcloud Talk, and more than a dozen others. You configure the gateway once and your AI assistant becomes available across all of them simultaneously. No per-app plugins. No recurring SaaS fees eating into your budget.

At the heart of the system sits the Gateway daemon, handling sessions, channels, routing, and tool execution. A built-in sandboxing layer wraps agent tool use in isolated Docker containers so even multi-user deployments keep sessions firewalled from each other. On a VPS you’ll run the gateway behind Nginx, let Let’s Encrypt manage SSL and talk to your assistant from anywhere through your own domain name.

Prerequisites

Before diving in, confirm your VPS meets the specifications below. The minimum is workable but tight. Running on 1 GB of RAM will get you OOM-killed during the Docker image pull, so 2 GB is a hard floor here, not merely a suggestion.

RequirementMinimumRecommended
RAM2 GB4 GB
CPU1 vCPU2 vCPUs
Disk20 GB SSD40 GB SSD
Operating SystemUbuntu 22.04 LTSUbuntu 24.04 LTS
Domain nameRequiredRequired

You’ll also need these ready before starting:

  • Root or sudo access on your VPS
  • A domain name with an A record pointing to your server’s IP address
  • An API key from at least one AI provider (OpenAI, Anthropic, or any OpenAI-compatible service)
  • Git installed on your server (sudo apt install -y git if not already present)

How to Install OpenClaw on a VPS

Step 1: Update Your Server

Start with a clean, fully patched system. Stale packages are a surprisingly common source of dependency conflicts and this takes about thirty seconds to prevent hours of debugging later.

sudo apt update && sudo apt upgrade -y

If the upgrade pulled in a kernel update, reboot before continuing:

sudo reboot

Step 2: Install Docker Engine

Install Docker Engine from the official Docker repository rather than Ubuntu’s default package manager. Ubuntu ships an older version called docker.io that lacks the Compose plugin and other features OpenClaw depends on. The official repository gives you the current release with everything bundled.

First, install the prerequisite packages and import Docker’s GPG signing key:

sudo apt-get install -y ca-certificates curl gnupg
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
sudo chmod a+r /etc/apt/keyrings/docker.gpg

Next, register the Docker repository with your system’s package sources:

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

Refresh your package index and install Docker Engine along with the Compose plugin:

sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Confirm Docker is running with a quick sanity check:

sudo docker run hello-world

If you’d prefer to run Docker commands without typing sudo every time, add your user to the docker group now:

sudo usermod -aG docker $USER
newgrp docker

Step 3: Clone OpenClaw and Prepare Data Directories

Clone the OpenClaw repository to /opt/openclaw. The repository contains the Docker Compose file and the setup scripts that orchestrate the entire deployment. You won’t be building from source here — the setup script pulls the official pre-built image from GitHub Container Registry, which sidesteps the significant RAM overhead of a local build.

sudo git clone https://github.com/openclaw/openclaw.git /opt/openclaw
cd /opt/openclaw

Create dedicated directories for OpenClaw’s persistent data. The gateway container runs as the node user (UID 1000) so the host directories need matching ownership, otherwise the container hits permission errors on first boot:

sudo mkdir -p /opt/openclaw/{config,workspace,auth}
sudo chown -R 1000:1000 /opt/openclaw/config /opt/openclaw/workspace /opt/openclaw/auth

These three directories hold OpenClaw’s configuration, agent workspace, and encrypted auth profile secrets respectively. Keeping them separate from the repository directory makes upgrades and off-site backups significantly cleaner.

Step 4: Lock Port Binding to Localhost

Here’s a subtlety worth knowing: Docker’s port publishing adds its own iptables rules and can bypass UFW entirely. On a VPS that means port 18789 might become publicly reachable before Nginx is even running. Prevent that by creating a Compose override file that pins all three gateway ports to localhost only:

cat > /opt/openclaw/docker-compose.override.yml << 'EOF'
services:
  openclaw-gateway:
    ports:
      - "127.0.0.1:18789:18789"
      - "127.0.0.1:18790:18790"
      - "127.0.0.1:3978:3978"
EOF

Docker Compose automatically merges this override file with the base docker-compose.yml. Nginx becomes the sole public entry point into the gateway, which is exactly the right shape for a production VPS deployment.

Step 5: Deploy OpenClaw with the Setup Script

The setup script orchestrates the entire deployment: it syncs your environment into a .env file, runs the onboarding wizard to capture your AI provider credentials, generates a gateway authentication token and starts everything via Docker Compose. Export your configuration paths before running it so the correct values land in .env:

cd /opt/openclaw
export OPENCLAW_IMAGE="ghcr.io/openclaw/openclaw:latest"
export OPENCLAW_CONFIG_DIR="/opt/openclaw/config"
export OPENCLAW_WORKSPACE_DIR="/opt/openclaw/workspace"
export OPENCLAW_AUTH_PROFILE_SECRET_DIR="/opt/openclaw/auth"
sudo -E ./scripts/docker/setup.sh

The -E flag preserves your exported variables when elevating to sudo. If you're already running as root, drop the sudo -E prefix entirely.

The onboarding wizard will prompt you for an AI provider choice and your API key. Work through the prompts to completion. When setup finishes, verify the gateway came up healthy:

docker compose ps

You should see openclaw-gateway listed with a healthy status. The .env file now holds your gateway token and other runtime secrets. Lock its permissions immediately:

chmod 600 /opt/openclaw/.env

Hit the health endpoint to confirm the gateway responds before moving on:

curl -fsS http://127.0.0.1:18789/healthz

A clean response here means the gateway is live on localhost and ready for Nginx to front it.

Step 6: Configure the UFW Firewall

Open SSH, HTTP, and HTTPS through the firewall then enable it. Everything else gets blocked by default:

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw --force enable
sudo ufw status

The output should list rules for SSH (22), HTTP (80), and HTTPS (443). Port 18789 should be absent from the list — Docker and Nginx handle that routing internally.

Step 7: Set Up Nginx as a Reverse Proxy

Install Nginx if it isn't already on your system:

sudo apt install -y nginx

Create a server block for OpenClaw. The configuration below enables WebSocket pass-through for the Control UI and CLI, disables proxy buffering so the gateway can stream AI responses in real time and sets a long read timeout for persistent connections:

sudo nano /etc/nginx/sites-available/openclaw

Paste in the following, replacing your-domain.com with your actual domain name:

server {
    listen 80;
    server_name your-domain.com;

    location / {
        proxy_pass http://127.0.0.1:18789;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        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_read_timeout 86400s;
        proxy_buffering off;
    }
}

Enable the site and verify Nginx accepts the configuration before reloading:

sudo ln -s /etc/nginx/sites-available/openclaw /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Step 8: Secure OpenClaw with Let's Encrypt SSL

Install Certbot and the Nginx plugin then request a certificate for your domain. Certbot handles everything automatically: it provisions the certificate, rewrites your Nginx config to enable HTTPS and sets up an HTTP-to-HTTPS redirect:

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.com

Certbot will ask for your email address and prompt you to agree to the Let's Encrypt terms of service. Follow the prompts and reload Nginx when it completes:

sudo systemctl reload nginx

Test the automatic renewal process now so you don't discover a broken timer after your certificate expires:

sudo certbot renew --dry-run

Step 9: Open the Control UI and Retrieve Your Gateway Token

Navigate to https://your-domain.com in your browser. The OpenClaw Control UI loads and asks for your gateway token. Fetch it from the .env file:

grep OPENCLAW_GATEWAY_TOKEN /opt/openclaw/.env

Paste that token into the login prompt. Once authenticated you'll land on the gateway dashboard, where you can monitor active sessions, configure agent behavior and manage channel connections.

You can also pull a full gateway status report directly from the command line using the CLI sidecar container:

cd /opt/openclaw
docker compose run --rm openclaw-cli gateway status

Step 10: Connect Your First Messaging Channel

OpenClaw's real appeal reveals itself the moment a messaging channel comes online. Telegram is the fastest to wire up because it only needs a bot token from BotFather — no QR code scanning, no phone number pairing, just a single command.

Open Telegram and start a conversation with @BotFather. Run /newbot, follow the prompts and copy the bot token BotFather generates. Then run this from your server:

cd /opt/openclaw
docker compose run --rm openclaw-cli channels add --channel telegram --token "YOUR_BOT_TOKEN_HERE"

Send your new bot a message in Telegram. It replies with a short pairing code. Approve it from the server:

docker compose run --rm openclaw-cli pairing approve telegram YOUR_PAIRING_CODE

Send the bot any message and your AI assistant responds directly in Telegram. For Discord, Slack, WhatsApp and other platforms the process follows the same pattern with provider-specific tokens. The full per-channel setup instructions live in the OpenClaw channel docs.

How to Update OpenClaw

OpenClaw uses date-stamped image tags like 2026.7.14 with latest always tracking the most recent stable release. Before updating, check the GitHub Container Registry to confirm nothing disruptive landed in the changelog. When you're ready, pull the new image and restart the stack:

cd /opt/openclaw
git pull
docker compose pull
docker compose up -d

The new gateway image runs startup-safe migration routines automatically. If those routines can't complete safely, the gateway exits rather than starting in a broken state — a deliberate design choice that prevents silent corruption. If you see the container restarting repeatedly after an upgrade, run the built-in doctor tool against your mounted config volume before restarting the stack:

docker run --rm \
  -v /opt/openclaw/config:/home/node/.openclaw \
  ghcr.io/openclaw/openclaw:latest \
  openclaw doctor --fix
docker compose up -d

Troubleshooting

Gateway Container Exits Immediately or Reports Exit Code 137

Exit code 137 is the OS killing your container for consuming too much memory. This almost always surfaces on 1 GB VPS instances during the initial image pull or first startup. The fix is straightforward: upgrade to a plan with at least 2 GB of RAM and retry. If you're already on a 2 GB server and still seeing this, run free -h before restarting to check whether other processes have claimed most of the available memory. Stop or prune anything unnecessary and try again.

Nginx Returns a 502 Bad Gateway Error

A 502 means Nginx is alive but can't reach the backend. Check whether the gateway container is actually running and accepting connections:

docker compose ps
curl -fsS http://127.0.0.1:18789/healthz

If the health check fails, inspect the last fifty lines of gateway logs for startup errors:

docker compose logs openclaw-gateway --tail 50

Also confirm your docker-compose.override.yml binds the gateway port to 127.0.0.1:18789. If the override file is missing or malformed, the port mapping falls through to Docker's default behavior and Nginx can't find the backend at the expected address.

Pairing Required or Unauthorized Error in the Control UI

Beyond the gateway token, the Control UI uses device pairing to authorize individual browsers. A fresh browser session or a cleared cookie jar will trigger this prompt. Generate a fresh dashboard link that includes pairing credentials:

cd /opt/openclaw
docker compose run --rm openclaw-cli dashboard --no-open

Open the printed URL in your browser. If the pairing prompt persists, list pending device requests and approve them manually:

docker compose run --rm openclaw-cli devices list
docker compose run --rm openclaw-cli devices approve REQUEST_ID

Channel Connection Fails or Returns Authentication Errors

Start by double-checking the token or credentials you passed to the channels add command. Telegram bot tokens get revoked if you regenerate them in BotFather so always use the most recent one. Discord and Slack bots need at minimum read and write message permission scopes or connection will fail silently. Run the built-in diagnostics tool to get a consolidated health report across all channels:

cd /opt/openclaw
docker compose run --rm openclaw-cli doctor

The doctor command also surfaces risky or overly permissive DM policies, which is worth reviewing any time you add a new channel or open access to additional users.

Permission Denied Errors on the Config Directory

The gateway container's node user runs as UID 1000. If your host directories are owned by root or any other UID, the container can't write to them and you'll see EACCES errors in the logs. Fix ownership and restart:

sudo chown -R 1000:1000 /opt/openclaw/config /opt/openclaw/workspace /opt/openclaw/auth
docker compose up -d

This is also the fix for the less obvious blocked plugin candidate: suspicious ownership error, which surfaces when the process UID and the mounted plugin directory owner disagree.

What to Build Next

With the gateway running, you've barely scratched the surface of what OpenClaw can do. Here are some logical next steps worth exploring:

  • Connect additional channels: Wire up Discord, Slack, or WhatsApp alongside Telegram. Each channel carries its own DM policy so you can maintain separate assistants for different contexts without any configuration overlap.
  • Enable agent sandboxing: Set agents.defaults.sandbox.mode to non-main in your openclaw.json to run non-primary agent sessions inside isolated Docker containers. This becomes essential if you plan to expose the gateway to anyone beyond yourself.
  • Install skills from ClawHub: ClawHub is the community registry for OpenClaw skills, roughly analogous to a plugin marketplace. Run docker compose run --rm openclaw-cli plugins install @openclaw/SKILL_NAME to extend what your assistant can do without touching the core config.
  • Configure cron automation: OpenClaw's built-in cron tool supports scheduled agent tasks defined directly in openclaw.json. Set up recurring summaries, daily digests, or automated checks without any external infrastructure.
  • Set up model failover: Add multiple AI provider profiles to openclaw.json so the gateway automatically switches to a secondary provider when your primary API key hits rate limits or experiences an outage.

You now have a production-grade personal AI gateway running entirely on infrastructure you control. A GreenGeeks VPS gives it a reliable long-term home: fast NVMe storage for the agent workspace, generous bandwidth for all those channel connections and the uptime your assistant needs to actually be there when you message it. If you're not already hosting with GreenGeeks, take a look at our VPS plans and give your gateway a proper permanent address.