Commit Graph
14682 Commits
Author SHA1 Message Date
kevinveenbirkenbachandClaude Opus 4.8 cbe2a3b091 refactor(mobilizon): drop the single-replica pin so it scales
Uploads ride the NFS-shared named volume (Local uploader), auth is stateless Guardian JWT with a shared secret_key_base, and boot migrations serialize on Ecto's default migration_lock against shared Postgres. Removing replicas:1 lets compose_replicas pick the topology count; compose ignores it. Confidence ~95% (static + deep-dive; no live swarm run).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 02:22:38 +02:00
kevinveenbirkenbach ebc4bc86f5 Merge branch 'main' into feature/swarm-nfs 2026-07-07 01:28:48 +02:00
kevinveenbirkenbachandClaude Opus 4.8 a4da2faa12 chore(claude): allow WebFetch docs.nextcloud.com
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 01:18:57 +02:00
kevinveenbirkenbachandClaude Opus 4.8 6e4f4a4377 fix(pihole): skip the swarm deploy mode (compose-only)
A recursive DNS resolver binds :53 udp/tcp on the host and has no horizontally-scalable swarm topology (the routing mesh cannot load-balance the resolver), so pihole opts out of swarm discovery and deploys compose-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 01:16:54 +02:00
kevinveenbirkenbachandClaude Opus 4.8 283108f802 test(lint): require a single-replica nocheck marker on every replicas:1 pin
Adds tests/lint/ansible/roles/test_single_replica_justified.py: a bare replicas:1 in meta/services.yml is flagged so a single-replica pin is never applied silently; services that can scale should carry no replicas key and let compose_replicas pick the topology default. Marks the pins on genuinely single-instance services (audit-verified as unscalable): checkmk OMD/RRD single-writer, erpnext websocket/scheduler/configurator sidecars, jenkins controller, listmonk campaign-manager singleton, mastodon db:prepare one-shot, minio single-node (no erasure), opencloud decomposedfs+NATS single-writer, seaweedfs single-node, taiga admin sidecar, ejabberd standalone Mnesia.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 01:14:29 +02:00
kevinveenbirkenbachandClaude Opus 4.8 a6dae38590 fix(ci): auto-build act runner image and probe toolless containers
act/workflow.sh: build local/act-runner-fixed:latest on demand when that tag is selected but the image is absent, avoiding an image-not-found failure. swarm/_context.sh: probe_app_reachable falls back to a bash /dev/tcp connect and finally the container's own Docker health status, so toolless images (e.g. fider's debian-slim without curl/wget/nc, which exit 127 on every in-container probe) are no longer reported unreachable. Both additions are additive: the curl/wget/nc path and the non-matching act tag are unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 00:55:16 +02:00
kevinveenbirkenbachandClaude Opus 4.8 cc03c72736 test(penpot): target the login submit button by testid, not the Login label
Penpot 2.14+ relabelled the native-login button (Login -> Continue), so the /^Login$/ role-name locator no longer matched and the e2e login flow failed on the 2.16 upstream UI. Use the stable data-testid=login-submit locator instead.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 00:46:50 +02:00
kevinveenbirkenbachandClaude Opus 4.8 cb6c0edaf9 fix(joomla): raise healthcheck start_period to 15m for the first-boot install
The stock install runs blocking in the entrypoint before apache serves, so no HTTP is answered during it and the only healthcheck lever is start_period. The entrypoint's follower-wait already tolerates a ~10min leader install (300x2s), but start_period was 5m, so in swarm the leader or a waiting follower was reaped mid-install, orphaning the mkdir lock and deadlocking the shared-NFS init. Raise start_period to 15m so it exceeds the follower-wait window and no task is reaped mid-install. Compose is unaffected (it does not reap on unhealthy).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 00:44:18 +02:00
kevinveenbirkenbachandClaude Opus 4.8 3cf83bfab1 fix(rdbms): reset compose_mode_force when initing the shared DB provider
A consumer that forces a per-role deploy mode (web-app-matrix ansible-flavor and web-app-bigbluebutton set compose_mode_force=compose) leaked that value through the include_role chain into the shared database provider (svc-db-postgres/mariadb). In a swarm cluster the provider then ran via 'docker compose up' (bridge) instead of 'docker stack deploy' (overlay), breaking the shared DB. Reset compose_mode_force to empty on the provider include, alongside the existing compose_repository_pull override, so the shared provider always follows the cluster DEPLOYMENT_MODE. Covers every consumer, not just matrix/bbb.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 00:31:38 +02:00
kevinveenbirkenbachandClaude Opus 4.8 6b07289d6b perf(swarm-registry-sync): drop mirrored externals from the engine after push
On disk-constrained sync runners (act/CI) a mirrored external image was double-stored: once in the docker engine and once in the local registry. After pushing, docker rmi the upstream and prefixed tags so only the registry copy remains; swarm re-pulls from the registry at deploy time. Locally-built images are never removed (recovery and base images depend on them staying in the engine store). Also skip the re-pull when the prefixed image already has a registry manifest. The compose image rewrite and registry push are unchanged; rmi is best-effort.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 00:18:13 +02:00
kevinveenbirkenbachandClaude Opus 4.8 1f83ede271 fix(networks): omit the network name line when own_entity is empty
Roles whose get_entity_name(application_id) resolves to an empty string (e.g. svc-runner) rendered 'name: ' with no value in the compose networks block, producing an invalid/empty network definition. Guard both the swarm overlay and the compose bridge emissions so the name line is only written when own_entity is non-empty; docker then auto-names the network. Add regression tests for both modes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 00:13:35 +02:00
kevinveenbirkenbachandClaude Opus 4.8 40a9eb5080 chore(format): autoformat wrap of test_tor_node read_text call
make autoformat re-wrapped the hostname read_text over multiple lines and moved the # nocheck: cache-read to the closing .strip() line; test-lint stays green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 00:11:55 +02:00
infinito-nexus-updater[bot] 36eb464f2f update(images): update Docker image versions (web-app-pihole) 2026-07-06 22:08:52 +00:00
kevinveenbirkenbachandClaude Opus 4.8 0bc601c587 chore(snipe-it): update image to v8.6.3-alpine
Pin from the floating latest-alpine tag to v8.6.3-alpine (published 2026-06-15).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 00:06:56 +02:00
kevinveenbirkenbachandClaude Opus 4.8 afc4592a3b fix(snipe-it): use redis for cache and sessions so replicas share state
The .env boilerplate set CACHE_DRIVER=file / SESSION_DRIVER=file, overriding the intended redis config (already wired via the engine lookup). That made sessions node-local and made the custom image's 'migrate --force --isolated' take a file-based lock, so concurrent swarm replicas did not coordinate the first migration. Drop the file overrides so cache, sessions and the isolated migration lock all use the shared redis. Extend start_period to 5m for the first-boot migrate and seed, and raise swarm converge retries to match.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 00:05:33 +02:00
kevinveenbirkenbach 620c4f92e9 Merge branch 'main' into feature/svc-net-tor 2026-07-06 23:54:07 +02:00
kevinveenbirkenbach 3b159c3940 Merge pull request #383 from infinito-nexus/update/docker-image-versions-web-app-seaweedfs-20260706-61503dd
update(images): update Docker image versions (web-app-seaweedfs)
2026-07-06 23:54:07 +02:00
kevinveenbirkenbach f86b68f265 Merge pull request #385 from infinito-nexus/update/docker-image-versions-web-app-mattermost-20260706-276ac10
update(images): update Docker image versions (web-app-mattermost)
2026-07-06 23:54:07 +02:00
infinito-nexus-updater[bot] d180a6e439 update(images): update Docker image versions (web-app-seaweedfs) 2026-07-06 23:54:07 +02:00
kevinveenbirkenbach 685117caf8 Merge pull request #386 from infinito-nexus/update/docker-image-versions-web-app-opencloud-20260706-bf0f4da
update(images): update Docker image versions (web-app-opencloud)
2026-07-06 23:54:07 +02:00
infinito-nexus-updater[bot] 1a4fdd73ee update(images): update Docker image versions (web-app-mattermost) 2026-07-06 23:54:06 +02:00
kevinveenbirkenbach 5d45ee1ddd Delete .claude/settings.local.json 2026-07-06 23:54:06 +02:00
kevinveenbirkenbach 1f9ab19669 Merge pull request #382 from infinito-nexus/update/docker-image-versions-web-app-decidim-20260706-fec8750
update(images): update Docker image versions (web-app-decidim)
2026-07-06 23:54:06 +02:00
infinito-nexus-updater[bot] 0e449c5596 update(images): update Docker image versions (web-app-opencloud) 2026-07-06 23:54:06 +02:00
kevinveenbirkenbach a9ce4bc52d Merge pull request #381 from infinito-nexus/dependabot/github_actions/docker/login-action-4.4.0
chore(deps): bump docker/login-action from 4.3.0 to 4.4.0
2026-07-06 23:54:06 +02:00
kevinveenbirkenbach 508509bf28 Merge pull request #384 from infinito-nexus/update/docker-image-versions-web-app-semaphore-20260706-4dc9aff
update(images): update Docker image versions (web-app-semaphore)
2026-07-06 23:54:06 +02:00
infinito-nexus-updater[bot] b4f3b4ebd8 update(images): update Docker image versions (web-app-decidim) 2026-07-06 23:54:06 +02:00
infinito-nexus-updater[bot] 0a5be925f9 update(images): update Docker image versions (web-app-semaphore) 2026-07-06 23:54:06 +02:00
kevinveenbirkenbach f2e47ed42b Merge pull request #379 from infinito-nexus/update/docker-image-versions-web-app-prometheus-20260704-fa62dcb
update(images): update Docker image versions (web-app-prometheus)
2026-07-06 23:54:05 +02:00
dependabot[bot] a7538bd9c2 chore(deps): bump docker/login-action from 4.3.0 to 4.4.0
Bumps [docker/login-action](https://github.com/docker/login-action) from 4.3.0 to 4.4.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/c99871dec2022cc055c062a10cc1a1310835ceb4...af1e73f918a031802d376d3c8bbc3fe56130a9b0)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 4.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-06 23:54:05 +02:00
infinito-nexus-updater[bot] d4370f769c update(images): update Docker image versions (web-app-prometheus) 2026-07-06 23:54:05 +02:00
kevinveenbirkenbachandClaude Opus 4.8 f36a6236df chore(format): make autoformat whitespace on unrelated roles
Pure formatting from make autoformat (a folded long Jinja line in svc-runner vars; double->single space before # nocheck comments in jitsi/openproject/rdr-www services and mailu/openwebui/snipe-it/web-svc-file variants). No semantic changes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:53:19 +02:00
kevinveenbirkenbachandClaude Opus 4.8 1f60e2b3fa feat(variants): tor variant coverage for keycloak/lam/matrix/wordpress/rdr-www
Add the tor.enabled true/false rounds (shared:false + nocheck on the disabled round) so the dynamic tor flag is covered on these roles, and reorder each variant services-first so the tor nocheck registers. Each variant keeps its exact keys (credentials / addons / server.domains preserved, values unchanged) — mapping key order only; no cross-variant moves.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:53:18 +02:00
kevinveenbirkenbachandClaude Opus 4.8 ad2913288a feat(svc-db): tor variant coverage for redis + memcached
Add meta/variants.yml with the tor.enabled true/false rounds (shared:false on the disabled round) so the dynamic tor flag is covered for the two embedded cache DBs. No exposed field — redis/memcached stay stubs (embedded per-consumer, no standalone host port).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:53:18 +02:00
kevinveenbirkenbachandClaude Opus 4.8 f6bed25b67 feat(services): resolve_service_config with provider fallback
Resolve services.<key>.<field> with consumer-override -> provider-native fallback (the provider being the role whose entity name is <key>, e.g. svc-net-tor for tor). Keeps provider defaults like tor.exclusive/tor.primary in one place while consumers stay free to override per app; consumed by utils.cache.domains for onion-domain injection.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:53:18 +02:00
kevinveenbirkenbachandClaude Opus 4.8 897abcc28c feat(test-harness): route Tor tests via the SOCKS SPOT + secure the CLI stage
test-e2e-cli renders test.env at 0600 in a 0700 stage dir and always removes the stage tree (it holds base64 DB credentials). test-e2e-playwright + the e2e scripts resolve the node SOCKS from the single spot: playwright via lookup('tor_socks', 'host.docker.internal'), onion.sh takes it as a required arg, rerun-spec.sh composes it from INFINITO_TOR_SOCKS_PORT — no 9050 literal or backup.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:53:18 +02:00
kevinveenbirkenbachandClaude Opus 4.8 005f649498 refactor(onion): the inventory provisioner is the SPOT for the node onion
Mint the node onion during provisioning and write its address straight into applications.svc-net-tor.services.tor.node, dropping the INFINITO_TOR_NODE_ONION env indirection: ensure_node_onion (was init_env) mints/reuses the .onion-identity key files + returns the address (no env write); identity_hs_dir/IDENTITY_DIRNAME move to utils.tor_onion so cli and utils share the path SPOT; provision.apply_tor_node_onion sets services.tor.node in host_vars when svc-net-tor is deployed (run by 'inventory provision' at deploy time, and the svc-net-tor role copies the same key files into the daemon); domains.py reads services.tor.node; nginx_vhosts reads the key file instead of os.environ; INFINITO_TOR_NODE_ONION removed from default.env/passthrough/compose + the inventory env-lookup. Bonus: the address now lives in the persistent key files, surviving .env regeneration by make test/autoformat.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:53:18 +02:00
kevinveenbirkenbachandClaude Opus 4.8 e471770299 feat(env): INFINITO_TOR_SOCKS_PORT handler from the SOCKS port SPOT
New env handler reads svc-net-tor services.tor.ports.local.socks (via ROLE_FILE_META_SERVICES) and emits INFINITO_TOR_SOCKS_PORT; registered in the handler registry + passthrough static keys + default.env, and forwarded to the container by compose.yml — so shell consumers (the Playwright rerunner) get the port without a literal. 08_networks.yml adds the local.socks PORT_BANDS band (9050).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:53:18 +02:00
kevinveenbirkenbachandClaude Opus 4.8 456ff59ca6 feat(lookups): tor_socks endpoint SPOT + tor_ports exposed-port forwarding
tor_socks returns <host>:<port> from svc-net-tor services.tor.ports.local.socks (single spot; default host 127.0.0.1, host overridable for 0.0.0.0/host.docker.internal). tor_ports gains variant-aware collect_exposed_ports: the loopback ports.local of exposed:true services become per-variant onion HiddenServicePort targets (public/TLS ports excluded).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:53:18 +02:00
kevinveenbirkenbachandClaude Opus 4.8 221ea9bd71 feat(svc-net-tor): declare node onion + SOCKS port SPOTs
meta/services.yml gains tor.node (node onion address, filled per environment by the inventory) and tor.ports.local.socks (SOCKS port single source of truth). torrc renders SocksPort via the tor_socks lookup; the role test.sh takes TOR_SOCKS from the environment instead of a hard-coded 127.0.0.1:9050.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:53:18 +02:00
kevinveenbirkenbachandClaude Opus 4.8 4e582c9d86 fix(svc-db): satisfy shellcheck + env-sort lint on the DB test scaffolding
test.sh: dispatch auth via a run_auth wrapper calling auth_tor/auth_local directly — shellcheck SC2317 flagged the indirect ${attempt_fn} invocation as unreachable. test.env.j2: sort keys ASC for the env alphabetical-order lint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:53:18 +02:00
kevinveenbirkenbachandClaude Opus 4.8 111e8cc7b2 feat(svc-db): per-DB exposed toggle + Tor/local credential tests
Add exposed: bool (default false) to svc-db-postgres/mariadb/openldap meta/services.yml with a variant-0 (exposed) / variant-1 (not) toggle, plus real credential e2e tests (files/test/test.sh + templates/test.env.j2): authenticate with actual credentials over the node Tor SOCKS proxy when the variant enables tor, locally in-container (password auth) otherwise. mariadb/openldap force the local publish (+ OPENLDAP_PORT var); secrets stay off the process argv (MYSQL_PWD, ldapwhoami -y /dev/stdin, PGPASSWORD env).

Depends on shared onion pieces landing in a follow-up commit: tor_ports exposed-port collection, svc-net-tor services.tor.node + services.tor.ports.local.socks SPOT, the tor_socks lookup, and test-e2e-cli 0600/stage-cleanup.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:53:17 +02:00
kevinveenbirkenbachandClaude Opus 4.8 fd7a808409 feat(tor): add onion on/off variant coverage to svc-prx-openresty
Provides the tor.enabled true/false matrix coverage (variant 0 on, non-baseline off) for the openresty proxy role, matching the per-role tor variant contract.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:53:17 +02:00
kevinveenbirkenbachandClaude Opus 4.8 c4e64656be test(tor): let onion-surfaceless domain roles opt out of the tor contract
test_tor_contract gains a '# nocheck: tor-contract' opt-out (it previously only excluded svc-net-tor by name). web-opt-rdr-domains, a redirect-only role with no onion surface, drops its tor block and marks the exemption; its variant-coverage stub is removed with it. The new rule is registered in docs/contributing/actions/testing/suppression.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:53:17 +02:00
kevinveenbirkenbachandClaude Opus 4.8 3f7face0aa feat(test-e2e-playwright): route .onion apps through Tor + defaults->vars refactor
Per-app PLAYWRIGHT_PROXY: an app whose canonical URL is a .onion (services.tor primary/exclusive) has its browser routed through the node Tor SOCKS proxy (socks5://host.docker.internal:9050); clearnet apps stay direct. A SOCKS readiness gate probes the hidden service and skips (not fails) the app's run when Tor cannot reach it. TEST_E2E_PLAYWRIGHT_PROXY is removed since the per-app logic supersedes the global knob. Non-overridable tuning constants moved defaults->vars (UPPERCASE); only genuinely overridable knobs (only_roles/skip_roles/keep/VARIANT_INDEX) remain in defaults.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:53:17 +02:00
kevinveenbirkenbachandClaude Opus 4.8 77be21f5fd feat(tor): mark tor as non-playwright-gateable in domain services.yml
Onion routing is transport-layer with no persona/UI surface, so tor cannot be gated from the per-persona Playwright specs. Mark the tor block with '# nocheck: playwright-service-flag' in the 60 domain roles that ship a playwright.env.j2, per test_env_services_match's documented exemption for services that legitimately cannot be Playwright-gated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:53:17 +02:00
kevinveenbirkenbachandClaude Opus 4.8 1d9d355bc9 feat(tor): add onion on/off variant coverage to domain roles
Each role's meta/variants.yml now pins the tor onion gate both ways so the matrix exercises it: variant 0 pins services.tor.enabled: true, every non-baseline variant pins enabled: false + shared: false (# nocheck: variants-static-override, since tor.shared is a static literal). This gives real test_coverage / test_bond_baseline coverage without the removed per-key code exemptions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:53:17 +02:00
kevinveenbirkenbachandClaude Opus 4.8 0a7164af48 feat(tor): per-role onion service block in meta/services.yml
Domain-serving roles reference the svc-net-tor provider via a tor: block. Consumers declare enabled (dynamic group_names gate) and shared: true (static — onion is always the shared node model, inline nocheck: dynamic-flag). The provider svc-net-tor additionally declares exclusive/primary defaults that consumers inherit via resolve_service_config unless overridden.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:53:16 +02:00
kevinveenbirkenbach be3591b6d5 Merge pull request #383 from infinito-nexus/update/docker-image-versions-web-app-seaweedfs-20260706-61503dd
update(images): update Docker image versions (web-app-seaweedfs)
2026-07-06 23:36:29 +02:00
kevinveenbirkenbach ec7f62d50c Merge pull request #385 from infinito-nexus/update/docker-image-versions-web-app-mattermost-20260706-276ac10
update(images): update Docker image versions (web-app-mattermost)
2026-07-06 23:33:31 +02:00