Commit Graph
18 Commits
Author SHA1 Message Date
kevinveenbirkenbachandClaude Opus 5.5 eda3bdbc35 refactor(sys-svc-proxy): set the upstream request headers in one snippet
Host, X-Real-IP, X-Forwarded-For, X-Forwarded-Proto, X-Forwarded-Port and
X-Forwarded-Ssl were written out separately in the html, ws and upload
locations and in the Prometheus health probes, and the copies had drifted:
ws and upload never sent Port and Ssl, and the probes sent only Host, which
is how the Shopware readiness probe came to see plain http.

headers/forwarded.conf.j2 now holds the set and every one of those locations
includes it. The html location renders the same headers as before. ws and
upload additionally send Port and Ssl with the values the html location
already gives the same backend. The ready and live probes gain X-Real-IP and
X-Forwarded-For, and the live probe the three X-Forwarded headers as well.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 17:15:22 +02:00
kevinveenbirkenbach 211d98aa88 fix(sys-svc-proxy): finish stripping forgeable identity headers
b8759a363e closed this for html.conf.j2 and its message said 'every proxy
location', so the class read as done. Three proxying snippets never got
it: ws, upload and media.

They are not covered by inheritance. nginx inherits proxy_set_header as
an array, so a location declaring any of its own discards every one from
the enclosing block, and proxy_pass_request_headers defaults to on. A
grep for the strip found exactly one include site before this commit,
which means there was nothing above those locations to inherit either.

So every websocket, upload and image location forwarded whatever
X-Forwarded-User the client sent, to applications that authenticate by
believing that header. Reached through ws_generic (mastodon, espocrm,
odoo), nextcloud's signaling and whiteboard, peertube's websocket and
tracker, and collabora's /cool/.

The lint asks the file whether it proxies rather than keeping a list of
snippet names. It grants no exemption for an SSO branch: html.conf.j2
carries both, and an exemption keyed on the SSO reference would keep it
green after the strip was deleted from the other branch.
2026-08-29 15:54:29 +02:00
kevinveenbirkenbachandClaude Opus 5 5137465c6f style: delete every comment the comments-valid policy rejects
3529 invalid comments in 528 files, grandfathered in while the linter
only saw the working-tree diff. Removal ran through the linter's own
collectors, so detection and deletion cannot drift: a comment whose
opener line is blank before it and whose closer line is blank after it
loses all its lines, anything else loses only the comment region, and a
line left holding a bare delimiter goes with it.

Five files keep their comments behind a nocheck marker instead. Four are
upstream configs whose inline docs are upstream's own (mautrix, systemd
journald, nextcloud-oidc-login, MediaWiki). In littlejs the
commented-out entries ARE the deactivation mechanism for an example
tile, so deleting them would delete configuration.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 03:22:02 +02:00
kevinveenbirkenbachandClaude Fable 5 d88f272f9f Merge branch 'feature/swarm-nfs' into feature/svc-net-tor
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 15:31:08 +02:00
kevinveenbirkenbachandClaude Opus 4.8 d492cc038e fix(opencloud): ride the node onion via an overridable X-Forwarded-Proto
OpenCloud's proxy mounts an unconditional https-redirect middleware: any
request carrying X-Forwarded-Proto other than https gets a 308, with no
config toggle. Onion vhosts are plaintext, so the app 308-looped on
onion nodes and the webserver health gate aborted the deploy.

Make X-Forwarded-Proto overridable in the shared proxy location
templates (default $scheme, byte-identical for every other role) and
have opencloud assert https towards its backend.

Verified on a fresh onion node: opencloud deploys, the health gate
passes, the SPA loads over the onion, and its well-known, OIDC env and
CSP all resolve to http://auth.<onion>. The SSO E2E still flakes on
transient Tor SOCKS errors mid-flow (client-side multi-hop OIDC), which
is a Tor path property, not an app defect.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 20:02:29 +02:00
kevinveenbirkenbachandClaude Opus 4.8 f424ac1007 fix(swarm/proxy): forward internal_port in shared location templates
The healthz, media, upload and ws location templates called proxy_pass
without internal_port, so in swarm they fell back to
services.<entity>.ports.internal.http. Apps whose entity service has no
internal http port (e.g. bluesky) hard-failed the nginx config render
with resolve_upstream: swarm upstream needs
services.<entity>.ports.internal.http. Forward internal_port (default '')
like html.conf.j2 already does; no-op where it is not passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 12:24:18 +02:00
kevinveenbirkenbachandClaude Opus 4.8 36ebf34b64 Merge branch 'main' into feature/swarm-nfs
Resolve 69 conflicts across ~70 files: union main's image-version bumps and new service fields (bond, resource limits) with the swarm branch's default_placement / NFS / IS_STACK_HOST config; retire the three per-deploy-type test workflows main still edited (consolidated into compose+swarm); adopt main's run-once 01_core dispatchers while re-applying each role's swarm guard. Fix the post-merge lint surfaced by main's stricter rules: bond + resource-budget keys, container-exec stack-host gating + resolver routing, leaky/dead proxy vars, suitecrm once-flag, xwiki variant nocheck, nextcloud oversized-block to gated include, matrix-mdad capped at 3g. make autoformat clean, make test green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 17:13:55 +02:00
kevinveenbirkenbachandClaude Opus 4.8 ffac55c1d5 fix(proxy): stop cross-role webserver_* var leak (config fields + task-scoping + front-proxy reset + lint)
A role's vars/main.yml is auto-loaded into play scope and persists, so proxy
override vars (webserver_*) leaked into the central front-proxy render of OTHER
roles (re-evaluated against the wrong application_id) — silently applying one
role's value elsewhere, or hard-failing when the lazy lookup hit a role lacking
the key (the seaweedfs<->matrix client_max_body_size crash).

- Templates (sys-svc-proxy html/upload/ws_generic, matrix synapse homeserver)
  resolve client_max_body_size from the role's own server config
  (lookup('config', application_id, 'server.client_max_body_size', '100m')).
- Move every role-level webserver_* out of vars/main.yml into task-scoped
  include params (9 roles); they apply only to that role's proxy and can't leak.
- sys-stk-front-proxy resets webserver_* to safe defaults via task-scoped vars
  on the render tasks, so a leaked value from any other source is neutralized;
  a role's own include params (#20) still override the reset (precedence-tested,
  direct + nested).
- Add test_no_leaky_proxy_role_vars lint forbidding webserver_* in vars/main.yml
  (suppressable via '# nocheck: leaky-proxy-var').

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 06:03:18 +02:00
kevinveenbirkenbachandClaude Opus 4.8 c3f01a8640 feat(proxy): mode-aware proxy_pass SPOT lookup
Centralise the nginx proxy_pass directive in one source of truth (utils/networks/proxy.py + plugins/lookup/proxy_pass.py). Compose keeps the literal 127.0.0.1:<local> upstream; swarm resolves the service over the shared overlay at request time (variable upstream + http resolver) so a rescheduling backend never blocks openresty startup. Converts the html/media/upload/ws location partials, the keycloak oauth2 and login-iframe endpoints, and the logout endpoint to the lookup; adds the swarm resolver and the front-proxy service_key plumbing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 19:49:18 +02:00
kevinveenbirkenbachandClaude Opus 4.7 e746368c20 fix(sys-svc-proxy): CSP is SPOT — strip deprecated security headers + add regression lint
Browser vendors deprecated X-Frame-Options/X-XSS-Protection/X-Download-Options/
X-Permitted-Cross-Domain-Policies; CSP (rendered from each role's
meta/server.yml via build_csp_header) is the modern replacement. To make the
SPOT actually win against upstream apps (e.g. Keycloak/Quarkus still emits
X-Frame-Options), the proxy now hides those headers on every location type.
Includes a fail-loud lint that catches any future add_header / Header set/add
re-introduction in .conf / .conf.j2 / .htaccess / .j2 / .jinja / .tmpl files.

- sys-svc-proxy: new upstream_strips.conf.j2 partial bundles HSTS + the 4
  deprecated header strips; included in html/media/ws/upload + web-svc-logout
  + web-app-oauth2-proxy locations (nginx array-replacement inheritance forces
  per-location placement)
- web-app-keycloak: meta/server.yml frame-ancestors allows the primary-domain
  wildcard with the dynamic TLS protocol so dashboard silent-check-sso iframe
  loads cleanly
- web-app-dashboard/playwright: drop isOidcSilentCheckNoise — root cause is
  now fixed, no noise filter needed
- web-app-dashboard/nginx + web-app-nextcloud/nginx: remove the deprecated
  add_header lines themselves
- tests + docs: new lint registers `deprecated-http-header` suppression rule

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 22:36:05 +02:00
kevinveenbirkenbach 3bb8c0ce30 refactor(tls): rename tls_resolve lookup to tls
The TLS lookup has been renamed from `tls_resolve` to `tls` to better
reflect its responsibility as a strict TLS state resolver.

This refactor updates all usages across the codebase, including:
- lookup plugins and internal helpers
- roles, vars, tasks, and templates
- tests, stubs, and error messages
- documentation and changelog references

Behavior, lookup API, and semantics remain unchanged.

https://chatgpt.com/share/6985e635-5a94-800f-b794-937e566ee308
2026-02-06 14:01:32 +01:00
kevinveenbirkenbach 8fe6b92e63 refactor(lookups): migrate nginx_paths, tls_resolve and cert_plan to strict positional want-path API
- Replace legacy want= keyword usage with mandatory positional want-path
- Align all nginx_paths, tls_resolve and cert_plan lookups to strict API
- Keep behavior unchanged while enforcing consistent lookup semantics

https://chatgpt.com/share/6985d642-b40c-800f-9cdf-ed54fc484a92
2026-02-06 13:06:09 +01:00
kevinveenbirkenbach 0b9f71463c refactor(tls): replace legacy tls filters with strict tls_resolve lookup
- Remove deprecated filter_plugins/tls.py and all dependent filters
- Introduce strict lookup plugin lookup_plugins/tls_resolve.py as single TLS authority
- Migrate all roles, templates, vars, and tasks to use tls_resolve (protocols, ports, URLs, cert paths)
- Enforce explicit TLS context (domains, applications, TLS_ENABLED, TLS_MODE)
- Support letsencrypt and self_signed with SAN handling and per-app overrides
- Update TLS provider roles to assert resolver state instead of setting facts
- Add comprehensive unit tests for tls_resolve lookup

https://chatgpt.com/share/6972b49b-b074-800f-a323-dd9fe69d02eb
2026-01-23 00:36:46 +01:00
kevinveenbirkenbach 9fdb0cddd0 Replace global WEB_PROTOCOL / WEB_PORT / WEBSOCKET_PROTOCOL logic
with explicit per-application TLS resolution.

Key changes:
- Introduce sys-front-tls-layer as the single TLS abstraction
- Centralize certificate paths via TLS_CERT_FILE / TLS_KEY_FILE / TLS_CA_FILE
- Replace sys-svc-letsencrypt SSL templates with generic TLS layer includes
- Add tls_* Jinja filters (enabled, mode, protocol, port, websocket)
- Resolve TLS mode per application (letsencrypt | self_signed | off)
- Remove implicit defaults and WEB_* globals to fail fast on misconfiguration
- Support self-signed certificates with SAN awareness
- Make TLS behavior explicit and consistent across all roles

This decouples application logic from certificate providers and
allows switching TLS flavor without touching app roles.

https://chatgpt.com/share/69727c61-8e68-800f-a267-473a7e627978
2026-01-22 20:36:49 +01:00
kevinveenbirkenbach f52f49118a Disable 'proxy_hide_header Strict-Transport-Security;' when TLS disabled 2026-01-22 16:26:37 +01:00
kevinveenbirkenbach 986f959696 Refactor webserver proxy variables and fix BigBlueButton deployment behavior
Refactor proxy/webserver configuration variables to a consistent webserver_* naming scheme across roles. Replace legacy variables like proxy_extra_configuration, client_max_body_size, vhost_flavour, location_ws and ws_port with webserver_extra_configuration, webserver_client_max_body_size, webserver_vhost_flavour, webserver_websocket_location and webserver_websocket_port. Update NGINX vhost and location templates (html, upload, ws, basic, ws_generic) as well as callers (sys-front-inj-all, sys-stk-front-proxy, various web-app-* and web-svc-* roles) to use the new naming.

Tighten docker-compose Git repository handling by making docker_git_repository_pull depend on docker_git_repository_address being defined, a string and non-empty. This avoids accidental Git operations when the repository address is unset or of the wrong type.

Refactor the BigBlueButton role structure and fix deployment bugs: introduce 01_core.yml to orchestrate docker/proxy setup, database seeding, websocket map deployment, docker-compose overrides and admin/bootstrap logic in a single once-executed entrypoint. Rename supporting task files (02_docker-compose.yml, 03_administrator.yml, 04_dependencies.yml) and update tasks/main.yml to delegate via include_tasks with run_once_web_app_bigbluebutton. Improve Greenlight admin creation behavior by treating the 'Email has already been taken' error as a non-fatal, unchanged outcome and running user:set_admin_role as a fallback, both for the primary password and the OIDC starred-password path.

Also standardize vhost flavour selection for services like Mailu, Discourse, CDN, Collabora, Coturn, OnlyOffice, Simpleicons and web-svc-logout by explicitly passing webserver_vhost_flavour where needed and aligning client_max_body_size and websocket configuration with the new webserver_* variables.

Reference: ChatGPT conversation https://chatgpt.com/share/6931c530-bba8-800f-9997-dd61dc1d497b
2025-12-04 18:31:09 +01:00
kevinveenbirkenbach 002f8de3ec feat(proxy): add configurable client_max_body_size for HTML and upload locations
This commit introduces a unified mechanism to configure client_max_body_size
for both HTML and upload locations in the sys-svc-proxy role. The directive
is now injected early in html.conf.j2 and moved to a dedicated block in
upload.conf.j2 to ensure consistent behavior for large file uploads such as
OpenProject attachments.

Additionally:
- Added client_max_body_size variable override from web-app-openproject (set to 30m).
- Reordered header includes to avoid duplicate injection.
- Improved comments and structure for better clarity.

Reference: https://chatgpt.com/share/691d873e-9b50-800f-ae70-baf8bf1e5454
2025-11-19 10:02:33 +01:00
kevinveenbirkenbach b02d88adc0 Refactored server roles for better readability 2025-09-01 18:08:35 +02:00