map $original_uri $api_uri { ~^/api(/.*$) $1; default $original_uri; } server { listen 80; server_name {{ opnform_domain }}; root /app/public; client_max_body_size {% raw %}${NGINX_MAX_BODY_SIZE}{% endraw %}; access_log /dev/stdout; error_log /dev/stderr error; index index.html index.htm index.php; # Re-resolve upstream container hostnames via Docker's embedded DNS # at request time. Without this, nginx caches the first resolution # forever; if `api` or `ui` get recreated and pick up a new IP, every # request 502s until the ingress itself is restarted. resolver 127.0.0.11 valid=10s ipv6=off; set $upstream_api api; set $upstream_ui ui; {% if opnform_oidc_enabled and opnform_oidc_sso_entrypoint %} # Root → /login. Public forms live under /forms/, so the bare # hostname only serves the authenticated dashboard — sending it # straight to /login (which then jumps to the IdP) saves an extra # UI-side redirect for anyone who lands there. location = / { return 302 /login; } # /login intercept: serve a tiny HTML page that calls OpnForm's # /api/auth/{slug}/redirect endpoint and forwards the browser to the # IdP authorize URL — skipping the email-based login form entirely. # Break-glass: /login?bypass=1 falls through to the UI's own login # form so the email/password path stays reachable when the IdP is # down. Bypass branches to a named location (`@login_bypass`) because # `proxy_pass` inside an `if` block is invalid nginx config. location = /login { if ($arg_bypass = "1") { error_page 418 = @login_bypass; return 418; } default_type text/html; return 200 'Redirecting to sign-in…

Redirecting to sign-in…

'; } location @login_bypass { proxy_http_version 1.1; proxy_pass http://$upstream_ui:3000/login; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port; } {% endif %} location / { proxy_http_version 1.1; proxy_pass http://$upstream_ui:3000; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; } location ~/(api|open|local\/temp|forms\/assets)/ { set $original_uri $uri; try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass $upstream_api:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html/public/index.php; fastcgi_param REQUEST_URI $api_uri; } }