Commit Graph
8 Commits
Author SHA1 Message Date
kevinveenbirkenbachandClaude Opus 5.5 a758ce71f9 fix(web-app-prometheus): pick each probe target's module by its own TLS mode
While the private CA is missing from the prometheus stack, a self-signed
target has to use http_ready_private_ca. The blackbox job chose that
module once per application from lookup('tls', app, 'mode'), which aligns
to one sibling domain. For web-app-docs that sibling was the onion domain
(TLS off), so its clearnet https target kept the verifying http_ready and
failed with "x509: certificate signed by unknown authority" (CI run
40131272595: n8n#1, and hidden behind the first failure in API#1 and
Mattermost#1).

Every served domain now gets its own target group whose module follows
lookup('tls', probe_domain, 'mode'). Series labels are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 12:57:11 +01:00
kevinveenbirkenbach 8f22a3d488 Merge branch 'feature/updater' into feature/store-i18n
# Conflicts:
#	README.md
#	roles/svc-bkp-local-2-device/tasks/00_core.yml
#	roles/svc-bkp-nfs-2-local/tasks/00_core.yml
#	roles/svc-bkp-remote-2-local/tasks/00_core.yml
#	roles/svc-bkp-secrets-2-local/tasks/00_core.yml
#	roles/svc-bkp-volume-2-local/tasks/00_core.yml
#	roles/sys-ctl-cln-bkps/tasks/00_core.yml
#	roles/sys-ctl-cln-certs/tasks/00_core.yml
#	roles/sys-ctl-cln-disc-space/tasks/00_core.yml
#	roles/sys-ctl-cln-faild-bkps/tasks/00_core.yml
#	roles/sys-ctl-hlth-webserver/filter_plugins/web_health_expectations.py
#	roles/sys-ctl-mtn-cert-renew/tasks/00_core.yml
#	roles/sys-svc-container/README.md
#	roles/sys-svc-container/vars/main.yml
#	roles/sys-svc-proxy/templates/headers/forwarded.conf.j2
#	roles/sys-svc-webserver-https/tasks/00_core.yml
#	roles/sys-token-store/tasks/write.yml
#	roles/web-app-discourse/templates/config.yml.j2
#	roles/web-app-keycloak/files/shell/per_app_mapper/ensure_app_group.sh
#	roles/web-app-keycloak/files/shell/per_app_mapper/purge/app_subgroups.sh
#	roles/web-app-keycloak/files/shell/per_app_mapper/sync_app_mapper.sh
#	roles/web-app-keycloak/files/shell/per_app_mapper/upsert_app_mapper.sh
#	roles/web-app-matomo/tasks/03_install_path.yml
#	roles/web-app-matomo/tasks/08_reinject_consumers.yml
#	roles/web-app-matrix/README.md
#	roles/web-app-matrix/tasks/flavor/compose/04_webserver.yml
#	roles/web-app-matrix/vars/main.yml
#	roles/web-app-moodle/tasks/03_ownership.yml
#	roles/web-app-seaweedfs/meta/info.yml
#	roles/web-app-stalwart/tasks/04_manage_user.yml
#	roles/web-opt-rdr-domains/README.md
#	roles/web-opt-rdr-domains/tasks/main.yml
#	roles/web-svc-file/tasks/00_core.yml
#	roles/web-svc-html/tasks/00_core.yml
#	tests/unit/python/roles/web-app-prometheus/test_blackbox_targets.py
2026-10-24 17:37:48 +02:00
kevinveenbirkenbachandClaude Opus 5.5 7a82a92e84 fix(web-app-prometheus): probe only the domains an app serves itself
#1180 gave web-app-matrix a canonical `jitsi` domain for its own Jitsi
and listed it under `services.jitsi.domains`. When Jitsi is shared or
disabled nothing serves that domain, and the blackbox healthz job of
web-app-prometheus probed every canonical domain, so the probe of
https://jitsi.matrix.<domain>/healthz/ready failed with "tls:
unrecognized name" and `prometheus scrape: every consumer role reports
up=1 and passes its probe` went red (main run 40017166046: Matrix#2,
Nextcloud#12).

web_health_expectations already skipped such keys. The rule now lives
in utils/domains/unserved.py: a key claimed by a service entity that is
disabled, or enabled but shared, is not served by that app. The health
filter uses it unchanged, and prometheus.yml.j2 filters its targets
through the new `served_domains` filter, which also drops the
`<key>_onion` mirror of a skipped key.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-24 11:44:14 +02:00
kevinveenbirkenbach 1da2cef95e Merge remote-tracking branch 'origin/main' into feature/network/multi-network-serving
# Conflicts:
#	plugins/lookup/email.py
#	tests/unit/python/roles/web-app-prometheus/test_blackbox_targets.py
2026-10-15 16:45:18 +02:00
kevinveenbirkenbachandClaude Opus 5.5 15bba26ef3 fix(web-app-prometheus): verify publicly trusted probe targets while the private CA is missing
The readiness module http_ready rendered insecure_skip_verify from
TLS_MODE and lookup('ca_injected', application_id) (#851). The lookup is
true only when Prometheus itself has a domain, TLS and the self-signed
mode, so in a self-signed deployment where Prometheus runs in another
mode the exporter had no CA file and skipped verification. All targets
share the module, so a target with a publicly trusted certificate was
probed without verification too, and anyone on the probe's path could
answer for a failed application.

http_ready now always verifies. A second module, http_ready_private_ca,
skips verification, and only the targets that need it select it: those
in the self-signed mode while the CA is not mounted into Prometheus,
through the __param_module label, which overrides the job's module for
that target. The default self-signed deployment mounts the CA and keeps
every target on the verifying module.

Verified on a local self-signed Tor round, where the CA is mounted:
the rendered blackbox.yml holds http_ready with insecure_skip_verify:
false and http_ready_private_ca with true, and no target of the scrape
configuration carries the module label. All targets of that round are
http onion names, so the https path itself ran only in the unit tests:
tests/unit/python/roles/web-app-prometheus pass, among them a publicly
trusted target that keeps the verifying module while the CA is missing,
a self-signed target that switches to the private-CA module, and the
verifying module rendering insecure_skip_verify: false without the CA.
Against the templates of main the three new cases fail.

Closes #851

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 21:31:58 +02:00
kevinveenbirkenbachandClaude Opus 5.5 7fa3400cc6 Merge remote-tracking branch 'origin/main' into feature/network/multi-network-serving
Conflicts resolved by keeping both sides' intent:

- call-test-deploy.yml: main's re-enabled deploy concurrency group, keyed
  on the network axis instead of the removed tor axis.
- sys-svc-proxy: main's shared headers/forwarded.conf.j2 now carries the
  branch's per-vhost semantics (X-Forwarded-Host, TLS port and state read
  from the vhost domain), so html, ws, upload and the Prometheus probes
  all answer per network sibling.
- plugins/lookup/email.py: main's provider-agnostic mail lookup asks the
  network registry instead of testing the .onion suffix, as the branch
  does everywhere; container_extra_hosts.py likewise. The provider host's
  NETWORK_MODE now decides whether it is served onion-first, since a Tor
  node defaults to multi and keeps clearnet canonical.
- workspace common.sh: main's INFINITO_DOMAIN fallback without the
  duplicated no-op line.
- README.md and requirement 035: both sides' rows (Wazuh plus main's
  Pi-hole and Stalwart entries); adapter_candidate count 39.

Adapted to main where the branch's rules now reach main's code:

- six tests from main read the primary domain from default.env instead
  of writing it out, as the hardcoded-domain lint requires;
- the chutney worker-check test passes ONION_SUFFIX from the network
  registry, which the branch's svc-net-tor test script requires;
- web-app-wazuh moves its local http ports to 8096/8097 (8094/8095 now
  belong to web-app-stalwart) and sizes the indexer heap through
  service_memory_mb, the same fixes #414 carries;
- web-app-wazuh's README cosmos follows Stalwart as the mail provider.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 00:14:42 +02:00
kevinveenbirkenbachandClaude Opus 5.5 2a1c5e13ce fix(web-app-prometheus): judge each probe by its own target
Since the targets take their scheme from the domain they probe, two
switches of the http_ready module no longer fit. Both still followed the
TLS state of the Prometheus vhost.

fail_if_not_ssl refused an http target, an onion vhost for example, as
soon as Prometheus itself was served over TLS. It is false now. The
module does not follow redirects, so the scheme of the target URL already
decides the transport.

insecure_skip_verify switched certificate checks off whenever Prometheus
itself had no TLS, also for an https target. Checks now stay on, except in
a self-signed deployment whose CA is not mounted into the Prometheus
containers, where the exporter has nothing to verify against.

The per-role test of the spec parsed every answer of the query API as
JSON. An answer that is not OK now counts as "no probe yet", so the poll
keeps waiting instead of ending on a parse error.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-06 16:40:34 +02:00
kevinveenbirkenbachandClaude Opus 5.5 883b9c4f46 fix(web-app-prometheus): probe apps where their vhosts answer
Every blackbox probe of a Tor deployment answered 404, so AppDown fired for
all deployed apps although they were up. The job built its targets from
canonical_domains_map(DOMAIN_PRIMARY), which knows no onion domain. In a Tor
deployment the vhosts answer under <sub>.<onion> only, and the front proxy
served the clearnet names from its default server.

The targets now come from lookup('domains'), the map the vhosts are built
from, and each target takes its scheme from the domain it probes instead of
from the Prometheus vhost.

Which roles are probed follows lookup('roles_with_service', 'prometheus'),
the list the role's own spec expects metrics for. It leaves out the database
roles, which have a domain in the map and no vhost, and the roles that
declare scrape: false because their vhost carries no Prometheus block.

Two roles declared more than their vhost delivers. web-svc-mirror renders a
vhost of its own with no backend behind it, and on a live stack its probe
answered 404 under the onion name as well, so it declares scrape: false now.
web-app-peertube has a backend, but its vhost template never included the
Prometheus locations. It includes them now.

The spec could not see any of this in a compose deployment. dotenv_quote
wraps PROMETHEUS_TARGET_ROLES_JSON in quotes there, JSON.parse returned a
string, the role list came out empty and the per-role test was skipped. The
value is decoded now, and the test also requires probe_success == 1 for
every role in the list.

Closes #792

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-06 11:37:28 +02:00