Commit Graph
14682 Commits
Author SHA1 Message Date
kevinveenbirkenbachandClaude Opus 4.8 646109690d fix(matrix): mount the bridge dir into synapse so registration.yaml stays a file
Mounting the not-yet-existing per-bridge registration.yaml into synapse made docker create it as a directory, which crash-looped the bridge ('registration.yaml: is a directory'). Mount the existing bridge directory (mautrix/<bridge> -> /data/mautrix-<bridge>) read-only instead and point app_service_config_files at <dir>/registration.yaml, so the bridge generates the file normally and synapse loads it after the restart.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 04:34:56 +02:00
kevinveenbirkenbachandClaude Opus 4.8 4558224e64 revert(matrix): drop the empty-registration pre-create (broke bridge generation)
Pre-creating an empty registration.yaml made the bridges skip registration generation ('appservice.as_token not configured') and left synapse broken. Reverts to the two-phase state where synapse + element + NC deploy healthy; the bridge registration/directory chicken-and-egg needs proper pre-generation (bridge -g one-off) as a follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 04:34:55 +02:00
kevinveenbirkenbach ec61d18286 Merge pull request #338 from infinito-nexus/dependabot/github_actions/actions/cache-6
chore(deps): bump actions/cache from 5 to 6
2026-06-24 04:21:28 +02:00
kevinveenbirkenbach 9dc1bb4caa Merge pull request #337 from infinito-nexus/dependabot/npm_and_yarn/playwright/test-1.61.1
chore(deps-dev): bump @playwright/test from 1.61.0 to 1.61.1
2026-06-24 04:20:16 +02:00
infinito-nexus-updater[bot] 9450f686fe update(images): update Docker image versions 2026-06-24 02:17:50 +00:00
infinito-nexus-updater[bot] c57c1f65d5 update(repos): bump git refs to latest semver tags 2026-06-24 02:17:44 +00:00
kevinveenbirkenbach 81e3075cd3 Release 10.1.1 2026-06-24 04:17:28 +02:00
kevinveenbirkenbachandClaude Opus 4.8 0c6ae365b6 style(web-app-pihole): apply autoformat normalization
make autoformat output: add YAML document-start marker and normalize
quote/indentation style in meta/info.yml and tasks/01_core.yml. No
semantic change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 04:17:28 +02:00
kevinveenbirkenbachandClaude Opus 4.8 31fe7df93d fix(web-app-pihole): disable email service
Set services.email enabled/shared to literal false in meta/services.yml.
Add corresponding suppressions:
- nocheck: dynamic-flag (flags are now static literals)
- nocheck: email (role has no lookup('email') integration)

Drop the now-static email overrides from meta/variants.yml (a static
base value must not be overridden by a variant) and add javascript
true/false pins to close a pre-existing dynamic-flag variant-coverage
gap that test_coverage flagged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 04:17:28 +02:00
kevinveenbirkenbachandClaude Opus 4.8 dca168dcba fix(matrix): pre-create bridge registration files so synapse can't make them dirs
After dropping the synapse->bridges depends_on (two-phase start), synapse starts before the bridges write registration.yaml, so docker bind-mounted the non-existent path and created it as a DIRECTORY, crash-looping the bridges ('Failed to save registration: open /data/registration.yaml: is a directory'). Pre-create empty registration.yaml files (force: false, mode 0666) before the compose up so docker mounts them as files, and wait for the bridge to write real content (search_regex: as_token, timeout 180) before restarting synapse.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 04:00:21 +02:00
kevinveenbirkenbachandClaude Opus 4.8 f57dda89db fix(matrix): null the mautrix-whatsapp segment.io analytics url (test-external)
The bridgev2 config migration carried over the upstream example-config's analytics block, whose url pointed at https://api.segment.io/v1/track. The token is already null (telemetry off), but the live external URL made the external-URL-reachability test fail (HTTP 400 from the segment tracking endpoint). Null the url so no external telemetry endpoint is referenced.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 04:00:20 +02:00
kevinveenbirkenbachandClaude Opus 4.8 aa407fe8a2 fix(web-svc-coturn): point the swarm front-proxy upstream at the nginx gateway
The HTTP landing page is served by the nginx gateway sidecar (port 80), not the
coturn TURN container, so resolve_upstream hard-failed in swarm on the missing
services.coturn.ports.internal.http. Pass proxy_service_key=nginx + proxy_internal_port=80
so the swarm upstream resolves to coturn_nginx:80, and attach the gateway to the
shared overlay via container_networks (it previously had no networks block).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:46:14 +02:00
kevinveenbirkenbachandClaude Opus 4.8 39b5774b5a fix(cache): rebuild canonical volumes when the registry is empty
get_canonical_volumes returned {} when _CANONICAL_VOLUMES_BY_ROLE was empty even
though the defaults cache was warm (get_application_defaults no-ops on a warm
cache, so it never refilled the registry). That left nfs_prep's volume loop empty,
so the NFS subdir for shared/late-loaded services (svc-ai-ollama's ollama_models)
was never created and the swarm bind mount failed ENOENT. Force a real
_build_application_defaults on an empty registry. Adds two regression tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:46:14 +02:00
kevinveenbirkenbachandClaude Opus 4.8 cec55f3720 fix(svc-dns-unbound): forward to public resolvers in DinD, not just WSL2
Iterative root-hints resolution is unsupported in nested Docker (per the role
README), so the mailu admin's DNSSEC AD-flag check fails in CI/DinD where unbound
ran iteratively. UNBOUND_FORWARD_DNS only detected WSL2 (microsoft in /proc/version);
extend it to DOCKER_IN_CONTAINER so unbound forwards to NETWORK_PUBLIC_DNS_RESOLVERS
(still DNSSEC-validating) under DinD too. Bare-metal stays iterative.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:46:13 +02:00
kevinveenbirkenbachandClaude Opus 4.8 7fc55c46dd fix(web-app-mailu): deploy svc-dns-unbound as a required dependency
The admin's startup DNSSEC self-check loops forever (never binds :8080) when
its dns: resolver is unreachable. The unbound service entry was gated on
`'svc-dns-unbound' in group_names`, so matrix variant rounds that omit
svc-dns-unbound from the inventory never deployed the resolver and the admin
hung. Mark unbound enabled+shared unconditionally in compose so svc-dns-unbound
becomes `required` and the service-loader deploys it every round; drop the
unbound override from both variants so the services.yml default applies.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:46:13 +02:00
kevinveenbirkenbachandClaude Opus 4.8 99cc3f436e fix(container-address): declare service names (friendica/bbb/erpnext) + lint guard
container_address(app, key) resolves services.<key>.name; a missing key or
empty name raises at task-arg finalization and killed the compose deploys for
erpnext (no 'backend' service) and friendica (service had no name).

- web-app-friendica: add name to the friendica service
- web-app-bigbluebutton: add names for postgres/greenlight (Compose default
  <project>-<service>-<index>, upstream sets no container_name)
- web-app-erpnext: short-key all 7 sub-containers (configurator/backend/
  websocket/scheduler/queue-short/queue-long/frontend) with prefixed
  container_names, so the swarm resolver (<stack>_<key>) and compose exec
  (<container_name>) both resolve; backend addressed via container_address('backend')
- tests/lint: new guard replays container_address._resolve_bare_name over the
  static services config so a missing service/name is caught before CI deploys

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:46:13 +02:00
kevinveenbirkenbachandClaude Opus 4.8 d9e8b0a0fd fix(swarm): bound service-update redeploys so a slow or stuck one cannot hang the deploy
The OpenResty redeploy handler ('remounts bind to live inode') fires once per app; without --detach each call blocked until the full rolling convergence, so the per-app blocks accumulated into an apparent hang. openresty actually converges (clean Shutdown->Running, old replica keeps serving during the rolling update, readiness is gated separately by the converge-wait), so add --detach to return immediately. Also add timeout: 600 (10 min) to that handler and to the three single-fire app service-update-force tasks (baserow post-migration restart, matomo install restart + bootstrap re-run) as a hard cap: a genuinely stuck redeploy now fails cleanly instead of hanging forever. 600s comfortably exceeds the normal rolling convergence (~2-5 min, matomo healthcheck start_period 60s x replicas) and matches the existing timeout: 600 already used elsewhere in baserow; the three keep their blocking so the next step still gets the service ready.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:46:13 +02:00
kevinveenbirkenbachandClaude Opus 4.8 522b7f636b fix(web-app-matomo): run the bootstrap installer as a single swarm replica to avoid a DB-init race
In swarm the matomo_bootstrap service inherited compose_replicas() (topology default = node count), so multiple installer replicas ran the Matomo web-installer against the shared central DB at once and raced on table creation ('[install] Please fix the following errors'). The bootstrap is a one-shot (restart_policy: no) that must run exactly once. Add a per-service replicas override: deploy.yml.j2 honours a 'service_replicas' var when defined (else the topology default, unchanged for every other service), and matomo's compose sets service_replicas=1 for the bootstrap only. The main matomo service is rendered before the set and keeps the topology default.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:46:13 +02:00
kevinveenbirkenbachandClaude Opus 4.8 c71a35268a fix(web-app-discourse): emit empty services mapping when no local sidecar so swarm compose validates
Discourse's app container runs via the upstream discourse_docker launcher, not compose, so when every backing engine is central the rendered stack has no service of its own and 'services:' is null - the Validate Docker Compose handler then fails with 'services must be a mapping' in swarm. Emit 'services: {}' unless a local sidecar exists. The condition mirrors base.yml.j2's render gates exactly (DB/objstore/redis local via type templates that gate on 'local' = enabled and not shared, plus the oauth2 sso-proxy sidecar).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:46:13 +02:00
kevinveenbirkenbachandClaude Opus 4.8 2928db263f fix(web-svc-collabora): run container-exec via shell so the swarm subshell expands
In swarm COLLABORA_CONTAINER_ADDRESS (container_address lookup) renders a $(/usr/bin/resolve-container-id collabora collabora) subshell. With command: ansible passes it literally, so docker gets 'No such container: $(...)' (bigbluebutton fatal at the Collabora systemplate/font task). shell: runs it via /bin/sh -c so the subshell expands to the real container ID. A lint rule already requires container-exec-with-subshell tasks to use shell.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:46:13 +02:00
kevinveenbirkenbachandClaude Opus 4.8 b03719106f chore(claude): allow WebFetch(domain:typesense.org), sorted into the allow list
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:46:13 +02:00
kevinveenbirkenbachandClaude Opus 4.8 4a8aeedcf6 fix(svc-db-typesense): reset raft peers on error so single-node recovers from a swarm IP change
On a swarm redeploy/reschedule the typesense container gets a new overlay IP, but its persisted single-node raft state (/data/state) still references the previous IP, so raft never elects a leader and the task stays 'Starting' forever - the 'Wait until typesense converges to running' step then times out (e.g. funkwhale). --reset-peers-on-error makes typesense reset its raft peer config to the current node on that mismatch; the data is a re-indexable search cache. Replaces a previously misdiagnosed curl->/dev/tcp healthcheck change (reverted) - the healthcheck was never the cause since the container never reaches Running.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:46:13 +02:00
kevinveenbirkenbachandClaude Opus 4.8 e0d2749e2a style(test-volume): parenthesize patched context managers (linter reformat)
Apply the formatter's preferred multi-line 'with (...)' grouping for the mocked context managers added with the volume-lookup registry guard. No behavior change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:46:13 +02:00
kevinveenbirkenbachandClaude Opus 4.8 08e6738c93 fix(sys-svc-container): skip swarm mem_reservation in github CI so the single-node runner schedules
In github CI the whole manager-pinned stack (mailu + central infra) lands on one ~16GB runner; the cumulative deploy.resources.reservations.memory exceeds the node, so swarm rejects placement with 'no suitable node ... insufficient resources on 1 node' (mailu_admin -> bluesky). Swarm reservation accounting counts physical RAM, not swap, so the enlarged runner swap cannot help. Gate the reservations block behind RUNTIME \!= 'github' (RUNTIME is baked into the inventory from detect_runtime, confirmed =github in CI); host/dev/act keep full reservations for QoS/spread.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:46:13 +02:00
kevinveenbirkenbachandClaude Opus 4.8 4e7ccf9953 ci(test-deploy-swarm): free disk space + enlarge runner swap for parity with compose
The swarm workflow ran 3 DinD nodes plus builds on the default ~4 GB runner swap while compose/workstation/universal already enlarge it. Add the same free-disk-space (swap-storage) and enlarge_swap.sh steps, guarded with \!env.ACT, to prevent host OOM during builds. Orthogonal to swarm mem_reservation scheduling, which counts physical RAM not swap.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:46:13 +02:00
kevinveenbirkenbachandClaude Opus 4.8 fb0a5fb53d chore(web-app-keycloak): pin sso_proxy oauth2-proxy image to 26.6.3
Replace the floating 'latest' tag on the oauth2-proxy sso_proxy sidecar with a concrete version for reproducible deploys.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:46:13 +02:00
kevinveenbirkenbachandClaude Opus 4.8 28df724ce6 fix(web-app-keycloak): gate realm-import bind to compose-only so the swarm service schedules off the manager
In swarm keycloak is unpinned and can land on a worker, where the realm-import host bind /opt/compose/keycloak/volumes/import does not exist (it is created only on the manager), so the task is Rejected and never converges. The running 'start' service reads the realm from the database; the swarm import is an independent manager-pinned one-shot (05b) that mounts the dir itself, and the bind is only needed by the compose import path (05a 'compose run keycloak import'). Gate the mount with when: DEPLOYMENT_MODE \!= 'swarm'.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:46:13 +02:00
kevinveenbirkenbachandClaude Opus 4.8 687f1243cd fix(volume-lookup): force application-defaults build on registry miss so nfs_prep pre-creates the NFS subdir
lookup('volume', role) read the lazily-populated canonical-volumes registry directly, so a lookup running before any consumer built that role (nfs_prep's pre-create loop for an early unpinned engine such as ollama) saw an empty registry and skipped the subdir; the swarm bind mount then failed with 'no such file or directory'. Force get_application_defaults() on a miss, guarded so the populated hot path skips the deepcopy. Adds two guard tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:46:13 +02:00
kevinveenbirkenbachandClaude Opus 4.8 0e18481ce7 style(svc-db-qdrant): shorten meta description to its essence
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:46:12 +02:00
kevinveenbirkenbachandClaude Opus 4.8 6df91fb0c2 fix(web-app-pihole): conform compose template to lookups + disable unused email
Route image/volumes/networks through the container_image, container_volumes, compose_volumes and *_networks lookups (was a raw image ref, an inline service volumes block, and the deprecated compose_volumes pipe form); add meta/volumes.yml as the volume source and drop the four now-unused PIHOLE_IMAGE/VERSION/VOLUME vars. Pi-hole sends no mail, so the email service is pinned enabled=false/shared=false (dynamic-flag nocheck) and dropped from the variant matrix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:46:12 +02:00
kevinveenbirkenbachandClaude Opus 4.8 11d723347f chore(meta): promote services lifecycle from pre-alpha to beta
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 03:46:12 +02:00
kevinveenbirkenbach cb29f29b28 Merge branch 'main' into feature/swarm-nfs 2026-06-24 03:46:12 +02:00
kevinveenbirkenbach 0300ab384a Release 10.1.0 2026-06-24 03:46:12 +02:00
kevinveenbirkenbach 717ff4cf66 Merge pull request #230 from pragepani/feature/web-app-pihole/add-role
Feature/web app pihole/add role
2026-06-24 03:46:12 +02:00
kevinveenbirkenbach 59009a88e7 Merge pull request #334 from infinito-nexus/update/docker-image-versions-20260623-96f0af4
update(images): update Docker image versions
2026-06-24 03:46:12 +02:00
kevinveenbirkenbach e3a923fc28 Add wait_for task for Pi-hole HTTP endpoint 2026-06-24 03:46:12 +02:00
kevinveenbirkenbach e3d3f4e6a5 Delete roles/web-app-pihole/tasks/01_setup.yml 2026-06-24 03:46:12 +02:00
kevinveenbirkenbach 5856f80e7b Change lifecycle from alpha to beta 2026-06-24 03:46:12 +02:00
kevinveenbirkenbach bda2874a1a Update service configurations for web-app-pihole 2026-06-24 03:46:12 +02:00
Prageeth Panicker 8f9ee819dd fix(pihole): resolve port collision with web-app-seaweedfs (sso 16507→16508) 2026-06-24 03:46:12 +02:00
Prageeth Panicker 04e3e29901 fix(pihole): add status_codes to server.yml for health checker
Pi-hole v6 returns 308 (HTTP→HTTPS redirect) in addition to the
platform's DEFAULT_OK codes (200, 301, 302). Without 308 in the
accepted status_codes, the webserver health checker would flag
pihole.infinito.example as unhealthy.
2026-06-24 03:46:11 +02:00
Prageeth Panicker 2fc7585ae8 fix(pihole): Pi-hole v6 compatibility fixes for login and password setup
- native.spec.js: update button selector from /sign in|login/i to
  /log in|sign in/i — Pi-hole v6's submit button text is
  'Log in (uses cookie)', not 'Sign in' or 'Login'

- 01_setup.yml: remove pihole setpassword CLI task — Pi-hole v6 blocks
  this command when FTLCONF_webserver_api_password is set via env var
  ('set by environment variable; please unset it to use this function').
  Password is now set at container startup via the env var, which is
  the v6-idiomatic approach.
2026-06-24 03:46:11 +02:00
Prageeth Panicker 71a565b9f0 fix(pihole): variant-1 test failures and Pi-hole v6 compatibility
Three fixes:

1. guest.spec.js: skip instead of fail when OIDC_ISSUER_URL is unset
   (variant-1 has SSO disabled so no Keycloak redirect is expected;
   the old expect().toBeTruthy() caused a hard failure instead of skip)

2. playwright.env.j2: only emit OIDC_ISSUER_URL when SSO is proxy-gated
   (was unconditionally set, causing native.spec.js to wrongly skip in
   variant-1 and oauth2.spec.js/guest.spec.js to fail on missing redirect)

3. compose.yml.j2: Pi-hole v6 compatibility fixes
   - Replace WEBPASSWORD with FTLCONF_webserver_api_password (v6 dropped
     legacy env vars; WEBPASSWORD is silently ignored in v6)
   - Add FTLCONF_webserver_domain={{ domain }} to whitelist the nginx
     proxy Host header; Pi-hole v6 FTL returns 403 for unrecognised Host
     headers (DNS rebinding protection) — this was causing the baseline
     playwright.spec.js to fail with HTTP 403 in variant-1
2026-06-24 03:46:11 +02:00
Prageeth Panicker dc7189ddc3 fix(pihole): rename persona Playwright specs to *.spec.js so they actually run
Playwright's default testMatch only discovers files matching
*.spec.js / *.test.js. test-guest.js, test-oauth2.js, and
test-native.js never matched this pattern and were silently never
executed in any CI variant -- only playwright.spec.js's 2 baseline
tests ever ran (confirmed: 0 occurrences of these files in any
playwright-junit.xml across variant-0/variant-1, sync/async).

Renamed to guest.spec.js, oauth2.spec.js, native.spec.js so the SSO
persona scenarios (Keycloak redirect, admin/biber login, native login)
actually execute and validate the sso-proxy CA trust fix.
2026-06-24 03:46:11 +02:00
Prageeth Panicker b10a09d28c fix(pihole): use provider_ca_files (plural array), not provider_ca_file
oauth2-proxy's singular 'provider-ca-file' flag has a known bug
(oauth2-proxy/oauth2-proxy#2802) and may not be a valid config key on
:latest, causing oauth2-proxy to fail config parsing and crash on
startup. This made nginx's auth_request to sso-proxy return 500 for
every pihole request (HTTP Error 500 on https://pihole.infinito.example/),
blocking even the pre-Playwright readiness check.

provider_ca_files (plural, array of strings) is the documented,
working config key for loading a custom CA for the OIDC provider
connection.
2026-06-24 03:46:11 +02:00
Prageeth Panicker 4342f2b2d7 fix(pihole): remove duplicate sso-proxy block from compose.yml.j2
This block was added in an earlier (reverted-in-intent but never
actually removed) attempt and caused a duplicate 'sso-proxy' YAML key
(also defined via sys-svc-compose/base.yml.j2's sso_proxy include),
breaking compose_ca.py's compose config parsing entirely.

The CA trust fix now lives solely in 01_core.yml's lineinfile task,
which patches the rendered oauth2-proxy config file directly -- no
compose.yml changes needed.
2026-06-24 03:46:11 +02:00
Prageeth Panicker 08a79490fd fix(pihole): sort playwright.env.j2 keys alphabetically 2026-06-24 03:46:11 +02:00
Prageeth Panicker bd44a3036c fix(pihole): declare CANONICAL_DOMAIN in playwright.env.j2
Required by playwright.spec.js baseline checks (canonical domain
assertion), added in the previous commit.
2026-06-24 03:46:11 +02:00
Prageeth Panicker 81365a314f fix(pihole): address review feedback (Kevin)
- playwright.spec.js: remove duplicated SSO/persona scenarios now
  covered by test-guest.js/test-oauth2.js/test-native.js. Reduce to
  baseline checks (front page + TLS/HSTS, HTML content-type), matching
  the pgadmin pattern.
- meta/main.yml: rewrite description to describe Pi-hole the software
  (network-wide DNS sinkhole, DNS/DHCP management, web dashboard)
  rather than the role/integration details.
2026-06-24 03:46:11 +02:00
Prageeth Panicker 41de20d3e2 fix(pihole): resolve port collision with web-app-penpot
penpot was merged using ports 8041/16506 after our last rebase.
Reassign pihole to 8078 (http) and 16507 (sso) via
infinito contributing network ports suggest.
2026-06-24 03:46:11 +02:00