Reverse Proxy
Put the bundled Caddy reverse proxy in front of IntelliAsk for HTTPS — TLS modes, enabling at provision time, and turning it on or off later without a full re-provision.
The stack ships a bundled Caddy reverse proxy (proxy.compose.yml) that
terminates TLS in front of IntelliAsk. It is opt-in: its PROXY_* settings live
in the single config/.env, and intelliask only references it when
PROXY_ENABLED is truthy.
Caddy is optional — bring your own proxy
The bundled Caddy proxy is provided purely as a convenience. It is in no way
required — IntelliAsk is just an HTTP app listening on port 3080, so you can put
any reverse proxy in front of it: nginx, Traefik, HAProxy, an
existing corporate load balancer, or a tunnel such as ngrok/Cloudflare
Tunnel.
To use your own, leave the bundled proxy disabled (PROXY_ENABLED=false, the
default) and point your proxy at the IntelliAsk container/host on port 3080. You'll
typically also want to:
- Set
INTELLIASK_BIND=127.0.0.1:(or a private interface) so the app port isn't exposed publicly and only your proxy can reach it. - Set
PUBLIC_SCHEME=https,PUBLIC_HOSTto your public DNS name, andTRUST_PROXY=1so IntelliAsk builds correct URLs and sees the real client IP behind your proxy.
The rest of this page covers only the bundled Caddy option; if you use your own proxy you can skip it entirely.
What the proxy changes
When the proxy is enabled:
- IntelliAsk is bound to loopback only (
127.0.0.1) and the proxy publishes the public port instead —443for any TLS mode, or80foroff.
The proxy only fronts the IntelliAsk web UI. The Code Interpreter (codeapi) is
reached directly over the internal network with a signed JWT, so it does not
depend on the proxy.
When disabled, only the IntelliAsk UI (3080) and exporter (9100) are published
to the host; everything else stays internal.
TLS modes
| Mode | Behaviour | Use when |
|---|---|---|
internal (default) | Caddy's internal CA issues a cert. HTTPS works immediately, no files or public DNS needed. | Internal hosts / first-time setup. |
file | Uses a supplied cert.pem / key.pem (e.g. an internal-CA certificate). | You have your own certificate. |
auto | Public ACME / Let's Encrypt certificates. Requires public DNS pointing at the host and an ACME email. | Public-facing deployments. |
off | Plain HTTP on port 80, no certificate. | Behind another TLS terminator. |
The default internal mode means first-time provisioning gets working HTTPS
without requiring cert.pem/key.pem.
Enable at provision time
--proxy-mode implies --with-proxy. The choice is persisted as PROXY_ENABLED
in config/.env, so day-2 commands and the systemd service honour it too.
Provision asks for the public DNS name
When the proxy is enabled, the interactive Configuration step of provision
prompts for the public DNS name clients use to reach IntelliAsk and stores it as
PUBLIC_HOST in config/.env (Caddy's server_name). It also offers to expose the
metrics exporter through the proxy — see Exposing the metrics exporter.
Exposing the metrics exporter
The Prometheus exporter can optionally be served through the proxy under its own
DNS name (with the same TLS mode), instead of publishing host port 9100. Toggle it
with flags on module enable proxy, which sets everything up and re-applies in one
step:
--exporter-host sets EXPORTER_PROXY_ENABLED=true and EXPORTER_PUBLIC_HOST, and
(unless you've already set it) defaults EXPORTER_BIND=127.0.0.1: so the raw :9100
port stays off the public interface. You can pass it alongside the other proxy flags
in one call:
Caddy adds a second site for EXPORTER_PUBLIC_HOST that reverse-proxies to the
exporter (EXPORTER_PROXY_UPSTREAM, default exporter:8000), sharing the stack's
TLS mode. When TLS mode is off the exporter site is skipped (it needs a hostname).
At provision time the interactive Configuration step also offers this when the proxy
is enabled. See the Prometheus Exporter
page for the metrics details.
Bring-your-own proxy for the exporter too
This Caddy-based exposure is just a convenience — like the main app, the exporter is
plain HTTP (container port 8000, host port 9100), so any reverse proxy
(nginx, Traefik, ngrok, …) can front it. To do it yourself, leave
EXPORTER_PROXY_ENABLED=false, set EXPORTER_BIND=127.0.0.1: so the raw :9100
port isn't public, and point your proxy at the exporter on port 9100 (host) or
exporter:8000 (in-network).
Or set the variables by hand
Those flags just write these keys in config/.env and re-render the Caddyfile
— you can edit them directly and run intelliask up (or intelliask module enable proxy) instead:
Turn it on or off later
You don't need a full re-provision to change the proxy. The proxy is an optional
module; toggle it with
intelliask module (it edits config/.env and re-applies):
| Flag | Effect |
|---|---|
--mode <mode> | TLS mode for enable: file | internal | auto | off. Defaults to whatever is in config/.env (or internal). |
--email <addr> | ACME contact email (only used by --mode auto). |
--host <name> | Public DNS name for IntelliAsk (sets PUBLIC_HOST). |
--exporter-host <name> | Also expose the metrics exporter through the proxy under this DNS name. |
--no-exporter | Stop fronting the exporter through the proxy, keeping the proxy up. |
--no-apply | Write the env changes but don't touch Docker (apply later with intelliask up). |
Enabling/disabling flips PROXY_ENABLED and INTELLIASK_BIND in config/.env,
then recreates the stack so the change takes effect.
Setting the public DNS name
module enable proxy no longer prompts for a hostname — pass --host <name> (or set
PUBLIC_HOST in config/.env) for auto/file modes. internal and off modes
don't need one. Re-running intelliask provision --with-proxy will prompt for it
interactively instead.
file mode certificates
For --proxy-mode file, place your cert.pem and key.pem where the proxy
expects them (under config/proxy/) before enabling. For auto, make sure the
host's public DNS record already resolves to the VM so ACME validation can succeed.
Last updated on