fix(matomo): keep ephemeral cache off NFS and reset DB on bootstrap retry

Matomo's swarm bootstrap failed rc=1: the high-churn tmp/templates_c Twig cache lived on the soft NFS state share, so a single mid-write RPC timeout surfaced as EIO and stalled the installer 300s; the DB was already seeded, so retries took the eraseAllTables path that wedged Matomo on the CoreUpdater screen the bootstrap image cannot click through. Mount a node-local matomo_tmp volume (nfs: false) for /var/www/html/tmp so caches never traverse NFS, and drop+recreate the app's own database in the pre-retry cleanup (via a container-run reset_database.php over the app credentials, gated exactly like the config-aside task on attempt>0 + no installed config) so every retry takes the clean-install path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
kevinveenbirkenbachandClaude Opus 4.8 committed 2026-07-22 20:50:17 +02:00
1 parent 97f6679243
commit e46659ac4b
3 files changed
+38

No files matched your search

@@ -0,0 +1,17 @@
<?php
/**
* Drop and recreate the Matomo database so a bootstrap retry takes the
* clean-install path. Runs inside the matomo container via stdin.
*
* Env (from the container):
* MATOMO_DATABASE_HOST host or host:port
* MATOMO_DATABASE_DBNAME database to reset
* MATOMO_DATABASE_USERNAME app user (holds ALL on the database)
* MATOMO_DATABASE_PASSWORD app password
*/
[$host, $port] = array_pad(explode(':', getenv('MATOMO_DATABASE_HOST')), 2, 3306);
$db = getenv('MATOMO_DATABASE_DBNAME');
$pdo = new PDO("mysql:host=$host;port=$port", getenv('MATOMO_DATABASE_USERNAME'), getenv('MATOMO_DATABASE_PASSWORD'));
$pdo->exec("DROP DATABASE IF EXISTS `$db`");
$pdo->exec("CREATE DATABASE `$db`");
echo "OK: database `$db` reset\n";
+9
View File
@@ -5,3 +5,12 @@ data:
mounts:
- service: matomo
target: /var/www/html
tmp:
type: volume
name: matomo_tmp
# nocheck: nfs-false-data-loss Reason: regenerable Twig/session cache; Matomo requires per-server tmp/ and rebuilds it on demand
nfs: false
mounts:
- service: matomo
target: /var/www/html/tmp
@@ -12,6 +12,18 @@
- matomo_config_exists.rc | int != 0
- ((matomo_bootstrap_swarm | default({})).rc | default(1)) | int != 0
- name: "🧹 Matomo bootstrap | Swarm: reset the database so the retry takes the clean-install path"
ansible.builtin.shell: # nocheck: container-exec-resolver MATOMO_LOCAL_CID resolved at delegate_to runtime; container_address would return a manager-only subshell
cmd: "container exec -i --user root {{ MATOMO_LOCAL_CID | quote }} php"
stdin: "{{ lookup('file', 'reset_database.php') }}"
changed_when: true
delegate_to: "{{ MATOMO_HOST_NODE }}"
when:
- IS_STACK_HOST | bool
- matomo_attempt_index | int > 0
- matomo_config_exists.rc | int != 0
- ((matomo_bootstrap_swarm | default({})).rc | default(1)) | int != 0
- name: "🐝 Matomo bootstrap | Swarm: force installer run and wait for its token"
ansible.builtin.script: "{{ role_path }}/files/bootstrap_swarm_poll.sh"
environment: