docs/content/advanced/reverse-proxy-tls.md
When running LocalAI behind a TLS termination reverse proxy, the Web UI may fail to load static assets (CSS, JS) correctly because the application doesn't automatically detect that it's being served over HTTPS. This guide explains how to properly configure your reverse proxy to work with LocalAI.
LocalAI uses the X-Forwarded-Proto HTTP header to determine the protocol used by clients. When this header is set to https, LocalAI will generate HTTPS URLs for static assets in the Web UI.
LocalAI does not terminate TLS itself, so HTTPS is provided by a reverse proxy in front of it. Self-referential links (generated image and video URLs, async job status URLs, OAuth callbacks) need the externally visible scheme, host and port.
LocalAI determines these in this order:
LOCALAI_BASE_URL - if set, it is authoritative for the origin. Set it to
the externally visible base URL, e.g. LOCALAI_BASE_URL=https://localai.example.com
or https://192.168.0.13:34567. Recommended whenever links come back with
the wrong scheme or host.X-Forwarded-Proto and X-Forwarded-Host headers (or the
RFC 7239 Forwarded header) sent by the proxy. Ensure your proxy forwards
X-Forwarded-Proto: https.A reverse-proxy subpath mount is supported via X-Forwarded-Prefix; it is
appended to LOCALAI_BASE_URL when both are present.
Your reverse proxy must forward these headers to LocalAI:
| Header | Purpose |
|---|---|
X-Forwarded-Proto | Set to https when TLS is terminated at the proxy |
X-Forwarded-Host | The original host requested by the client |
X-Forwarded-Prefix | Any path prefix if LocalAI is served under a sub-path |
frontend https-in
bind *:443 ssl crt /path/to/cert.pem
mode http
# Set the X-Forwarded-Proto header
http-request set-header X-Forwarded-Proto https
# Pass the original host
http-request set-header X-Forwarded-Host %[hdr(host)]
# If serving under a sub-path, set the prefix
# http-request set-header X-Forwarded-Prefix /localai
default_backend localai
backend localai
mode http
server localai1 127.0.0.1:8080 check
<VirtualHost *:443>
ServerName your-domain.com
SSLEngine on
SSLCertificateFile /path/to/cert.pem
SSLCertificateKeyFile /path/to/key.pem
# Enable proxy and headers modules
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
# Set the X-Forwarded-Proto header
RequestHeader set X-Forwarded-Proto "https"
# Set the X-Forwarded-Host header (optional, usually automatic)
RequestHeader set X-Forwarded-Host "%{HTTP_HOST}s"
# If serving under a sub-path
# RequestHeader set X-Forwarded-Prefix "/localai"
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>
server {
listen 443 ssl;
server_name your-domain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# Allow multimodal requests with images or other large inputs.
client_max_body_size 50m;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
# Set the externally visible scheme and host.
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header Host $host;
# If serving under a sub-path
# proxy_set_header X-Forwarded-Prefix /localai;
# Local inference can take much longer than common proxy defaults.
proxy_connect_timeout 60s;
proxy_send_timeout 60m;
proxy_read_timeout 60m;
# Stream responses as LocalAI emits them. Disabling request buffering is
# optional and can help when clients upload large multimodal inputs.
proxy_buffering off;
proxy_request_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_cache_bypass $http_upgrade;
}
}
Adjust the 60m values for the slowest request you expect to serve. The
important setting for long non-streaming requests is proxy_read_timeout: if
the proxy stops waiting before LocalAI finishes, clients receive a proxy-generated
504 Gateway Time-out even though inference may still be running. OpenResty,
Nginx Proxy Manager, Caddy, Traefik, HAProxy, and ingress controllers have
equivalent upstream response timeout settings.
For bulk jobs on a trusted private network, you can also bypass the public
reverse proxy and connect directly to LocalAI, for example
http://localai-host:8080/v1.
If you serve LocalAI under a sub-path (e.g., https://your-domain.com/localai), you need to:
X-Forwarded-Prefix headerExample with Nginx:
proxy_set_header X-Forwarded-Prefix /localai;
localaihttps:// URLs for static assetsX-Forwarded-Proto header is being forwardedhttps (lowercase)X-Forwarded-Proto header is set before LocalAI processes the requestX-Forwarded-Proto is not being set to both http and httpsAn HTML 504 Gateway Time-out page branded by Nginx or OpenResty means the
reverse proxy stopped waiting for LocalAI. Increase the proxy's upstream read
and send timeouts beyond the worst-case inference time. Also check its request
body limit when sending images, audio, or other large inputs.
This is separate from LocalAI's optional busy watchdog. If busy watchdog checks
are enabled, set LOCALAI_WATCHDOG_BUSY_TIMEOUT beyond the longest expected
request or disable the busy check for workloads that legitimately run longer.
The default busy timeout is 5 minutes, but it is only enforced when the busy
watchdog is enabled.
When using reverse proxies, ensure your proxy only accepts connections from trusted sources and properly validates SSL certificates. Never expose LocalAI directly to the internet without TLS termination.