Skip to main content

Tutorial: Secure OpenClaw on a Linux Server Using CloudConnexa and Caddy

Abstract

Secure OpenClaw with CloudConnexa using a private tunnel, HTTPS reverse proxy, and Host Connector for remote access without exposing public ports.

Overview

This guide shows how to securely deploy OpenClaw and make it accessible over CloudConnexa without exposing it to the public internet.

This setup uses:

  • CloudConnexa Host Connector — provides private, always-on access.

  • Caddy reverse proxy — enables HTTPS access.

  • OpenClaw gateway — runs locally on your server.

Users connect through CloudConnexa and access OpenClaw using a private domain and tunnel IP.

Architecture

[Authorized CloudConnexa Users]
        ↓ (Tunnel)
[CloudConnexa]
        ↓
[Host Connector on your VM] ← always-on tunnel, stable IP (e.g., 100.96.x.x)
        ↓
[Caddy Reverse Proxy] ← HTTPS/TCP443, proxies to localhost:18789
        ↓
[OpenClaw Gateway] ← systemd service, localhost:18789, token auth + device pairing
        ↓
[Claude / OpenAI / ... APIs]

Before you begin

Ensure you have the following:

  • Linux VM (Ubuntu 22.04/24.04 recommended) with at least 2 GB RAM (4 GB recommended) and 10 GB disk space

  • Root or sudo access

  • CloudConnexa account

  • OpenClaw API key (OpenAI, Anthropic, etc.)

Step 1: Install OpenClaw

  1. Install OpenClaw using the official guide: OpenClaw Install.

  2. Run onboarding (if not prompted automatically):

    openclaw onboard

    Important

    Ensure you run the onboarding wizard as a non-root user so the systemd service installs correctly.

  3. Follow the prompts to:

    • Select your AI provider.

    • Enter your API key.

    • Configure defaults.

1.1 Retrieve the gateway token

The gateway token is displayed at the end of the onboarding wizard. Copy it for use later.

If you need to find it again:

  1. Run:

    openclaw dashboard --no-open
  2. Copy the token value from:

    Dashboard URL: http://127.0.0.1:18789/#token=

Step 2: Create a host in CloudConnexa

The CloudConnexa host connector installs directly on your application server, enabling access to applications running on that machine.

  1. Navigate to Hosts → Hosts.

  2. Click Add Host.

  3. Configure:

    • Name: OpenClaw

    • Domain Name: openclaw.local (CloudConnexa will automatically resolve this domain to the Connector's tunnel IP for users connected to the WPC.)

    • Connector name

    • Region

  4. Click Finish.

    Important

    The domain name you choose here (e.g., openclaw.local) will be used throughout this guide. If you use a different domain, replace openclaw.local in all subsequent steps.

Step 3: Deploy the host connector

  1. Open the new Host, and click the Connectors tab.

  2. Click Deploy → Deploy Connector.

  3. Select your Linux distribution running on your VM.

  4. Run the provided script on your VM's terminal.

  5. Paste the token shown under "Generate Token" (located below the script).

  6. Click Next.

  7. Verify that the Connector shows "Connected."

  8. Record the tunnel IP shown next to the Connector (e.g., 100.96.1.50) for a later step.

Step 4: Configure applications (optional)

Define which services are exposed so that granular access control can be configured.

  1. Open the new Host, and click the Applications tab.

  2. Click Add Application.

  3. Add an application for HTTPS:

    • Name: OpenClaw HTTPS

    • Protocol: TCP

    • Port: 443

  4. (Optional) Add an application for HTTP (useful for curl testing from the tunnel):

    • Name: OpenClaw HTTP

    • Protocol: TCP

    • Port: 80

  5. Save and ensure the appropriate Access Groups have permission to reach these Applications.

Step 5: Install and configure Caddy

  1. Install Caddy following the official documentation: Caddy Install.

  2. Detect the CloudConnexa tunnel IP:

    TUNNEL_IP=$(sudo openvpn3 sessions-list | grep 'tun' | awk -F ':' '{print $3}') && \
    TUNNEL_IP=$(ip -4 addr show $TUNNEL_IP | grep -oP '(?:\b\.?(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){4}' | head -1)
    
    echo "Detected tunnel IP: $TUNNEL_IP"
  3. Verify this matches the tunnel IP shown in the CloudConnexa Admin portal (Step 3: Deploy the host connector). If it doesn't, set it manually:

    TUNNEL_IP='100.96.1.50'
  4. Create the Caddyfile:

    sudo tee /etc/caddy/Caddyfile > /dev/null << EOF
    https://$TUNNEL_IP, https://openclaw.local1c {
        tls internal
        reverse_proxy 127.0.0.1:18789
    }
    EOF

    1

    Replace openclaw.local with your Host domain if different.

  5. Restart:

    sudo systemctl restart caddy

Step 6: Configure allowed origins

The Control UI rejects requests from origins not in its allowlist.

  • Configure the allowed HTTPS domain and tunnel IP used by CloudConnexa:

    TUNNEL_IP=$(sudo openvpn3 sessions-list | grep 'tun' | awk -F ':' '{print $3}') && \
    TUNNEL_IP=$(ip -4 addr show $TUNNEL_IP | grep -oP '(?:\b\.?(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){4}' | head -1)
    
    openclaw config set gateway.controlUi.allowedOrigins "[\"https://$TUNNEL_IP\",\"https://openclaw.local1\"]" --strict-json

    1

    Replace openclaw.local with your Host domain if different.

Step 7: Access OpenClaw remotely

  1. Connect to CloudConnexa.

  2. In a web browser, navigate to:

    https://openclaw.local1/#token=<your-token>2

    1

    Replace openclaw.local with your Host domain if different.

    2

    Replace <your-token> with the gateway token from Step 1: Install OpenClaw.

  3. Accept the certificate warning. (Caddy uses a self-signed internal certificate.)

Step 8: Approve the device

On first connection from a new browser, the Control UI will show "pairing required". This is expected; the gateway requires device approval as an additional layer of security on top of token authentication.

  1. Connect to your server.

  2. List pending device requests:

    openclaw devices list
  3. Note the device ID you'll need to approve.

  4. Approve the device:

    openclaw devices approve <requestId>1

    1

    Replace <requestId> with the ID from the device list.

  5. Refresh the browser.

  6. The Control UI should now load.

    Note

    Each browser/device needs approval once. After approval, it's remembered across sessions.