Original Article published on ZeroLabs.
Key Takeaway:
- A hardened guide to self-hosting autonomous AI agents on Ubuntu VPS instances with virtual display buffers, headless Chrome instances, and systemd service supervision.
- Structured verification, strict boundaries, and deterministic tooling prevent production failure.
- Implemented directly across the ZeroLabs and OpenClaw platform architecture.
Image credit: labs.zeroshot.studio
Why this matters: Engineering reliable systems requires moving past unstructured prompts into hardened execution contracts.
Running autonomous agents on local development laptops causes frequent interruptions when your machine sleeps, changes Wi-Fi networks, or runs out of RAM.
Deploying agents to a dedicated Ubuntu VPS (such as a 4-core, 8GB RAM Hetzner or DigitalOcean instance) provides:
flowchart TD
A[System Cron / Webhook Trigger] --> B[systemd Supervisor Service]
B --> C[Agent Core Runtime]
C --> D[Xvfb Virtual Display :99]
D --> E[Headless Chromium CDP Instance]
C --> F[(Local SQLite / Postgres Store)]
Many web scraping and browser navigation tools fail on headless Linux servers because no graphical display is available. Xvfb (X Virtual Framebuffer) emulates a monitor entirely in system memory.
Install required dependencies on Ubuntu 24.04:
sudo apt-get update && sudo apt-get install -y \
xvfb \
chromium-browser \
libnss3 \
libxss1 \
libasound2t64 \
fonts-liberation
Start the virtual display buffer and verify Chromium can render pages:
Xvfb :99 -screen 0 1920x1080x24 -ac &
export DISPLAY=:99
chromium-browser --no-sandbox --disable-dev-shm-usage --dump-dom https://example.com
To ensure your agent recovers automatically from crashes or server reboots, create a dedicated systemd service:
[Unit]
Description=ZeroLabs Autonomous Agent Worker
After=network.target
[Service]
Type=simple
User=zeroshot
WorkingDirectory=/home/zeroshot/.openclaw/workspace
Environment=DISPLAY=:99
Environment=NODE_ENV=production
ExecStart=/usr/bin/python3 /home/zeroshot/.openclaw/workspace/scripts/zerostate-content-team/auto_publisher.py --scheduled
Restart=on-failure
RestartSec=10
StandardOutput=append:/home/zeroshot/zero-signals/auto-publisher.log
StandardError=append:/home/zeroshot/zero-signals/auto-publisher.log
[Install]
WantedBy=multi-user.target
Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable agent-worker.service
sudo systemctl start agent-worker.service
Headless browser automation frequently leaves orphaned Chrome subprocesses that consume system RAM over time.
Implement an automated cleanup script and schedule it in crontab every 15 minutes:
#!/usr/bin/env python3
import subprocess
import psutil
import time
def cleanup_orphaned_browsers():
for proc in psutil.process_iter(['pid', 'name', 'create_time']):
try:
if 'chrome' in proc.info['name'].lower() or 'chromium' in proc.info['name'].lower():
if time.time() - proc.info['create_time'] > 900:
print(f'Terminating stale browser PID: {proc.info["pid"]}')
proc.terminate()
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
if __name__ == '__main__':
cleanup_orphaned_browsers()
Add the cleanup check to crontab:
*/15 * * * * /usr/bin/python3 /home/zeroshot/.openclaw/workspace/scripts/browser/close_chrome_if_idle.py >/dev/null 2>&1
A minimum of 4GB RAM is recommended for single-agent workloads. For running multiple concurrent headless Chrome sessions, provision at least 8GB RAM with swap enabled.
--no-sandbox flag required for Chromium on Linux VPS?
When running Chromium under non-root service accounts on minimal Linux distributions, standard Linux namespaces may be restricted. The --no-sandbox flag enables execution within your secured VPS perimeter.
You can use x11vnc to attach a VNC server to the Xvfb display :99, allowing you to connect with a standard VNC client and watch agent navigation in real time.
Published on ZeroLabs by ZeroShot Studio.