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

5.6 KiB

Put ThothII behind Nginx

Choose exactly one authentication mode. Direct ThothII-managed OIDC and deprecated upstream authentication are mutually exclusive proxy contracts; never combine their locations or headers.

Direct ThothII-managed OIDC

Use this mode when auth.yaml has mode: oidc. Nginx terminates TLS and proxies every request to loopback frontend. ThothII owns OIDC login, callback validation, browser sessions, and authorization. No external auth_request or authentication gateway belongs in this server.

The location / block below has a proxy_pass without a replacement URI, so public /api/auth/oidc/login and /api/auth/oidc/callback are forwarded unchanged. The configured publicUrl must match the browser origin.

server {
    listen 80;
    server_name thoth.example.invalid;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name thoth.example.invalid;

    ssl_certificate /etc/nginx/tls/thoth/fullchain.pem;
    ssl_certificate_key /etc/nginx/tls/thoth/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;

    location / {
        # No auth_request and no URI rewrite: ThothII receives OIDC paths unchanged.
        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;
        proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 3600s;
        add_header X-Accel-Buffering no always;
    }
}

After reload, run Workspace Validate for static validation, tht auth check for live, non-interactive authentication diagnosis, and then Workspace Test for aggregate live validation.

Deprecated upstream migration mode

Use this section only while the installation explicitly uses deprecated upstream mode. Do not use it with mode: oidc or mode: local. In this mode an external authentication gateway owns login, and Nginx applies auth_request before forwarding normalized private identity headers.

Forwarding identity headers alone does not authenticate a user. The authentication gateway returns 2xx only after validating its own credential or session.

server {
    listen 443 ssl;
    server_name thoth.example.invalid;

    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;
        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;

        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;
        proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 3600s;
        add_header X-Accel-Buffering no always;
    }
}

Trust boundary

Nginx is the only public listener and proxies only to loopback frontend, never directly to core. Keep private keys outside the ThothII tree. Do not log cookies, authorization headers, OIDC callback query values, authentication bodies, or trusted identity headers.

Validate and reload

Keep the public firewall closed while validating:

curl --fail http://127.0.0.1:8080/health
sudo nginx -t
sudo systemctl reload nginx

Test authentication and SSE

For direct OIDC, verify login redirects to the configured provider, callback traffic reaches ThothII unchanged, forged identity headers grant nothing, and SSE is unbuffered. For deprecated upstream mode, additionally verify the external gateway rejects unauthenticated traffic and only its 2xx response can create trusted identity headers.