Files
Remsly/deploy/prod/frontend/app.boxi.ch.conf
T
2026-07-13 22:47:34 +02:00

94 lines
4.5 KiB
Plaintext

<VirtualHost *:80>
DocumentRoot "/var/www/html/app"
ServerName remsly.tail276105.ts.net
# ServerAlias www.${server_name}
ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined
LogLevel info
# TLS is terminated by the tailscale sidecar; make mod_auth_openidc and the
# app aware that the external scheme is https.
RequestHeader set X-Forwarded-Proto "https"
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
Header always set Content-Security-Policy "default-src 'self' ; \
script-src 'self' 'unsafe-inline' 'unsafe-eval'; \
style-src 'self' use.fontawesome.com 'unsafe-inline'; \
font-src 'self' data: use.fontawesome.com; \
base-uri 'self'; \
form-action 'self'; \
frame-ancestors 'none'; \
img-src 'self' api.mapbox.com data:; \
upgrade-insecure-requests" "expr=%{CONTENT_TYPE} =~ m#text\/(html|javascript)|application\/pdf|xml#i"
Header always append X-Frame-Options SAMEORIGIN
Header always set X-Content-Type-Options nosniff
Header always set Referrer-Policy "same-origin"
# this feature is not yet used and must be extended if needed, currently only a sample config
Header always set Feature-Policy "payment 'none';"
<Directory />
AllowOverride none
Options -Indexes -Includes
Require all granted
<LimitExcept GET POST HEAD>
deny from all
</LimitExcept>
</Directory>
<Directory "/var/www/html/app">
AllowOverride None
Options -Indexes -Includes
Require all granted
# SPA deep-link support: serve index.html (HTTP 200) for any path that does not map to a
# real file, so the Angular router can resolve it client-side. Existing assets are still
# served directly; /api/ (proxied) and /openidc (mod_auth_openidc) are unaffected.
FallbackResource /index.html
</Directory>
RequestHeader set X-Forwarded-User expr=%{REMOTE_USER}
RequestHeader set Authorization "Bearer %{oidc_access_token}e"
Header set User-Details "%{REMOTE_USER}e %{oidc_claim_email}e"
# Fetch metadata + run the backchannel (token exchange, jwks) over the internal http:8080
# URL; the discovery doc still advertises the https issuer/authorization/logout endpoints
# (KC_HOSTNAME_BACKCHANNEL_DYNAMIC=true on Keycloak keeps those frontend URLs public).
OIDCProviderMetadataURL ${KC_INTERNAL_ADDR}/realms/${KC_REALM}/.well-known/openid-configuration
OIDCClientID ${OIDC_CLIENT_ID}
OIDCClientSecret ${OIDC_CLIENT_SECRET}
OIDCRefreshAccessTokenBeforeExpiry 10
OIDCRedirectURI ${OIDC_REDIRECT_URI}
OIDCCryptoPassphrase ${OIDC_CRYPTO_PASSPHRASE}
# Where to land after a successful login when no original target URL is known (e.g. SSO entry
# via the redirect URI). Without this, mod_auth_openidc aborts with "Invalid Request".
OIDCDefaultURL https://remsly.tail276105.ts.net/
OIDCDefaultLoggedOutURL ${KC_ADDR}/realms/${KC_REALM}/protocol/openid-connect/logout?redirect_uri=https%3A%2F%2Fremsly.tail276105.ts.net
OIDCRemoteUserClaim preferred_username
OIDCStateMaxNumberOfCookies 3 true
<Location /status >
SetHandler server-status
</Location>
<Location />
AuthType openid-connect
Require valid-user
</Location>
# If the browser is allowed to cache index.html, it starts loading assets/scripts/images before apache had a chance
# to check whether or not the user is even authenticated, leading to many failed requests.
# Disabling cache for index.html forces the browser to fetch it first, and therefore ensures that the full
# authentication mechanic is being run.
# See also https://github.com/zmartzone/mod_auth_openidc/issues/113
<filesMatch "index.html">
FileETag None
Header unset ETag
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires "Mon, 21 Mar 1983 14:10:00 UTC"
</filesMatch>
ProxyPass /api/ ${BACKEND_URL}:${BACKEND_PORT}/api/ retry=0
ProxyPassReverse /api/ ${BACKEND_URL}:${BACKEND_PORT}/api/
</VirtualHost>