- authentik: address the rewrite service by compose service name instead of a network alias on the public FQDN, which shadowed extra_hosts pins and broke OIDC discovery for c-ares-based (Node) resolvers - homarr: add homarr_extra_hosts to pin the IdP FQDN to a LAN IP so OIDC discovery stays in-network while the issuer matches the browser-facing URL - opnform: add opnform_oidc_sso_redirect_root to 302 the root URL to the SSO path (deep-links untouched, /login?bypass=1 break-glass); restart ingress via container restart so envsubst re-renders nginx.conf - nextcloud: make the UserConfig sed workaround fail loud on upstream drift instead of silently skipping (nextcloud/server#59629) - gitignore: exclude the local .ansible/ collection cache
87 lines
3.8 KiB
Django/Jinja
87 lines
3.8 KiB
Django/Jinja
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/<slug>, 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 '<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Redirecting to sign-in…</title></head><body style="font-family:sans-serif;text-align:center;padding:3rem;color:#374151"><p id="m">Redirecting to sign-in…</p><script>fetch("/api/auth/{{ opnform_oidc_slug }}/redirect",{method:"POST",headers:{Accept:"application/json"}}).then(function(r){if(!r.ok)throw new Error("HTTP "+r.status);return r.json()}).then(function(d){if(d&&d.redirect_url){window.location.replace(d.redirect_url)}else{throw new Error("no redirect_url")}}).catch(function(e){document.getElementById("m").textContent="Sign-in redirect failed: "+e.message+". Open /login?bypass=1 to use the email form.";});</script></body></html>';
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|