Commit Graph
11 Commits
Author SHA1 Message Date
kevinveenbirkenbachandClaude Opus 5 9bc0d834fe fix(espocrm): start the sidecars past a readiness gate that can never pass
espocrm_daemon and espocrm_websocket exited 0 every six seconds while the main
container sat healthy for thirty-nine minutes, so the deploy waited out its retries
on

    not converged: espocrm_daemon espocrm_websocket
      espocrm_daemon.1 desired=Shutdown current=Complete

The service log shows our own gate working -- "[entrypoint] Exec: docker-websocket.sh"
-- and upstream's failing right after it. docker-*.sh call exitIfNotReady, which runs
`bin/command app-check` and exits 0 when that fails. CommandManager resolves the name
to an AppCheck class, and espocrm/espocrm carries no AppCheck.php at 10.0.6, so the
gate can never pass. isLegacy does not spare us either: it returns true only when
/var/www/html is itself a mount point, and we mount three subdirectories.

Only the broken half is replaced. applyConfigEnv stays, because the websocket service
is the only carrier of ESPOCRM_CONFIG_WEB_SOCKET_*, and those reach the shared
config.php nowhere else. Readiness is the caller's job already: --wait-ready blocks on
the marker the main container writes once its install has finished, which is a
strictly better-informed signal than app-check.

The logic lives in files/shell/sidecar_boot.sh rather than a bash -c string, following
the route this role already uses for docker-entrypoint-custom.sh and seed_config.php:
copied into the build context, COPYed and chmod'ed in the Dockerfile, addressed
through ESPOCRM_SCRIPT_SIDECAR_DOCKER. That buys shellcheck and bash -n coverage the
embedded string never had, drops one layer of quoting, and turns a missing argument
into a named error instead of a php invocation with no script.

ESPOCRM_APP_DIR replaces the second hardcoded /var/www/html in vars.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-31 15:33:40 +02:00
kevinveenbirkenbachandClaude Opus 5 a77bc07d4a fix(espocrm): take the original entrypoint path from the spot
The path to the image entrypoint the build patches was written out four times in the Dockerfile, and /usr/local/bin twice more in vars. It now comes from ESPOCRM_BIN_DIR through ESPOCRM_ENTRYPOINT_SCRIPT_ORIGINAL, declared as a build ARG after FROM and passed from the compose build args. The runtime side already reads the same value from the environment, because a build ARG does not exist at runtime.

The sed expressions themselves are byte-identical. Only the file operand changed, and the variable sits outside the single quotes, so the delimiter and ampersand escaping that e272ae2d0 had to correct is untouched.

Not exercised: the four sed and grep pairs are build gates and there is no cheap target that builds a role image. A missing ARG would expand to nothing and leave sed without a file operand, which exits 4 with no input files, so the failure is loud at that layer rather than a silently broken image.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-14 13:46:31 +02:00
kevinveenbirkenbachandClaude Fable 5 e272ae2d04 fix(espocrm): correct sed delimiter and ampersand escape in entrypoint patch
The Dockerfile RUN that appends '|| true' to the upstream create-admin-user line used '|' as the sed delimiter, which collides with the '||' in the replacement (sed: unknown option to s), and left the '&' in '2>&1' unescaped (sed expands it to the whole match). Use '#' as the delimiter and escape the ampersand as '\&'.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 01:12:29 +02:00
kevinveenbirkenbachandClaude Opus 4.8 3a6c181dc8 fix(espocrm): tolerate an existing admin during upstream first-boot install
The upstream v10 entrypoint runs create-admin-user unguarded under
set -euo pipefail; on a persistent database that already holds the
admin (redeploy, DR recovery) it exits non-zero and aborts the install
before isInstalled is persisted, so every boot re-runs the install and
crash-loops. Append '|| true' the same way the adjacent set-password
line is already patched; the grep guard fails the build if upstream
moves the line.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 16:15:27 +02:00
kevinveenbirkenbachandClaude Fable 5 842ad7e356 fix(espocrm): patch hardcoded set-password admin in the v10 entrypoint
Upstream actionInstall() runs create-admin-user "$ESPOCRM_ADMIN_USERNAME"
but then pipes the password to a hardcoded 'set-password admin' (line 203,
verified in the 10.0.2 image); with our admin named 'administrator' the
silenced failure aborts the install under set -euo pipefail and loops the
container. Patch the line at image build time; the grep guard fails the
build if a future image reshapes it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 03:15:53 +02:00
kevinveenbirkenbachandClaude Opus 4.8 2944a7fc5d fix(espocrm): bake code node-local, share only mutable dirs over NFS
The stock image lays the app under /var/www/html from /usr/src at runtime, so the whole webroot landed on the shared NFS volume; on kernel-nfsd the www-data Apache workers on a non-populating swarm node get EPERM serving that root-owned code (403), and the stack never converges. Bake the code into the image at build time so /var/www/html is node-local on every replica, and share only data/, custom/ and client/custom over NFS. Move the boot-lock and ready-marker into the shared data/ so replicas still serialize the one-time install, keep the ready-marker check ahead of the lock (a serving replica must not re-enter the image entrypoint and rebuild the shared cache, which aborts 255), and chown the three shared dirs. Verified in compose (deploy + hard-restart + e2e); swarm eliminates cross-node code access by construction.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 00:03:34 +02:00
kevinveenbirkenbachandClaude Opus 4.8 9ecb2f8f5e test(lint): cover Dockerfiles in the comments lint
Dockerfiles have no suffix, so the comments lint never scanned them. Match the Dockerfile basename in the changed-targets collector and dispatch it to the hash-comment parser; changed-files-only semantics stay, so the legacy tree is unaffected until a Dockerfile is touched. Drop the remaining prose comment from the espocrm Dockerfile it immediately flagged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 02:37:27 +02:00
kevinveenbirkenbachandClaude Opus 4.8 e7ee192162 refactor(espocrm): full multi-replica conversion
Drop the replicas:1 pin and make the web tier genuinely scalable. The custom entrypoint now runs the image entrypoint's install/upgrade/config-seed exactly once cluster-wide: an atomic mkdir mutex on the shared volume root (flock is node-local on this NFS mount), the image init invoked with /bin/true so its final exec returns control, a ready marker for followers, stale-lock takeover past the orchestrator kill ceiling and TERM/INT release; every replica then starts apache itself. Previously the image entrypoint execed apache directly, so the seed/clear-cache block was dead code - it now runs as intended. PHP sessions move to the NFS-shared data/.sessions via a conf.d ini so OIDC/SAML handshakes survive replica hops. The cron daemon and the websocket service become explicitly pinned singletons (they only inherited the entity pin before). A missing image entrypoint after a version bump now fails loudly (upstream master restructured the entrypoint; 9.3.10 is verified). Converge retries 600, healthcheck start_period 15m, seeder debug env renamed out of the ESPOCRM_SEED_ config prefix scan.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 02:37:26 +02:00
Environment TestandClaude Sonnet 4.6 1db58af7fd fix(docker): replace ENV-based ENTRYPOINT with RUN symlink in espocrm and suitecrm
The ENV approach failed at runtime because the ca-trust-wrapper does not
propagate container ENV variables when executing the wrapped ENTRYPOINT,
causing $ESPOCRM_ENTRYPOINT_SCRIPT_DOCKER / $SUITECRM_ENTRYPOINT_SCRIPT_DOCKER
to remain unexpanded ("not found" error in CI).

Replace with a RUN-time symlink (ln -sf) so the dynamic ARG path is baked
into the image filesystem layer. ENTRYPOINT now uses the fixed /entrypoint.sh
path, which is independent of ENV propagation and cache state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 21:48:18 +02:00
Environment TestandClaude Sonnet 4.6 1c026ce6ef fix(docker): remove quoted FROM and fix ENTRYPOINT ARG expansion in 4 roles
- Remove quotes from FROM instruction in confluence, jira, suitecrm, espocrm Dockerfiles
  (Docker does not strip quotes — quoted image references are invalid)
- Promote ENTRYPOINT_SCRIPT_DOCKER ARG to ENV in espocrm and suitecrm so the
  runtime shell can resolve the path (ARG is not expanded in ENTRYPOINT exec form)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 12:40:28 +02:00
kevinveenbirkenbachandClaude Sonnet 4.6 f5a81736cf refactor(roles): convert Dockerfile.j2 templates to plain files/Dockerfile
Replace Jinja2 Dockerfile templates with static Dockerfiles using Docker
ARG statements. Variables are now passed as build args in compose.yml.j2,
following the existing pattern from web-app-bridgy-fed. Affects 12 roles:

- svc-db-openldap
- web-app-bookwyrm
- web-app-confluence
- web-app-espocrm
- web-app-jira
- web-app-joomla
- web-app-mediawiki
- web-app-pretix
- web-app-shopware
- web-app-suitecrm
- web-app-xwiki
- web-svc-simpleicons

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 00:28:37 +02:00