Skip to content

Deployment Guide

Cove is a static single-page application (SPA) that can be deployed anywhere you can serve static files.

Prerequisites

  • An OpenClaw gateway running and accessible from where you'll access Cove
  • The gateway must be reachable via WebSocket (ws:// or wss://)

Deployment Options

Using Docker Compose:

bash
# Clone the repo
git clone https://github.com/MaudeCode/cove.git
cd cove

# Start Cove
docker compose up -d

# Access at http://localhost:8080

Using Docker directly:

bash
# Build
docker build -t cove .

# Run (rootless, read-only filesystem)
docker run -d -p 8080:8080 --read-only --security-opt no-new-privileges:true \
  --cap-drop ALL --tmpfs /tmp --tmpfs /var/cache/nginx --tmpfs /var/run \
  --name cove cove

Using pre-built image:

bash
docker run -d -p 8080:8080 ghcr.io/maudecode/cove:latest

2. Static File Hosting

Build the app and serve the dist/ folder:

bash
# Build
bun install
bun run build

# The dist/ folder contains all static files
ls dist/

Then serve with any static file server:

Caddy:

bash
caddy file-server --root dist --listen :8080

Nginx:

nginx
server {
    listen 80;
    root /path/to/cove/dist;
    index index.html;
    
    location / {
        try_files $uri $uri/ /index.html;
    }
}

Python:

bash
cd dist && python -m http.server 8080

Node.js (serve):

bash
npx serve dist -p 8080 -s

3. Cloud Platforms

Cloudflare Pages

  1. Connect your GitHub repo to Cloudflare Pages
  2. Set build command: bun run build
  3. Set output directory: dist
  4. Deploy

Vercel

  1. Import your GitHub repo to Vercel
  2. Framework preset: Other
  3. Build command: bun run build
  4. Output directory: dist
  5. Deploy

Netlify

  1. Connect your GitHub repo to Netlify
  2. Build command: bun run build
  3. Publish directory: dist
  4. Deploy

Note: Add a _redirects file for SPA routing:

/* /index.html 200

4. Kubernetes

Example deployment:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: cove
spec:
  replicas: 2
  selector:
    matchLabels:
      app: cove
  template:
    metadata:
      labels:
        app: cove
    spec:
      containers:
        - name: cove
          image: ghcr.io/maudecode/cove:latest
          ports:
            - containerPort: 8080
          securityContext:
            runAsNonRoot: true
            runAsUser: 101
            readOnlyRootFilesystem: true
            allowPrivilegeEscalation: false
            capabilities:
              drop:
                - ALL
          volumeMounts:
            - name: tmp
              mountPath: /tmp
            - name: cache
              mountPath: /var/cache/nginx
            - name: run
              mountPath: /var/run
          resources:
            limits:
              memory: "64Mi"
              cpu: "100m"
          livenessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 30
      volumes:
        - name: tmp
          emptyDir: {}
        - name: cache
          emptyDir: {}
        - name: run
          emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
  name: cove
spec:
  selector:
    app: cove
  ports:
    - port: 80
      targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: cove
spec:
  rules:
    - host: cove.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: cove
                port:
                  number: 80

Configuration

Cove is configured entirely through the browser UI. There are no server-side environment variables.

When you first open Cove, you'll be prompted to enter:

  • Gateway URL: Your OpenClaw gateway WebSocket URL (e.g., wss://gateway.example.com)
  • Authentication: Either a token or password

These are stored in your browser's localStorage.

HTTPS Considerations

If your Cove instance is served over HTTPS, your OpenClaw gateway must also use WSS (WebSocket Secure). Browsers block mixed content (HTTPS page connecting to WS).

Options:

  1. Serve both Cove and gateway over HTTPS/WSS
  2. Serve both over HTTP/WS (local development only)
  3. Use a reverse proxy (Traefik, Caddy, nginx) to terminate TLS

Reverse Proxy Examples

Traefik

yaml
# docker-compose.yml with Traefik labels
services:
  cove:
    image: ghcr.io/maudecode/cove:latest
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.cove.rule=Host(`cove.example.com`)"
      - "traefik.http.routers.cove.entrypoints=websecure"
      - "traefik.http.routers.cove.tls.certresolver=letsencrypt"

Caddy

cove.example.com {
    root * /path/to/cove/dist
    file_server
    try_files {path} /index.html
}

nginx with SSL

nginx
server {
    listen 443 ssl http2;
    server_name cove.example.com;
    
    ssl_certificate /etc/ssl/certs/cove.crt;
    ssl_certificate_key /etc/ssl/private/cove.key;
    
    root /path/to/cove/dist;
    index index.html;
    
    location / {
        try_files $uri $uri/ /index.html;
    }
}

Updating

Docker

bash
docker pull ghcr.io/maudecode/cove:latest
docker compose down
docker compose up -d

Static Hosting

bash
git pull
bun install
bun run build
# Copy dist/ to your web server

Troubleshooting

"Connection failed" on connect

  1. Check gateway URL is correct (include wss:// or ws://)
  2. Verify gateway is running: curl -I https://your-gateway/health
  3. Check browser console for errors
  4. If using HTTPS, ensure gateway uses WSS

Blank page after deploy

  1. Check browser console for errors
  2. Verify SPA routing is configured (all routes → index.html)
  3. Check that all files in dist/ were uploaded

Styles look broken

  1. Clear browser cache (Ctrl+Shift+R)
  2. Check that CSS files are being served with correct MIME type
  3. Verify no CSP headers blocking inline styles

Resource Requirements

Cove is extremely lightweight:

  • Container memory: ~10-20MB
  • Container CPU: Minimal (static file serving only)
  • Browser: Any modern browser with WebSocket support
  • Disk: ~5MB for built assets

Released under the MIT License.