Files
ThothII/docs/install/reverse-proxy-nginx.md
T

133 lines
5.6 KiB
Markdown

# Put ThothII behind Nginx
This example assumes Nginx runs on the Linux host, ThothII `frontend` listens only on
`127.0.0.1:8080`, and a separate authentication gateway validates the user's real login/session.
Replace the documentation domain, certificate paths, and auth-gateway address.
## Trust boundary
Nginx is the only public listener. It terminates TLS, performs an `auth_request`, and proxies only
to `frontend`; frontend then uses its private same-origin `/api` route to reach `core`. Never proxy
the public listener directly to core port 8787.
The authentication gateway must return 2xx only after validating a real credential or session. It
returns normalized `X-Thoth-Principal-*` and `X-Thoth-Is-Admin` response headers. Nginx clears all
client-supplied public and private-hop identity headers and copies only those successful auth
response values into `X-Thoth-Trusted-*` on the private hop to frontend.
Forwarding identity headers alone does not authenticate a user.
Do not substitute a static header, network allowlist, or client-provided header for the
authentication gateway. The admin value must come from reviewed identity-provider authorization,
not from a username supplied by the browser.
## Example configuration
Install an Nginx build that includes `ngx_http_auth_request_module`. Save a reviewed version of
this server block under the host's Nginx configuration directory:
```nginx
server {
listen 80;
server_name thoth.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name thoth.example.com;
ssl_certificate /etc/nginx/tls/thoth/fullchain.pem;
ssl_certificate_key /etc/nginx/tls/thoth/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
location = /_authenticate {
internal;
proxy_pass http://auth-gateway:4180/verify;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
proxy_set_header X-Original-Method $request_method;
# The auth service derives identity from the real login/session, never these headers.
proxy_set_header X-Authenticated-User "";
proxy_set_header X-Thoth-Principal-Issuer "";
proxy_set_header X-Thoth-Principal-Subject "";
proxy_set_header X-Thoth-Principal-Display-Name "";
proxy_set_header X-Thoth-Is-Admin "";
proxy_set_header X-Thoth-Trusted-Principal-Issuer "";
proxy_set_header X-Thoth-Trusted-Principal-Subject "";
proxy_set_header X-Thoth-Trusted-Principal-Display-Name "";
proxy_set_header X-Thoth-Trusted-Is-Admin "";
}
location / {
auth_request /_authenticate;
auth_request_set $thoth_principal_issuer
$upstream_http_x_thoth_principal_issuer;
auth_request_set $thoth_principal_subject
$upstream_http_x_thoth_principal_subject;
auth_request_set $thoth_principal_display_name
$upstream_http_x_thoth_principal_display_name;
auth_request_set $thoth_is_admin
$upstream_http_x_thoth_is_admin;
# Discard browser claims. Carry only successful auth-subrequest values to frontend.
proxy_set_header X-Authenticated-User "";
proxy_set_header X-Thoth-Principal-Issuer "";
proxy_set_header X-Thoth-Principal-Subject "";
proxy_set_header X-Thoth-Principal-Display-Name "";
proxy_set_header X-Thoth-Is-Admin "";
proxy_set_header X-Thoth-Trusted-Principal-Issuer $thoth_principal_issuer;
proxy_set_header X-Thoth-Trusted-Principal-Subject $thoth_principal_subject;
proxy_set_header X-Thoth-Trusted-Principal-Display-Name $thoth_principal_display_name;
proxy_set_header X-Thoth-Trusted-Is-Admin $thoth_is_admin;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Connection "";
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
# SSE must reach the browser without response buffering or cache delay.
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
add_header X-Accel-Buffering no always;
}
}
```
Keep the certificate private key outside the ThothII tree. Do not log cookies, authorization
headers, auth response bodies, or trusted identity headers.
## Validate and reload
First keep the public firewall rule closed. Confirm ThothII responds only on loopback, validate the
full Nginx configuration, then reload without stopping existing connections:
```sh
curl --fail http://127.0.0.1:8080/health
sudo nginx -t
sudo systemctl reload nginx
```
If `nginx -t` reports that `auth_request` is unknown, install the distribution package/module that
provides it. Do not remove authentication to make the syntax check pass.
## Test authentication and SSE
Open the firewall only after all of these pass:
1. An unauthenticated HTTPS request is redirected to login or returns 401/403.
2. Supplying forged `X-Thoth-Principal-*`, `X-Thoth-Is-Admin`, or `X-Thoth-Trusted-*` request
headers does not grant access.
3. A real authenticated non-admin can use the application but cannot open Pi Management.
4. A real authenticated admin can use Pi Management.
5. A browser session receives live model updates for longer than the default proxy timeout without
batching; a protected `curl --no-buffer` test using a real short-lived login cookie is also
acceptable. Delete the cookie jar immediately afterward.
Re-run these checks after changing the identity provider, auth gateway, Nginx, or ThothII release.