Docker Deployment — Vulpine-Box
Vulpine-Box packages the VulpineOS runtime, OpenClaw, Camoufox, and an Xvfb display into a single container. Use it when you want the browser kernel on a VPS and connect to it from your laptop through the web panel or the TUI.
By default the container starts:
./vulpineos serve --binary ./browser/camoufox --port 8443 --no-tls --api-key "$VULPINE_API_KEY"That means the stock Docker path exposes the same served control plane as a normal
vulpineos serve run. The panel and the remote TUI both authenticate with the same access
key.
Quick Start
git clone https://github.com/VulpineOS/VulpineOS.git
cd VulpineOS
# Build or copy the Linux Camoufox distribution first.
# The Dockerfile expects dist/camoufox-linux/ to exist.
# Set an access key for the served runtime.
export VULPINE_API_KEY=$(openssl rand -hex 32)
# Launch the container.
docker compose up -dOpen the remote panel from your local machine:
vulpineos remote panel --url http://your-vps:8443 --api-key $VULPINE_API_KEYConnect with the remote TUI instead:
vulpineos remote tui --url http://your-vps:8443 --api-key $VULPINE_API_KEYvulpineos remote defaults to panel mode, so vulpineos remote --url ... also works.
What You Need Before docker compose up
Dockerfile.vulpinebox does not compile Camoufox. It copies a prebuilt browser bundle
from dist/camoufox-linux/ into the image at build time.
Required layout:
VulpineOS/
dist/
camoufox-linux/
camoufox
camoufox-bin
...other runtime files...If dist/camoufox-linux/ is missing, the Docker build will fail.
Docker Compose
The docker-compose.yml defines the service:
services:
vulpineos:
build:
context: .
dockerfile: Dockerfile.vulpinebox
ports:
- "8443:8443"
environment:
- VULPINE_API_KEY=${VULPINE_API_KEY:?set VULPINE_API_KEY to a random access key before running docker compose}
volumes:
- vulpineos-data:/root/.vulpineos
- vulpine-profiles:/opt/vulpineos/profiles
restart: unless-stopped
deploy:
resources:
limits:
memory: 4G
volumes:
vulpineos-data:
vulpine-profiles:Default behavior:
- port
8443is published from the container VULPINE_API_KEYis passed through tovulpineos serve- the stock compose file serves plain HTTP on
8443 - the healthcheck hits
http://localhost:8443/health - Xvfb provides a display so Camoufox can stay headful inside the container
If you want HTTPS/WSS, mount certificates and provide VULPINE_TLS_CERT and
VULPINE_TLS_KEY. Until then, connect with http://... URLs for the panel and let
vulpineos remote tui normalize that to ws://.../ws.
Persistent Volumes
| Volume | Path | Purpose |
|---|---|---|
vulpineos-data | /root/.vulpineos | Config, SQLite vault, agent records, logs, and runtime state |
vulpine-profiles | /opt/vulpineos/profiles | Browser profiles, warmed state, and disk cache |
Data survives container restarts. To start fresh, remove the volumes:
docker compose down -vWhat’s Inside
The multi-stage Dockerfile builds:
- Stage 1 — Go binary compilation (
CGO_ENABLED=0, stripped) - Stage 2 — Ubuntu 22.04 runtime with:
- GTK/X11 libraries for Firefox rendering
- Xvfb virtual display (headless)
- Pre-built Camoufox binary
- Node.js + OpenClaw
The runtime image expects the browser executable at ./browser/camoufox, matching the
entrypoint.
Entrypoint
The scripts/entrypoint.sh script:
- Starts Xvfb on display
:99 - Launches
vulpineos serve --binary ./browser/camoufox --port 8443 --no-tls - Adds
--api-key "$VULPINE_API_KEY"when that environment variable is set - Replaces
--no-tlswith--tls-certand--tls-keywhen both TLS environment variables are set
The panel does not have a separate login database. The prompt in the remote panel is asking
for the same access key passed in as VULPINE_API_KEY.
If you connect with:
vulpineos remote panel --url http://your-vps:8443 --api-key $VULPINE_API_KEYthe generated URL includes the token, the panel validates it, stores it in session storage, and strips it from the visible URL after load.
Memory
Each browser context uses roughly 10-15 MB. With the 4 GB memory limit, you can comfortably run 20-30 concurrent contexts with headroom for the kernel itself. Adjust the memory limit in docker-compose.yml for larger deployments.
TLS
To enable TLS, mount your certificates:
volumes:
- ./certs/fullchain.pem:/etc/vulpineos/cert.pem:ro
- ./certs/privkey.pem:/etc/vulpineos/key.pem:roThen pass the matching environment variables:
environment:
- VULPINE_API_KEY=${VULPINE_API_KEY:?set VULPINE_API_KEY to a random access key before running docker compose}
- VULPINE_TLS_CERT=/etc/vulpineos/cert.pem
- VULPINE_TLS_KEY=/etc/vulpineos/key.pemOnce TLS is enabled:
- use
https://your-vps:8443withvulpineos remote panel - use the same
https://...base URL withvulpineos remote tui - the remote TUI normalizes that base URL to
wss://.../ws
Known Limits
- The image depends on a prebuilt Linux Camoufox distribution; the Docker build does not produce one for you.
- The stock compose file does not include TLS certificates.
docker-compose.ymlrequiresVULPINE_API_KEY; generate one before launching the service on a network.- Browser rendering happens under Xvfb, so direct desktop inspection is not part of this deployment mode.
See also
- Remote Access — WebSocket server mode and client connection
- Getting Started — install and launch your first agent
- Architecture — single-process runtime overview