Skip to main content
Caddy 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:

Caddyfile

Public domain (Let’s Encrypt)

Caddy automatically provisions and renews TLS certificates for any public domain. No extra directives are needed.
Caddyfile
Save the file and run:
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.
Caddyfile
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.

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.
.env
NEXT_PUBLIC_BUILDER_URL and BETTER_AUTH_URL must match exactly. A mismatch causes authentication callbacks to fail.

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:
.env
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.

Running Caddy with Docker Compose

If you run Caddy inside the same Docker Compose stack, use the container service name instead of localhost:
Caddyfile
docker-compose.yml
Caddy stores certificate data in the caddy-data volume. Keeping this volume across container restarts prevents unnecessary certificate re-issuance.