Skip to content

Web Services

The Control Center can expose web applications running inside the AI sandbox VM to the internet via Traefik reverse proxy.

How It Works

sequenceDiagram
    participant User as Browser
    participant Traefik
    participant CC as Control Center
    participant VM as AI VM

    User->>CC: POST /api/routes {subdomain: "myapp", vm_port: 8080}
    CC->>CC: Update vm-services.yml
    Note over Traefik: Watches file, auto-reloads
    User->>Traefik: https://myapp.clsxx.de
    Traefik->>VM: http://192.168.10.10:8080
    VM-->>Traefik: Response
    Traefik-->>User: HTTPS response
  1. The AI starts a web service on a port inside the VM
  2. You add a route via the Control Center: subdomain + port
  3. The Control Center generates a Traefik file provider YAML
  4. Traefik detects the change and creates the route
  5. Let's Encrypt automatically provisions a TLS certificate
  6. The service is available at https://<subdomain>.clsxx.de

Traefik File Provider

Routes are stored in two Traefik dynamic configuration files:

  • vm-services.yml — VM service routes (fully managed by Control Center)
  • host-services.yml — Host infrastructure routes (VPN toggle managed by Control Center)

Both files are mounted from the host's Traefik dynamic configuration directory.

# VM Services — managed by OpenClaw Control Center
# Auto-generated — edits will be overwritten by the UI
# Traefik watches this file and reloads automatically

http:
  routers:
    myapp:
      rule: Host(`myapp.clsxx.de`)
      entryPoints:
        - websecure
      service: myapp-svc
      tls:
        certResolver: letsencrypt
      middlewares:
        - auth
  services:
    myapp-svc:
      loadBalancer:
        servers:
          - url: http://192.168.10.10:8080

Authentication

By default, routes include the auth middleware (BasicAuth). This can be toggled per route:

Setting Behavior
auth_required: true Requires BasicAuth login (default)
auth_required: false Public access — no login needed

Public Services

Services without authentication are accessible to anyone on the internet. Only disable auth for services that have their own authentication.

VPN-Only Access

By default, all new routes are VPN-only (vpn_only: true). This restricts access to clients connected via WireGuard VPN.

VPN Only Auth Required Middleware Access Level
✅ Yes ✅ Yes secure-admin VPN + BasicAuth (default)
✅ Yes ✅ Yes secure-api VPN-only, no BasicAuth (API paths for AI agents)
✅ Yes ❌ No vpn-whitelist VPN only
❌ No ✅ Yes auth Public + BasicAuth
❌ No ❌ No — Fully public

The VPN-only flag can be toggled per route via the UI (clickable 🔒/🌐 button) or the API.

Default Security

The default vpn_only: true ensures services are not accidentally exposed to the public internet.

Managing Routes

Add a Route

curl -X POST http://localhost:8089/api/routes \
  -H "Content-Type: application/json" \
  -d '{"subdomain": "myapp", "vm_port": 8080, "auth_required": true, "vpn_only": true}'

List Routes

curl http://localhost:8089/api/routes

Toggle VPN-Only

curl -X PATCH http://localhost:8089/api/routes/<route_id> \
  -H "Content-Type: application/json" \
  -d '{"vpn_only": false}'

Remove a Route

curl -X DELETE http://localhost:8089/api/routes/<route_id>

Host Infrastructure Routes

Infrastructure services (Control Center, root redirect) are managed via host-services.yml. Their VPN-only status can be toggled through the UI or API.

List Host Routes

curl http://localhost:8089/api/routes/host

Toggle VPN-Only on Host Route

curl -X PATCH http://localhost:8089/api/routes/host/<route_id> \
  -H "Content-Type: application/json" \
  -d '{"vpn_only": false}'

Docker-label infrastructure routes (Traefik dashboard, Pi-hole, Fail2ban, Docs) are always VPN-only and cannot be toggled from the Control Center.

Current Routes

Domain Service Port Access
trading.clsxx.de Trading UI 5173 VPN + BasicAuth
trading-api.clsxx.de Trading API 8000 VPN + BasicAuth
trading-flower.clsxx.de Celery Flower 5555 VPN + BasicAuth
cloud.clsxx.de Nextcloud 8880 VPN + BasicAuth
git.clsxx.de Gitea 3000 VPN + BasicAuth
mail.clsxx.de Webmail (Rainloop) 8888 VPN + BasicAuth
portainer.clsxx.de Portainer 9000 VPN + BasicAuth
parts.clsxx.de Part Finder 8090 VPN + BasicAuth
dashboard.clsxx.de CLSXX Dashboard 8091 VPN + BasicAuth
dashboard.clsxx.de/api/* Dashboard API 8091 VPN-only (no auth)
tickets.clsxx.de/api/* Tickets API 8091 VPN-only (no auth)

DNS Requirement

For the route to work, the subdomain must resolve to the server's IP. Since *.clsxx.de is a wildcard DNS record pointing to 217.154.228.231, any subdomain works automatically.

Current Limitations

  • Routes can only point to the VM at 192.168.10.10
  • Only HTTP backends are supported (Traefik handles HTTPS termination)
  • No health checking — Traefik will return 502 if the VM service is down