# How to Configure ClosedClaw Gateway Exposure: Local, LAN, Tailscale, and Public Access Options

> Explore ClosedClaw gateway exposure options: local, LAN, Tailscale, and public access. Learn how to configure these modes easily for your security needs. Get secure access now.

- Repository: [aSafeLobotomy/closedclaw](https://github.com/asafelobotomy/closedclaw)
- Tags: how-to-guide
- Published: 2026-02-25

---

**ClosedClaw supports five distinct gateway exposure modes—loopback, LAN, direct Tailnet, Tailscale Serve, and Tailscale Funnel—controlled via the `gateway.bind` and `gateway.tailscale.mode` configuration fields defined in [`src/config/zod-schema.ts`](https://github.com/asafelobotomy/closedclaw/blob/main/src/config/zod-schema.ts).**

The ClosedClaw gateway serves as the central WebSocket server that all UI clients (Web, TUI, desktop, and Chrome extension) and node-hosts connect to. The `asafelobotomy/closedclaw` repository exposes network accessibility through a strict configuration schema, allowing you to bind the server to specific interfaces or proxy through Tailscale for secure remote access.

## Gateway Bind Modes

The `gateway.bind` field in [`src/config/zod-schema.ts`](https://github.com/asafelobotomy/closedclaw/blob/main/src/config/zod-schema.ts) (lines 3009–3015) accepts five string values that determine which network interface the WebSocket listener binds to:

- **`"loopback"`** – Binds exclusively to `127.0.0.1`, restricting access to the local machine only.
- **`"lan"`** – Discovers and binds to the host’s LAN IP address (e.g., `192.168.x.x`), allowing other devices on the same network to connect.
- **`"tailnet"`** – Binds directly to the machine’s Tailscale IP (e.g., `100.x.x.x`) without using Tailscale Serve or Funnel, exposing the service only to your Tailnet.
- **`"auto"`** – Defaults to loopback, but falls back to `0.0.0.0` if Tailscale automation is enabled.
- **`"custom"`** – Allows binding to an explicit address specified in `gateway.customBindHost`.

When the gateway starts, [`src/gateway/server-startup.ts`](https://github.com/asafelobotomy/closedclaw/blob/main/src/gateway/server-startup.ts) reads the resolved configuration and instantiates the `GatewayServer` on the address dictated by this setting.

## Tailscale Integration Modes

The `gateway.tailscale.mode` field (defined in [`src/config/zod-schema.ts`](https://github.com/asafelobotomy/closedclaw/blob/main/src/config/zod-schema.ts) lines 3036–3040) automates Tailscale tunneling for the Control UI and WebSocket endpoint:

- **`"off"`** – Disables Tailscale automation; the gateway listens directly on the interface determined by `gateway.bind`.
- **`"serve"`** – Keeps the gateway bound to `127.0.0.1` while Tailscale creates an HTTPS proxy via `tailscale serve`, making the service accessible only within your Tailnet.
- **`"funnel"`** – Uses `tailscale funnel` to expose a public HTTPS endpoint on the internet. This mode **requires** password-based authentication (`gateway.auth.mode: "password"`).

The Tailscale helper logic in [`src/infra/tailscale.ts`](https://github.com/asafelobotomy/closedclaw/blob/main/src/infra/tailscale.ts) executes the appropriate CLI commands during server startup and handles cleanup on exit.

## Authentication Requirements

The `gateway.auth` object (lines 3026–3033) controls how clients authenticate to the gateway:

- **`mode: "token"`** – Uses a random secret token. When the `ClosedClaw_GATEWAY_TOKEN` environment variable is present, the system defaults to this mode.
- **`mode: "password"`** – Uses a shared secret string. Required when using `tailscale.mode: "funnel"`.
- **`allowTailscale: true`** – When combined with `tailscale.mode: "serve"`, clients can authenticate via Tailscale identity headers instead of presenting a token or password. The gateway validates these headers against `tailscale whois` data in [`src/gateway/protocol/auth.ts`](https://github.com/asafelobotomy/closedclaw/blob/main/src/gateway/protocol/auth.ts).

## Remote Gateway Mode

For scenarios where the UI runs on a different machine than the gateway process, the `gateway.remote` object (lines 3044–3050) configures the local instance to act as a client bridge:

```json5
{
  "gateway": {
    "remote": {
      "url": "ssh://user@host:22",
      "transport": "ssh",
      "token": "my-gateway-token",
      "sshIdentity": "~/.ssh/id_ed25519"
    }
  }
}

```

This setting makes the local process forward client traffic to a remote gateway endpoint while preserving authentication handling.

## Configuration Examples

### Local Development (Loopback Only)

For single-machine development where only local clients connect:

```json5
{
  "gateway": {
    "bind": "loopback",
    "auth": { "mode": "token" }
  }
}

```

The UI connects to `ws://127.0.0.1:18789`.

### LAN Network Sharing

To allow other devices on your private network to access the gateway:

```json5
{
  "gateway": {
    "bind": "lan",
    "auth": { "mode": "token" }
  }
}

```

CLI shortcut:

```bash
ClosedClaw gateway --bind lan

```

### Direct Tailnet Binding

Expose the gateway directly on your Tailscale IP without HTTPS proxying:

```json5
{
  "gateway": {
    "bind": "tailnet",
    "auth": { 
      "mode": "token", 
      "token": "my-secret" 
    }
  }
}

```

Connect from another Tailnet device:

```bash
ClosedClaw tui --url ws://100.123.45.67:18789 --token my-secret

```

### Tailscale Serve (Tailnet HTTPS)

Secure your gateway with HTTPS within your Tailnet only:

```json5
{
  "gateway": {
    "bind": "loopback",
    "tailscale": { "mode": "serve" },
    "auth": { 
      "mode": "token", 
      "allowTailscale": true 
    }
  }
}

```

The Control UI becomes reachable at `https://<magic-dns>/` using Tailscale identity headers for authentication.

### Tailscale Funnel (Public Internet)

Expose the dashboard publicly with password protection:

```json5
{
  "gateway": {
    "bind": "loopback",
    "tailscale": { "mode": "funnel" },
    "auth": { 
      "mode": "password", 
      "password": "replace-me" 
    }
  }
}

```

CLI command:

```bash
ClosedClaw gateway --tailscale funnel --auth password

```

### Remote Gateway via SSH

Run the UI locally while the gateway process operates on a remote headless server:

```json5
{
  "gateway": {
    "mode": "remote",
    "remote": {
      "url": "ssh://user@host:22",
      "token": "my-gateway-token"
    }
  }
}

```

## Implementation Architecture

During startup, [`src/gateway/server-startup.ts`](https://github.com/asafelobotomy/closedclaw/blob/main/src/gateway/server-startup.ts) resolves the configuration (including wizard overrides from [`src/wizard/onboarding.gateway-config.ts`](https://github.com/asafelobotomy/closedclaw/blob/main/src/wizard/onboarding.gateway-config.ts)) and initializes the `GatewayServer`. If `gateway.tailscale.mode` is active, [`src/infra/tailscale.ts`](https://github.com/asafelobotomy/closedclaw/blob/main/src/infra/tailscale.ts) establishes the tunnel before the WebSocket listener starts.

When clients connect, [`src/gateway/protocol/auth.ts`](https://github.com/asafelobotomy/closedclaw/blob/main/src/gateway/protocol/auth.ts) validates credentials against the `gateway.auth` schema. For Tailscale Serve with `allowTailscale: true`, the system inspects `x-forwarded-for` and `x-forwarded-proto` headers to verify the Tailnet node identity before accepting the connection.

## Summary

- **Five bind modes** control network exposure: `loopback`, `lan`, `tailnet`, `custom`, and `auto`, defined in [`src/config/zod-schema.ts`](https://github.com/asafelobotomy/closedclaw/blob/main/src/config/zod-schema.ts).
- **Tailscale integration** offers three tiers: disabled (`off`), Tailnet-only HTTPS (`serve`), and public internet (`funnel`), implemented in [`src/infra/tailscale.ts`](https://github.com/asafelobotomy/closedclaw/blob/main/src/infra/tailscale.ts).
- **Funnel mode requires password authentication**; standard token auth is insufficient for public exposure.
- **Tailnet identity authentication** allows passwordless access when using `tailscale.serve` with `allowTailscale: true`.
- **Remote gateway mode** supports SSH tunneling for split UI/gateway architectures.
- All configuration changes can be applied via the onboarding wizard, the `ClosedClaw configure gateway` CLI, or direct edits to `~/.ClosedClaw/ClosedClaw.json`.

## Frequently Asked Questions

### What is the default gateway exposure mode in ClosedClaw?

The default configuration uses `gateway.bind: "auto"`, which prefers `loopback` (127.0.0.1) for security. If Tailscale automation is detected during startup, it falls back to `0.0.0.0` to accommodate the proxy, though the service remains protected by your Tailnet ACLs.

### Can I use token authentication with Tailscale Funnel?

No. The `tailscale.mode: "funnel"` configuration explicitly requires `gateway.auth.mode: "password"` because the endpoint is exposed to the public internet. Token-based authentication is permitted for `loopback`, `lan`, and `tailnet` bindings, as well as `tailscale.serve` when combined with Tailscale identity verification.

### How does ClosedClaw validate Tailscale identity headers?

When `allowTailscale: true` is set alongside `tailscale.mode: "serve"`, the authentication handler in [`src/gateway/protocol/auth.ts`](https://github.com/asafelobotomy/closedclaw/blob/main/src/gateway/protocol/auth.ts) inspects incoming requests for Tailscale-specific headers. It executes `tailscale whois` to verify that the connecting node belongs to your Tailnet, bypassing the token/password requirement only for verified Tailscale identities.

### What port does the ClosedClaw gateway use?

The gateway listens on port **18789** by default for WebSocket connections. This port is used across all bind modes, though the accessibility depends on your `gateway.bind` setting—whether bound to localhost, LAN, Tailscale IP, or proxied through Tailscale Serve/Funnel on standard HTTPS ports.