Skip to content

Configure nginx

gotifacts is proxy-agnostic and serves plain HTTP. nginx (or any proxy) provides TLS, runs forward-auth/SSO, and routes the planes. This page shows the routing split; adapt the SSO subrequest to your provider (Authelia, oauth2-proxy, Keycloak gatekeeper, …).

LocationForward-authServes
apex / and /api/*ON (inject identity header)portal + management API
apex /ingest/*OFF (API key)machine publish API
/mcp/oauth/authorizeON (browser consent)MCP consent screen
/mcp, /mcp/oauth/token, /mcp/oauth/register, /.well-known/oauth-*OFF (OAuth)MCP machine endpoints
*.base, *.*.baseOFFstatic site content

A complete, commented example lives in the repo at examples/nginx/gotifacts.conf. The essentials:

# SECURITY: strip any client-supplied identity header on the way in.
proxy_set_header Remote-User "";
# Ingest plane: forward-auth OFF (API key enforced by gotifacts).
location /ingest/ {
client_max_body_size 64m;
proxy_pass http://gotifacts;
proxy_set_header Host $host;
proxy_set_header Remote-User "";
}
# Management plane: forward-auth ON.
location / {
auth_request /auth;
auth_request_set $authed_user $upstream_http_remote_user;
proxy_pass http://gotifacts;
proxy_set_header Host $host;
proxy_set_header Remote-User $authed_user; # inject the real user
}

Site content is served from a separate server block matching *.base (and *.*.base for deeper hosts), which also adds the framing header so the portal can render live thumbnails:

add_header Content-Security-Policy "frame-ancestors https://example.com" always;

Keep the frame-ancestors value pointed at the canonical GOTIFACTS_BASE_DOMAIN, since the portal is served from there.

To serve the instance on additional alias domains, list them in GOTIFACTS_ALIAS_DOMAINS and repeat the apex + wildcard server blocks for each domain (with its own certificate). gotifacts serves the same sites under every domain.

If you enable the MCP connector, the machine endpoints must bypass forward-auth while /mcp/oauth/authorize stays behind it. The reference config uses a regex location to match exactly the machine endpoints; see the file for the precise pattern and the long-timeout / buffering settings needed for streamable HTTP.