From d476bca4f5a228c54743248c62a9c72d250cd8ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20B=C3=A4rlocher?= Date: Tue, 26 May 2026 14:04:33 +0200 Subject: [PATCH] fix(nextcloud): in-container patch for UserConfig::getValueBool TypeError nextcloud/server#59629: under PHP 8.x with OPcache, UserConfig::getValueBool() passes a non-string from getTypedValue() straight into strtolower(), throwing a TypeError on every authenticated request once user_ldap is involved. Fix landed in master (PR #59646) but no stable33 backport made it into 33.0.4. Discover all compose-managed nextcloud containers, check whether the `strtolower((string)` cast is already present, and `sed` it into `lib/private/Config/UserConfig.php` on the ones that still ship the broken version. Idempotent via grep guard so re-runs are no-ops. Remove this block once the deployed image >= 33.0.4 ships the upstream fix. --- roles/nextcloud/tasks/main.yml | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/roles/nextcloud/tasks/main.yml b/roles/nextcloud/tasks/main.yml index 8d2a5cd..a5c8dc9 100644 --- a/roles/nextcloud/tasks/main.yml +++ b/roles/nextcloud/tasks/main.yml @@ -49,6 +49,42 @@ project_src: "{{ nextcloud_docker_compose_dir }}" state: present +# nextcloud/server#59629: UserConfig::getValueBool() passes a non-string from +# getTypedValue() into strtolower() under PHP 8.x + OPcache, throwing a +# TypeError on every authenticated request once user_ldap is involved. Fix +# is in master (PR #59646) but no stable33 backport landed before 33.0.4. +# Apply the (string) cast in-container; idempotent via grep guard. Remove +# this block once nextcloud_image >= 33.0.4. +- name: Discover nextcloud php containers needing the UserConfig patch + ansible.builtin.shell: + cmd: >- + docker ps --filter "label=com.docker.compose.project={{ nextcloud_docker_compose_dir | basename }}" + --filter "label=com.docker.compose.service=nextcloud" + --format '{% raw %}{{.Names}}{% endraw %}' + register: _nextcloud_php_containers + changed_when: false + +- name: Check UserConfig.php patch status per container + ansible.builtin.shell: + cmd: >- + docker exec {{ item }} grep -q "strtolower((string)" /var/www/html/lib/private/Config/UserConfig.php + loop: "{{ _nextcloud_php_containers.stdout_lines }}" + register: _nextcloud_userconfig_check + changed_when: false + failed_when: false + +- name: Apply UserConfig::getValueBool string-cast workaround + ansible.builtin.shell: + cmd: >- + docker exec {{ item.item }} + sed -i 's|$b = strtolower($this->getTypedValue|$b = strtolower((string)$this->getTypedValue|' + /var/www/html/lib/private/Config/UserConfig.php + loop: "{{ _nextcloud_userconfig_check.results }}" + loop_control: + label: "{{ item.item }}" + when: + - item.rc | default(1) != 0 + - name: Wait for Nextcloud to be ready ansible.builtin.shell: cmd: docker compose exec -T nextcloud php /var/www/html/occ status --output=json