Dotfiles/setup/modules/FreeipaAnsible/image/nginx/templates/default.conf.template

111 lines
5.3 KiB
Plaintext

# ansipa reverse-proxy + portal — rendered by nginx's envsubst entrypoint.
# Placeholders (${VAR}) are filled from the container environment at start.
#
# Design: each backend is proxied at the path it ALREADY serves natively
# (FreeIPA /ipa, CheckMK /cmk, Keycloak under a configured /auth relative path,
# Nextcloud under OVERWRITEWEBROOT=/nextcloud), so no fragile path rewriting is
# needed and a single hostname/entry works — which is what lets the whole stack
# sit behind one upstream reverse proxy.
# Honor an upstream proxy's X-Forwarded-Proto if present (double-proxy case),
# otherwise fall back to this server's own scheme.
map $http_x_forwarded_proto $ansipa_fwd_proto {
default $scheme;
"~.+" $http_x_forwarded_proto;
}
# Preserve the original client IP chain when we sit behind another proxy.
map $http_x_forwarded_for $ansipa_fwd_for {
default $remote_addr;
"~.+" "$http_x_forwarded_for, $remote_addr";
}
server {
listen 80 default_server;
server_name _;
# Big cookies/headers: CheckMK and Keycloak set sizeable auth cookies.
large_client_header_buffers 4 32k;
proxy_busy_buffers_size 32k;
proxy_buffers 8 32k;
proxy_buffer_size 32k;
# ── Portal start page ────────────────────────────────────────────────────
location = / {
root /usr/share/nginx/portal;
try_files /index.html =404;
}
location = /index.html { root /usr/share/nginx/portal; }
location = /portal.css { root /usr/share/nginx/portal; }
# ── FreeIPA web UI (native path /ipa) ──────────────────────────────────────
# IPA's Apache is strict about Host and Referer (anti-CSRF): both must name
# the IPA server itself, not the proxy. Pin Host to the IPA hostname and
# rewrite Referer so the referer-check passes through the proxy.
location /ipa/ {
proxy_pass https://${ANSIPA_IPA_UPSTREAM}/ipa/;
proxy_ssl_server_name on;
proxy_ssl_verify off; # IPA ships a self-signed CA
proxy_set_header Host ${IPA_HOSTNAME};
proxy_set_header Referer https://${IPA_HOSTNAME}/ipa/ui/;
proxy_set_header X-Forwarded-Proto $ansipa_fwd_proto;
proxy_set_header X-Forwarded-For $ansipa_fwd_for;
proxy_set_header X-Forwarded-Host $host;
# IPA issues 301s to its own hostname; rewrite them back onto this proxy.
proxy_redirect https://${IPA_HOSTNAME}/ /ipa/../;
proxy_redirect http://${IPA_HOSTNAME}/ /ipa/../;
}
# ── CheckMK (native path /cmk) ─────────────────────────────────────────────
location /cmk/ {
proxy_pass http://${ANSIPA_CMK_UPSTREAM}/cmk/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $ansipa_fwd_proto;
proxy_set_header X-Forwarded-For $ansipa_fwd_for;
proxy_set_header X-Forwarded-Host $host;
}
# ── Nextcloud (subpath /nextcloud, matches OVERWRITEWEBROOT) ───────────────
# Sync clients push multi-GB files and Nextcloud streams them, so buffering
# is off and the body limit lifted; the default 1 MB cap would break every
# upload larger than a photo.
location /nextcloud/ {
proxy_pass http://${ANSIPA_NC_UPSTREAM}/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $ansipa_fwd_proto;
proxy_set_header X-Forwarded-For $ansipa_fwd_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Prefix /nextcloud;
client_max_body_size 0;
proxy_request_buffering off;
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
# Nextcloud sets this itself, but only over HTTPS; harmless otherwise.
proxy_hide_header X-Frame-Options;
}
# Desktop/mobile clients and CalDAV/CardDAV consumers probe these at the
# SERVER ROOT regardless of where Nextcloud is mounted. Without these
# redirects Nextcloud's own setup checks flag the instance as misconfigured
# and DAV auto-discovery fails.
location = /.well-known/carddav { return 301 /nextcloud/remote.php/dav; }
location = /.well-known/caldav { return 301 /nextcloud/remote.php/dav; }
location = /.well-known/webdav { return 301 /nextcloud/remote.php/dav; }
location = /.well-known/nodeinfo { return 301 /nextcloud/index.php$request_uri; }
# ── Keycloak (relative path /auth, set via KC_HTTP_RELATIVE_PATH) ──────────
location /auth/ {
proxy_pass http://${ANSIPA_KC_UPSTREAM}/auth/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $ansipa_fwd_proto;
proxy_set_header X-Forwarded-For $ansipa_fwd_for;
proxy_set_header X-Forwarded-Host $host;
# Deliberately NOT forwarding X-Forwarded-Port: this gateway listens on
# :80 internally, but the public port is whatever the upstream TLS proxy
# uses (typically 443). Sending :80 makes Keycloak emit redirects like
# https://host:80/... — let it infer the standard port from the proto.
}
}