Skip to main content
Run Agent Canvas on a VM or dedicated machine when you want an always-on backend, more compute, or a self-hosted Canvas that you can reach from other devices.
The agent server can read and write the host filesystem, execute shell commands, access the network, and store secrets. Treat the VM as trusted infrastructure. Use --public, a strong LOCAL_BACKEND_API_KEY, and a network access control layer before exposing it to the internet.

Choose a Deployment Shape

Agent Canvas supports two VM runtime modes and several ways to reach them:
SetupStart CommandHow You Use It
Backend onlyagent-canvas --backend-only --publicRun only the agent server on the VM. Start agent-canvas --frontend-only on your laptop and add the VM URL in Manage Backends.
Backend only + ngrokagent-canvas --backend-only --public and ngrok http 8000Use an ngrok URL as the backend URL. Do not add ngrok OAuth for this mode; rely on LOCAL_BACKEND_API_KEY plus a private or temporary URL.
Full Canvasagent-canvas --publicServe both the Agent Canvas UI and the backend from the VM. Open the VM, reverse proxy, or ngrok URL in a browser.
Full Canvas + ngrok OAuthagent-canvas --public and ngrok http 8000 --traffic-policy-file ~/policy.ymlProtect the full Canvas URL with an ngrok login policy before users reach Agent Canvas.
Use backend only when you want to keep the UI on your laptop and switch between backends. Use full Canvas when the VM should serve the browser UI too.

1. Provision and Secure the VM

Use any always-on Linux or macOS host. Ubuntu 24.04 LTS with 2 vCPU and 4 GB RAM is enough for a single user. Before starting Agent Canvas, restrict inbound traffic:
  • SSH (22) — allow only your IP address or VPN CIDR.
  • Agent Canvas (8000) — keep closed unless you are using an SSH tunnel. If you expose it through ngrok, nginx, or another proxy, expose only that proxy.
  • HTTP/HTTPS (80, 443) — open only if you configure a reverse proxy and TLS.

2. Install Prerequisites

Agent Canvas requires:
  • Node.js 22.12 or later, including npm.
  • uv for the agent server runtime.
  • git and curl.
  • Optional: ngrok for a temporary public URL.
  • Optional: tmux to keep Agent Canvas and ngrok running after disconnecting from SSH.

Ubuntu 22.04 / 24.04

Install Node.js 22.x, uv, and Agent Canvas:
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg git

# Node.js 22.x from NodeSource.
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs

# uv for the agent server runtime.
curl -LsSf https://astral.sh/uv/install.sh | sh
source "$HOME/.local/bin/env"

# Agent Canvas CLI.
sudo npm install -g @openhands/agent-canvas

node --version
uv --version
agent-canvas --version
If your npm global prefix is user-writable, omit sudo from npm install -g. For macOS or other Linux distributions, use the official Node.js, uv, and ngrok installation links above instead of the Ubuntu-specific commands.
Install optional runtime helpers if needed:
sudo apt-get install -y tmux
Install ngrok only if you plan to expose the VM through ngrok:
curl -sSL https://ngrok-agent.s3.amazonaws.com/ngrok.asc \
  | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null

echo "deb https://ngrok-agent.s3.amazonaws.com buster main" \
  | sudo tee /etc/apt/sources.list.d/ngrok.list

sudo apt-get update
sudo apt-get install -y ngrok

ngrok config add-authtoken <YOUR_NGROK_AUTHTOKEN>
Get the authtoken from the ngrok dashboard.

3. Set the Backend API Key

Remote and shared deployments should always run in public mode. Public mode requires LOCAL_BACKEND_API_KEY. Create a local environment file on the VM:
cat > ~/.agent-canvas.env <<'EOF_ENV'
export LOCAL_BACKEND_API_KEY="<choose-a-strong-secret>"
EOF_ENV
chmod 600 ~/.agent-canvas.env
source ~/.agent-canvas.env
Use a high-entropy secret. You will enter this key in Agent Canvas when connecting to the VM backend or opening the full Canvas UI.

4. Start Agent Canvas

Start only the backend on the VM:
source ~/.agent-canvas.env
agent-canvas --backend-only --public
Then start the frontend on your laptop:
agent-canvas --frontend-only
Add the VM backend in Agent Canvas:
  1. Click the backend switcher, then select Manage Backends.
  2. Click Add Backend.
  3. Enter a name, such as my-vm.
  4. Enter the Host / Base URL:
    • http://localhost:8000 if you use an SSH tunnel.
    • The https://...ngrok-free.app URL if you use ngrok.
    • Your reverse proxy URL if you use nginx or another proxy.
  5. Enter the LOCAL_BACKEND_API_KEY from the VM.
  6. Save and select the backend.

Keep It Running with tmux

Use tmux when you want Agent Canvas to keep running after your SSH session disconnects.
tmux new-session -d -s canvas
tmux send-keys -t canvas 'source ~/.agent-canvas.env && agent-canvas --backend-only --public' Enter
tmux attach-session -t canvas
Detach from tmux with Ctrl-b, then d. Reattach later with tmux attach-session -t canvas.

5. Choose an Access Method

Option A: SSH Tunnel

Use an SSH tunnel when you only need personal access and do not want to expose a public URL. On your laptop:
ssh -L 8000:127.0.0.1:8000 user@your-vm
Then use http://localhost:8000 as the backend URL in Manage Backends.

Option B: ngrok Without OAuth

Use ngrok without OAuth only for temporary testing or personal access. Keep --public enabled and use a strong LOCAL_BACKEND_API_KEY. On the VM, in a second terminal or tmux pane:
ngrok http 8000
Use the https://...ngrok-free.app forwarding URL:
  • Backend-only mode: enter it as the Host / Base URL in Manage Backends.
  • Full Canvas mode: open it directly in your browser.

Option C: ngrok With Google OAuth

Use ngrok OAuth with full Canvas deployments when the ngrok URL may be reachable by a team or a broader audience. OAuth is an additional gate in front of Agent Canvas; it does not replace LOCAL_BACKEND_API_KEY. For backend-only deployments, use ngrok without OAuth and keep --public enabled. OAuth is best suited to the full Canvas URL where the UI and backend share the same origin. Create ~/policy.yml, replacing openhands.dev with your allowed Google Workspace domain:
on_http_request:
  # Require Google OAuth login.
  - actions:
      - type: oauth
        config:
          provider: google

  # Deny anyone outside the allowed domain.
  - expressions:
      - "!actions.ngrok.oauth.identity.email.endsWith('@openhands.dev')"
    actions:
      - type: deny
        config:
          status_code: 403
Start ngrok with the traffic policy:
ngrok http 8000 --traffic-policy-file ~/policy.yml
To run full Canvas and ngrok side by side in tmux:
tmux new-session -d -s canvas
tmux send-keys -t canvas 'source ~/.agent-canvas.env && agent-canvas --public' Enter
tmux split-window -h -t canvas
tmux send-keys -t canvas 'ngrok http 8000 --traffic-policy-file ~/policy.yml' Enter
tmux attach-session -t canvas

Option D: Reverse Proxy With TLS

Use a reverse proxy when you need a stable domain instead of an ngrok URL. Point a domain at the VM, proxy it to 127.0.0.1:8000, and terminate TLS at the proxy. On Ubuntu, install nginx and Certbot:
sudo apt-get install -y nginx certbot python3-certbot-nginx
Create /etc/nginx/sites-available/canvas.example.com, replacing canvas.example.com with your domain:
server {
    listen 80;
    listen [::]:80;
    server_name canvas.example.com;

    location /.well-known/acme-challenge/ {
        root /var/www/html;
    }

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;
        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;

        # WebSocket / SSE support for live agent events.
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }
}
Enable the site and issue a certificate:
sudo ln -sf /etc/nginx/sites-available/canvas.example.com \
  /etc/nginx/sites-enabled/canvas.example.com
sudo nginx -t
sudo systemctl reload nginx

sudo certbot --nginx -d canvas.example.com \
  --non-interactive --agree-tos \
  --email you@example.com \
  --redirect
Use https://canvas.example.com as the URL for either the remote backend entry or the full Canvas UI.

Security Checklist

Before exposing Agent Canvas beyond an SSH tunnel:
  1. Run with --public and set a strong LOCAL_BACKEND_API_KEY.
  2. Restrict network access with a firewall, VPN, ngrok OAuth, or an identity-aware proxy.
  3. Use HTTPS for any internet-reachable URL.
  4. Limit who can SSH to the VM and keep the OS patched.
  5. Protect the VM filesystem because it stores settings, secrets, conversations, and working copies.
  6. Rotate keys if an ngrok URL, API key, or VM login is shared too broadly.