> ## Documentation Index
> Fetch the complete documentation index at: https://chatbotx.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Caddy

> Configure Caddy as a reverse proxy for ChatbotX.

[Caddy](https://caddyserver.com) is the simplest way to put ChatbotX behind a reverse proxy. It handles TLS certificates automatically via Let's Encrypt with zero extra configuration.

ChatbotX exposes two services that need to be proxied:

| Service                       | Internal port | Recommended subdomain |
| ----------------------------- | ------------- | --------------------- |
| **Builder** (web UI + API)    | `3123`        | `app.yourdomain.com`  |
| **Realtime** (WebSocket)      | `1999`        | `ws.yourdomain.com`   |
| **Storage** (S3 API + assets) | `9000`        | `cdn.yourdomain.com`  |

***

## Caddyfile

### Public domain (Let's Encrypt)

Caddy automatically provisions and renews TLS certificates for any public domain. No extra directives are needed.

```caddy Caddyfile theme={null}
app.yourdomain.com {
    reverse_proxy localhost:3123
}

ws.yourdomain.com {
    reverse_proxy localhost:1999
}

cdn.yourdomain.com {
    reverse_proxy localhost:9000
}
```

Save the file and run:

```bash theme={null}
caddy reload
```

Caddy will obtain Let's Encrypt certificates on the first request to each domain.

***

### Local / internal network (self-signed)

For private networks or development hosts that are not publicly reachable, use `tls internal` to generate a locally-trusted certificate with Caddy's built-in CA.

```caddy Caddyfile theme={null}
app.chatbotx.local {
    reverse_proxy localhost:3123
    tls internal
}

ws.chatbotx.local {
    reverse_proxy localhost:1999
    tls internal
}

cdn.chatbotx.local {
    reverse_proxy localhost:9000
    tls internal
}
```

<Note>
  Browsers will show a certificate warning until you install Caddy's root CA. Run `caddy trust` to add it to your system trust store, then restart the browser.
</Note>

***

## ChatbotX configuration

After setting up the proxy, update the following variables in your `.env` to use the public HTTPS URLs. Restarting the services picks up the new values.

```bash .env theme={null}
NEXT_PUBLIC_BUILDER_URL=https://app.yourdomain.com
NEXT_PUBLIC_REALTIME_URL=https://ws.yourdomain.com
BETTER_AUTH_URL=https://app.yourdomain.com
NEXT_PUBLIC_ASSET_URL=https://cdn.yourdomain.com/chatbotx/public/
S3_ENDPOINT=https://cdn.yourdomain.com
```

<Warning>
  `NEXT_PUBLIC_BUILDER_URL` and `BETTER_AUTH_URL` must match exactly. A mismatch causes authentication callbacks to fail.
</Warning>

***

## WebSocket support

Caddy's `reverse_proxy` directive proxies WebSocket connections transparently — no additional configuration is required for PartySocket. The `Upgrade` and `Connection` headers are forwarded automatically.

***

## Storage (RustFS / S3)

The storage service (RustFS) runs on port `9000` and serves user-uploaded files and generated assets. Proxying it through Caddy gives you HTTPS asset URLs and avoids exposing the raw port to the internet.

Set `NEXT_PUBLIC_ASSET_URL` to the public path of your bucket's public folder, and `S3_ENDPOINT` to the root of the storage domain so the Builder and Worker can upload files:

```bash .env theme={null}
NEXT_PUBLIC_ASSET_URL=https://cdn.yourdomain.com/chatbotx/public/
S3_ENDPOINT=https://cdn.yourdomain.com
```

<Note>
  The storage console (port `9001`) does not need to be publicly exposed. Access it directly on the server with an SSH tunnel or restrict it to an internal network interface.
</Note>

***

## Running Caddy with Docker Compose

If you run Caddy inside the same Docker Compose stack, use the container service name instead of `localhost`:

```caddy Caddyfile theme={null}
app.yourdomain.com {
    reverse_proxy builder:3000
}

ws.yourdomain.com {
    reverse_proxy partysocket:1999
}

cdn.yourdomain.com {
    reverse_proxy filesystem:9000
}
```

```yaml docker-compose.yml theme={null}
services:
  caddy:
    image: caddy:2-alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy-data:/data
      - caddy-config:/config
    networks:
      - chatbotx-network

volumes:
  caddy-data:
  caddy-config:
```

<Tip>
  Caddy stores certificate data in the `caddy-data` volume. Keeping this volume across container restarts prevents unnecessary certificate re-issuance.
</Tip>
