Setting Up OpenClaw on Linux VPS (Complete Tutorial)
Setting Up OpenClaw on Linux VPS (Complete Tutorial)

Let's skip the fluff. You want to get OpenClaw running on a Linux VPS so your AI agents can actually browse the web, interact with pages, and do real work in production. You've probably already tried hacking together Playwright scripts on your local machine, watched it work beautifully, then deployed to a $20 Hetzner box and watched everything fall apart.
I've been there. Multiple times. And I'm going to walk you through the entire process of getting OpenClaw installed, configured, and running on a Linux VPS β from a blank server to a functioning deployment. No hand-waving, no "just figure it out," no skipping the parts where things actually go wrong.
Why This Is Harder Than It Should Be
Here's the thing nobody tells you upfront: browser automation was designed for testing. Selenium, Playwright, Puppeteer β all built so QA teams could run quick scripts against predictable pages on beefy CI machines. They were never designed for what we're doing now, which is running long-lived AI agents that need to browse unpredictable websites on cheap cloud servers with limited RAM.
The result? You get hit with a wall of pain:
- Chrome crashes because your 2GB VPS can't handle three tabs
- Docker networking silently fails and your agent can't reach the browser container
- Sessions evaporate between runs, so your agent re-authenticates to every service every single time
- You install Chrome via
apt-getand get a version from 2022 that Playwright refuses to talk to - Logs are either nonexistent or 50MB of noise where you can't find the actual error
OpenClaw exists specifically to solve this intersection of problems. It's not "Playwright but better." It's browser automation purpose-built for AI agents running on constrained VPS infrastructure. Long-running sessions, resource efficiency, resilience, and observability are baked in from the ground up.
Let's get it running.
Prerequisites: What You Need Before You Start
You need a Linux VPS. That's it. Here's what I recommend:
- OS: Ubuntu 22.04 LTS or Debian 12 (both work, Ubuntu has slightly better community support)
- RAM: Minimum 2GB, but 4GB is the sweet spot for running a few concurrent agent sessions
- CPU: 2 vCPUs minimum
- Storage: 20GB SSD minimum (browser profiles and screenshots add up)
- Providers that work great: Hetzner, DigitalOcean, Linode, Vultr. Avoid the cheapest AWS Lightsail tier β the burstable CPU will throttle you at the worst times.
You also need SSH access and a non-root user with sudo privileges. If you're still running everything as root, fix that first. I'm serious.
Step 1: Update Your System and Install Docker
SSH into your VPS and start with the basics:
sudo apt update && sudo apt upgrade -y
Now install Docker. Don't use the docker.io package from Ubuntu's default repos β it's outdated. Use Docker's official repository:
# Install prerequisites
sudo apt install -y ca-certificates curl gnupg lsb-release
# Add Docker's GPG key
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# Add the repository
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker Engine and Docker Compose
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
Add your user to the Docker group so you don't need sudo for every command:
sudo usermod -aG docker $USER
newgrp docker
Verify it works:
docker run hello-world
If you see the "Hello from Docker!" message, you're good. If you get a permissions error, log out and back in β the group change needs a fresh session.
Step 2: Install OpenClaw
Here's where things get dramatically simpler than the old way of doing this. No matching Chrome versions, no fighting with system dependencies, no 47-step install guides:
curl -fsSL https://openclaw.dev/install.sh | bash
That's the single-command install. Everything is containerized, so it doesn't pollute your system with random Chrome binaries or conflicting Python packages.
Once the install completes, verify it:
openclaw --version
You should see the version number print out. If the command isn't found, you may need to add the install path to your shell profile:
export PATH="$HOME/.openclaw/bin:$PATH"
echo 'export PATH="$HOME/.openclaw/bin:$PATH"' >> ~/.bashrc
Step 3: Initialize Your Project
Create a directory for your OpenClaw deployment and initialize it:
mkdir ~/openclaw-agent && cd ~/openclaw-agent
openclaw init
This generates a project structure with a docker-compose.yml, a config file, and some starter templates. The docker-compose.yml is where the magic happens β OpenClaw pre-configures the networking between your agent process and the browser container so you never have to debug DNS resolution or Docker bridge networks:
# Generated docker-compose.yml (simplified)
version: '3.8'
services:
openclaw:
image: openclaw/openclaw:latest
ports:
- "3000:3000"
networks:
- agent_network
environment:
- MAX_CONCURRENT_CONTEXTS=5
- STEALTH_MODE=true
- PERSISTENT_PROFILES=true
volumes:
- ./profiles:/data/profiles
- ./screenshots:/data/screenshots
deploy:
resources:
limits:
memory: 2G
networks:
agent_network:
driver: bridge
Notice a few things here that matter:
MAX_CONCURRENT_CONTEXTS=5β This prevents your agent from opening infinite browser contexts and eating all your RAM. On a 4GB VPS, 5 contexts is a reasonable default. OpenClaw uses lightweight contexts that share browser processes, so 5 contexts doesn't mean 5 Chrome instances. It means 5 isolated sessions sharing maybe 2 browser processes using roughly 1GB total.STEALTH_MODE=trueβ Pre-configures anti-detection measures: user-agent rotation, WebGL fingerprint randomization, and navigator property patching. Without this, every major website immediately flags your VPS IP as a bot.PERSISTENT_PROFILES=trueβ Sessions survive restarts. Your agent logs into a service once, and the session persists across runs. No more re-authenticating every time your agent spins up.
Step 4: Configure for Your VPS Resources
Open the config file and tune it for your specific server. This is the part most tutorials skip, and it's the part that causes the most production headaches:
nano openclaw.config.yml
Here's what I recommend for a 4GB VPS:
# openclaw.config.yml
server:
host: 0.0.0.0
port: 3000
browser:
max_concurrent_contexts: 5
context_timeout_minutes: 30
auto_cleanup: true
cleanup_idle_after_minutes: 10
resources:
max_memory_mb: 2048
max_cpu_percent: 80
stealth:
enabled: true
rotate_user_agent: true
proxy:
enabled: false
# Uncomment and configure if you need residential proxies:
# type: residential
# provider: brightdata
# endpoint: your-proxy-endpoint
# username: your-username
# password: your-password
logging:
level: info
format: json
max_size_mb: 50
persistence:
profiles_dir: /data/profiles
screenshots_dir: /data/screenshots
auto_screenshot_on_error: true
Key settings to adjust based on your VPS:
| VPS RAM | max_concurrent_contexts | max_memory_mb |
|---|---|---|
| 2GB | 3 | 1024 |
| 4GB | 5 | 2048 |
| 8GB | 12 | 4096 |
| 16GB | 25 | 8192 |
The auto_screenshot_on_error: true setting is a lifesaver. When your agent fails on a page, OpenClaw automatically captures a screenshot so you can actually see what happened β a JavaScript popup blocking content, a CAPTCHA challenge, a weird layout shift. Without this, you're debugging blind.
Step 5: Start OpenClaw
docker compose up -d
Check that everything is running:
docker compose ps
You should see the OpenClaw container running and healthy. Check the logs to make sure there are no startup errors:
docker compose logs -f openclaw
Test the API endpoint:
curl http://localhost:3000/health
You should get back something like:
{
"status": "healthy",
"version": "1.x.x",
"active_contexts": 0,
"memory_mb": 120,
"cpu_percent": 2
}
That resource information is available in real-time, which means your agent code can check before launching resource-heavy tasks:
import httpx
async def check_resources():
resp = await httpx.AsyncClient().get("http://localhost:3000/health")
status = resp.json()
if status["memory_mb"] > 1800:
# Too close to limit, wait or clean up
await cleanup_idle_contexts()
return status
Step 6: Secure Your Deployment
If your VPS has a public IP (it does), you need to lock this down. OpenClaw's API should not be exposed to the internet without authentication.
Option A: Firewall rules (simplest)
# Only allow OpenClaw access from localhost
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Do NOT allow 3000/tcp from outside
sudo ufw enable
Then use an SSH tunnel when you need to access OpenClaw remotely:
ssh -L 3000:localhost:3000 user@your-vps-ip
Option B: Reverse proxy with authentication
If your agents run on a different server (or you need API access from outside), put Nginx in front with basic auth:
sudo apt install -y nginx apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd openclaw
Then configure Nginx:
server {
listen 80;
server_name your-domain.com;
location / {
auth_basic "OpenClaw API";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Don't skip security. I've seen open browser automation endpoints get discovered by bots within hours and used for credential stuffing. Don't be that person.
Step 7: Connect Your Agent
With OpenClaw running, here's how your AI agent code actually connects to it:
from openclaw import OpenClawClient
async def run_agent():
client = OpenClawClient("http://localhost:3000")
# Create a persistent context (session survives restarts)
context = await client.create_context(
profile_id="research_agent",
persistent=True
)
# Navigate and interact
page = await context.new_page()
await page.goto("https://example.com")
# Get structured page data for your LLM
content = await page.get_accessibility_tree()
# Returns structured elements your agent can reason about
# Take action based on agent decision
await page.click("#search-button")
# Get current state for next LLM call
screenshot = await page.screenshot()
dom_snapshot = await page.get_dom_snapshot()
# Clean up when done
await context.close()
The accessibility tree is particularly valuable. Instead of feeding raw HTML to your language model (expensive, noisy, often confusing), OpenClaw gives you a structured tree of interactive elements that your agent can reference by ID. This dramatically reduces hallucinated UI interactions β your agent clicks on elements that actually exist.
Step 8: Set Up Auto-Restart and Monitoring
You want OpenClaw to survive VPS reboots and recover from crashes:
# Docker Compose already handles restart policy, but verify:
# In docker-compose.yml, add under the openclaw service:
# restart: unless-stopped
For basic monitoring, create a simple health check script:
#!/bin/bash
# /usr/local/bin/check-openclaw.sh
HEALTH=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/health)
if [ "$HEALTH" != "200" ]; then
echo "OpenClaw unhealthy, restarting..."
cd ~/openclaw-agent && docker compose restart
# Optional: send alert via webhook
# curl -X POST "https://your-webhook-url" -d '{"text":"OpenClaw restarted"}'
fi
Add it to cron:
chmod +x /usr/local/bin/check-openclaw.sh
crontab -e
# Add: */5 * * * * /usr/local/bin/check-openclaw.sh
Common Gotchas and How to Fix Them
"Container starts but browser won't launch"
Usually a shared memory issue. Add this to your docker-compose.yml under the openclaw service:
shm_size: '1gb'
Chrome needs shared memory for rendering. Docker's default 64MB is laughably insufficient.
"Everything works but sites block me"
Enable proxy support in openclaw.config.yml. Residential proxies from Bright Data or Oxylabs work well. Datacenter IPs get blocked by Cloudflare almost immediately. Budget roughly $15-30/month for proxy bandwidth depending on your usage.
"Agent works for an hour then memory explodes"
Your agent is probably creating contexts without closing them. Make sure you're calling context.close() when done, and keep auto_cleanup: true in your config as a safety net. OpenClaw will kill idle contexts after the configured timeout.
"Can't install β 'permission denied' errors" You're probably running on a VPS with restricted Docker access. Some providers (notably certain OpenVZ-based hosts) don't support Docker properly. KVM-based VPS is what you want. Hetzner, DigitalOcean, and Vultr all use KVM.
The Shortcut: Skip the Manual Setup
I've just walked you through the full manual process because I think it's important to understand what's happening under the hood. When something breaks at 2 AM, you need to know where to look.
But if you'd rather skip the configuration trial-and-error and start with a deployment that already has the gotchas handled, check out Felix's OpenClaw Starter Pack on Claw Mart. It's $29 and includes pre-configured skills, optimized configs for common VPS sizes, and templates that handle the stuff I just spent 1500 words explaining β resource tuning, session persistence, error handling patterns, the whole setup. I've seen people shave days off their deployment time with pre-built skill packs instead of configuring everything from scratch.
It's not required. Everything I've covered above works on its own. But if your time is worth more than $29 (it is), it's a no-brainer starting point, especially if this is your first OpenClaw deployment.
What's Next
Once OpenClaw is running on your VPS, you've got a production-grade browser automation layer that your AI agents can talk to. From here:
-
Build your agent logic β Connect your LLM (through whatever framework you prefer) to OpenClaw's API. The accessibility tree and structured page data make it straightforward to build agents that actually understand what they're looking at.
-
Add persistent sessions β Set up profiles for each service your agent interacts with. Log in once, let OpenClaw maintain the session.
-
Set up proxy rotation β If you're interacting with sites that care about bot detection (most of them), configure residential proxy rotation early. It's much easier to set up before you have active sessions than after.
-
Monitor resource usage β Watch the
/healthendpoint for a week. You'll learn your actual memory and CPU patterns and can adjustMAX_CONCURRENT_CONTEXTSaccordingly. -
Scale when ready β When you outgrow a single VPS, OpenClaw supports horizontal scaling with Redis coordination. But don't over-engineer this upfront. A single 8GB VPS running OpenClaw can handle a surprising amount of concurrent agent work β 20+ contexts sharing a handful of browser processes at roughly 1GB total RAM.
The gap between "my agent works on my laptop" and "my agent works reliably in production" is where most projects die. OpenClaw exists to close that gap. Get it installed, get it configured, and focus your time on what actually matters: building agents that do useful work.
Recommended for this post
