Self-Hosting Autonomous Agents on Ubuntu: Headless Browser Pools, Xvfb, and VPS Isolation ZeroLabs and OpenClaw have published a guide to self-hosting autonomous AI agents on Ubuntu VPS instances, detailing the use of Xvfb virtual displays, headless Chromium, and systemd service supervision to ensure reliable production operation. The approach addresses common failures such as display absence, orphaned processes, and crash recovery, and is implemented across the ZeroLabs and OpenClaw platform architecture. Original Article published on ZeroLabs https://labs.zeroshot.studio/agents/self-hosting-headless-agent-vps?utm source=devto&utm medium=syndication&utm campaign=self-hosting-headless-agent-vps . 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 https://labs.zeroshot.studio/vps-infra 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: php 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: Launch Xvfb on display :99 with standard 1920x1080 resolution Xvfb :99 -screen 0 1920x1080x24 -ac & export DISPLAY=:99 Test headless browser navigation 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: /etc/systemd/system/agent-worker.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: python /usr/bin/env python3 scripts/browser/close chrome if idle.py 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 : Terminate browser processes running longer than 15 minutes 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 https://labs.zeroshot.studio/agents/self-hosting-headless-agent-vps?utm source=devto&utm medium=syndication&utm campaign=self-hosting-headless-agent-vps by ZeroShot Studio https://zeroshot.studio .