# 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.