TLS and your reverse proxy
The recommended setup is to run the install behind a reverse proxy or load
balancer you already have, and let it terminate TLS. That’s what
veltro install does by default (--tls off): the gateway serves plain HTTP
on VELTRO_HTTP_PORT and your proxy sends every request to it. If you don’t
have a proxy, the installer can run one for you; see
the bundled TLS front end below.
Behind your own proxy
Section titled “Behind your own proxy”1. Install without starting
Section titled “1. Install without starting”Install with the address people will type, over https, and stop before anything starts:
veltro install --products <products> --public-url https://soc.example.com --skip-up--public-url is saved as PUBLIC_BASE_URL in .env. Identity issues
sessions and request assertions for that origin, and the products build their
links from it, so it must be exactly the URL your proxy serves, with no path.
To change it later, run veltro install again with the new --public-url.
2. Keep the gateway private, then start
Section titled “2. Keep the gateway private, then start”The gateway listens on port 80 on every interface by default, which is also
the port a proxy on the same host usually holds. Bind the gateway to loopback
in .env before the first start:
VELTRO_HTTP_PORT=127.0.0.1:8088veltro upWhen the proxy runs somewhere else, leave the port where you want it and firewall it so only the proxy can reach it. Either way, plain HTTP should never leave the host or the private network.
3. Point the proxy at the gateway
Section titled “3. Point the proxy at the gateway”The whole install is one site on one origin: Home and Settings at /, the
products at /vectorflow, /sigmatic/ and /warden/, and MCP at /mcp. Send
all of it to the gateway, with no path rewriting. Your proxy must:
- keep the
Hostheader the client sent; - set
X-Forwarded-For, which the gateway appends to; - set
X-Forwarded-Proto: https. The gateway passeshttpson to the products and sayshttpotherwise. Identity doesn’t trust the header: its cookies areSecurebecausePUBLIC_BASE_URLstarts withhttps://; - pass WebSocket upgrades (
UpgradeandConnection), because Sigmatic’s and Warden’s live updates use them; - stream responses without buffering, and allow long reads: event streams and the VectorFlow agent’s long poll stay open, and the gateway allows 24 hours;
- accept request bodies up to 64 MB, the size of the log shipper batches on
/api/logs/and the agent batches on/api/agent/.
soc.example.com { reverse_proxy 127.0.0.1:8088}That’s all Caddy needs. It gets a certificate for the name, keeps Host,
sets the X-Forwarded-* headers, passes WebSockets, flushes event streams
straight away, and sets no request body limit unless you add one.
# In the http block:map $http_upgrade $connection_upgrade { default upgrade; '' close;}
server { listen 80; server_name soc.example.com; return 301 https://$host$request_uri;}
server { listen 443 ssl; server_name soc.example.com; ssl_certificate /etc/ssl/soc.example.com/fullchain.pem; ssl_certificate_key /etc/ssl/soc.example.com/privkey.pem;
client_max_body_size 64m;
location / { proxy_pass http://127.0.0.1:8088; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_buffering off; proxy_read_timeout 24h; proxy_send_timeout 24h; }}nginx’s defaults would break the install without these lines: it replaces
Host with the upstream address, drops WebSocket upgrades, buffers event
streams, closes idle reads after 60 seconds and refuses bodies over 1 MB.
4. Check it
Section titled “4. Check it”curl -I https://soc.example.com/api/health/readyA 200 means the proxy reaches the gateway and identity is ready. Then sign
in at https://soc.example.com/login.
With Sigmatic installed, log shippers can use the same proxy: Sigmatic’s ingest API is
at /api/logs/ on the public URL. The separate ingest listener on port 8001
stays private; see
Install Sigmatic.
The bundled TLS front end
Section titled “The bundled TLS front end”For an install with no proxy in front, --tls adds the tls compose profile
(compose/tls.yml): Caddy 2.9.1-alpine in front of the gateway
(veltro-nginx:80). The installer generates its Caddyfile from
veltro.toml, so you choose a mode instead of editing configuration by hand.
| Mode | Behaviour |
|---|---|
internal |
Caddy’s own CA, for a LAN. The root to trust is at tls/caddy-data/caddy/pki/authorities/local/root.crt |
custom |
Mount your own tls/fullchain.pem and tls/privkey.pem |
off |
No front end. Run behind your own proxy, as above (the default) |
veltro install --products <products> --public-url https://example.com --tls customveltro up --tls custom # or: make up TLS=customThe bundled Caddy doesn’t get certificates from Let’s Encrypt or any other
ACME CA. For a publicly trusted certificate, either run your own proxy or put
the certificate in tls/ and use custom; renewing it is up to you. An
install made with the old --tls auto stops before it changes anything until
you move it to one of those. See
Bundled Let’s Encrypt TLS was removed.
Caddy serves HTTPS on the port in --public-url (443 when there isn’t one)
and HTTP on VELTRO_TLS_HTTP_PORT (80). The host publishes the same HTTPS port
unless you set VELTRO_HTTPS_PORT, for example behind NAT. The URL can’t use
80, 2019 or 8443. The installer moves the gateway to
loopback (127.0.0.1:8088 by default) so Caddy is the only public listener.
VELTRO_TLS_MODE records the selected mode. On a --tls internal install,
veltro status and veltro demo seed trust the install’s own root, so they
work on the host without extra setup.
With Sigmatic installed, the front end also serves Sigmatic’s log ingest over TLS on
VELTRO_TLS_INGEST_PORT (8443); see
Install Sigmatic.