diff --git a/collabora/CHANGELOG.md b/collabora/CHANGELOG.md index 116a541546..6792738832 100644 --- a/collabora/CHANGELOG.md +++ b/collabora/CHANGELOG.md @@ -1,4 +1,19 @@ +## 26.04.2.4.1 (2026-07-26) +- Rebuild on a Debian base: upstream turned collabora/code into a distroless image with no shell, which broke the addon build entirely. collabora/code stays the tracked upstream image in build.json, but is now a build stage whose payload is copied onto ghcr.io/hassio-addons/debian-base, and the addon ships its own launcher in place of the removed /start-collabora-online.sh +- build.json names the architecture explicitly again (`collabora/code:latest-amd64` and `collabora/code:latest-arm64`). The builder never passes `--platform`, so the tag is the only thing that decides which binaries land in the addon +- Restore the file capabilities on `coolforkit-caps` and `coolmount`. The official image carries them as extended attributes, which `COPY --from` does not transfer, and without them Collabora starts but cannot open any document +- The certificates for `ssl: true` are read from the copies in /etc/coolwsd rather than from /ssl directly, which Collabora could not read as uid 1001 when the private key is root-only +- Make the `ssl` option authoritative even when `extra_params` is empty or customized. `ssl: false` now always disables Collabora's internal HTTPS instead of silently falling back to its default self-signed TLS +- Fix version numbering: releases on CollaboraOnline/online are now Helm charts only, which had renumbered the addon from 25.4.9.2 down to 1.3.0 and hid updates. The version is tracked from the collabora/code Docker Hub tags again +- `server_name` is now passed to Collabora, fixing `Your browser has been unable to connect to the Collabora server` behind a reverse proxy +- `domain1` was never passed to Collabora at all (the script read a `domain` option that does not exist, and recent Collabora releases dropped that variable). It is now deprecated and applied as `server_name` +- `aliasgroup*` values are normalised: unescaped, escaped and double-escaped dots all produce the correct regex, and the value handed to Collabora is printed in the log +- Added `ssl_termination`, needed when `ssl` is false but Collabora is reached over https through a reverse proxy +- Added `aliasgroup2` and `aliasgroup3` for additional Nextcloud servers +- `cert_domain` is now a string (it is a certificate common name) and is passed to Collabora +- Documented the above, and corrected the README which asked for two backslashes where Collabora expects one + ## 1.3.0 (2026-07-16) - Update to latest version from CollaboraOnline/online (changelog : https://github.com/CollaboraOnline/online/releases) diff --git a/collabora/Dockerfile b/collabora/Dockerfile index e6a80949e9..a14f258332 100644 --- a/collabora/Dockerfile +++ b/collabora/Dockerfile @@ -16,7 +16,45 @@ ARG BUILD_FROM ARG BUILD_VERSION -FROM ${BUILD_FROM} + +############################################################################### +# Get Collabora Online from the official image (BUILD_FROM, see build.json) +# +# build.json pins the architecture explicitly, collabora/code:latest-amd64 and +# collabora/code:latest-arm64, rather than the multi-arch collabora/code:latest. +# The builder never passes --platform: it runs the amd64 build on a native amd64 +# runner and the aarch64 build on a native arm runner, so the only thing that +# decides which Collabora binaries end up in the add-on is this tag. With the +# multi-arch tag that happens to resolve correctly, but only for as long as the +# runner architecture keeps matching the target, and a mismatch would silently +# produce an image full of foreign-architecture binaries. The per-arch tags are +# published in lockstep with latest, so nothing is lost by naming them. +# +# Upstream rebuilt collabora/code as a Nix-based distroless image: /bin and +# /sbin are empty, so it can no longer be the base of the add-on itself, as s6, +# bashio and every RUN need a shell. It stays the tracked upstream image, and +# only the Collabora payload is copied out of it onto a Debian runtime. +# +# Copy only what belongs to Collabora. Do NOT copy /etc or /nix: in that image +# /etc/resolv.conf, /etc/hosts, /etc/passwd, /etc/group and /etc/nsswitch.conf +# are symlinks into /nix/store, and importing them breaks DNS resolution and +# wipes the base image users. +############################################################################### +# hadolint ignore=DL3006 +FROM ${BUILD_FROM} AS collabora + +############################################################################### +# Build the actual add-on on a base that has a shell +############################################################################### +FROM ghcr.io/hassio-addons/debian-base:9.3.0 + +# Inherited from the base, declared here so it is visible to hadolint and to +# anyone adding a pipe below. Note that the linkage check does NOT pipe into +# grep: with pipefail an ldd that exits non-zero (a binary it cannot handle at +# all) would make the pipeline fail even though grep matched, and "if" would +# then read that as "no unresolved libraries" -- the one case worth catching. +# Capturing the output and matching it with case avoids the question entirely. +SHELL ["/bin/bash", "-o", "pipefail", "-c"] ################## # 2 Modify Image # @@ -55,11 +93,88 @@ COPY ha_automodules.sh /ha_automodules.sh RUN chmod 744 /ha_automodules.sh && /ha_automodules.sh "$MODULES" && rm /ha_automodules.sh # Manual apps -ENV PACKAGES="" +# coolwsd itself only needs glibc/libstdc++ (max GLIBCXX_3.4.22); the office +# engine bundles its own cairo, fontconfig, curl, icu and fonts under +# /opt/collaboraoffice/program. openssl is used to generate the self-signed +# certificate when the ssl option is off, cpio and findutils by the jail setup. +ENV PACKAGES="ca-certificates cpio findutils fontconfig libcap2-bin libstdc++6 openssl tzdata" # Automatic apps & bashio COPY ha_autoapps.sh /ha_autoapps.sh -RUN chmod 744 /ha_autoapps.sh && /ha_autoapps.sh "$PACKAGES" || true && rm /ha_autoapps.sh +RUN chmod 744 /ha_autoapps.sh && /ha_autoapps.sh "$PACKAGES" && rm /ha_autoapps.sh + +# Collabora Online payload, taken from the official image. COPY --from keeps the +# numeric ownership, so /opt/cool and /etc/coolwsd arrive already owned by 1001. +COPY --from=collabora /usr/bin/coolwsd /usr/bin/coolforkit-caps /usr/bin/coolforkit-ns /usr/bin/coolmount /usr/bin/ +COPY --from=collabora /usr/share/coolwsd /usr/share/coolwsd +COPY --from=collabora /etc/coolwsd /etc/coolwsd +COPY --from=collabora /opt/collaboraoffice /opt/collaboraoffice +COPY --from=collabora /opt/cool /opt/cool + +# Recreate the runtime user the official image declares (uid/gid 1001), and the +# per-container state upstream sets up in its own final build stage. +RUN \ + groupadd --gid 1001 cool && \ + useradd --uid 1001 --gid 1001 --no-create-home --home-dir /opt/cool --shell /usr/sbin/nologin cool && \ + mkdir -p /opt/cool/child-roots /opt/cool/cache && \ + chown -R 1001:1001 /opt/cool /etc/coolwsd && \ + chmod 640 /etc/coolwsd/coolwsd.xml && \ + touch /var/log/coolwsd.log && \ + chown 1001:1001 /var/log/coolwsd.log && \ + # the WOPI proof key must be unique per container, not baked into the image + rm -rf /etc/coolwsd/proof_key* && \ + (fc-cache /opt/collaboraoffice/share/fonts/truetype > /dev/null 2>&1 || true) + +# Restore the file capabilities. The official image carries them as extended +# attributes on two binaries: +# coolforkit-caps cap_chown,cap_fowner,cap_sys_chroot=ep +# coolmount cap_sys_admin=ep +# COPY --from does not transfer extended attributes, so both arrive stripped. +# Nothing about the build notices: coolwsd starts and serves the admin console, +# but every document fails to open because it cannot chroot a kit process. Set +# them again and check they stuck, so a builder without xattr support fails here +# instead of shipping an add-on that only looks like it works. +# +# cap_sys_admin on coolmount only takes effect if the container is given +# SYS_ADMIN, which the add-on does not request; without it Collabora copies its +# child roots instead of bind-mounting them, which is slower but works. +RUN \ + setcap "cap_chown,cap_fowner,cap_sys_chroot=ep" /usr/bin/coolforkit-caps && \ + setcap "cap_sys_admin=ep" /usr/bin/coolmount && \ + caps="$(getcap /usr/bin/coolforkit-caps /usr/bin/coolmount)" && \ + case "$caps" in \ + *cap_sys_chroot*) ;; \ + *) echo "coolforkit-caps lost its capabilities: ${caps}"; exit 1 ;; \ + esac && \ + case "$caps" in \ + *cap_sys_admin*) ;; \ + *) echo "coolmount lost its capabilities: ${caps}"; exit 1 ;; \ + esac + +# Fail the build rather than ship an image with unresolved runtime dependencies. +# The payload was linked against the libraries of the distroless image, so each +# executable and shared library is checked against the Debian runtime. +# +# coolwsd itself cannot be executed as a smoke test. It refuses to run as root +# ("Do not run as root. Please run as cool user.", exit 78), and --version does +# not exit either -- the official entrypoint passes it to the long-running +# server to get the version into the log. Checking that every binary resolves +# its libraries proves the same thing and terminates. +RUN \ + command -v openssl > /dev/null && \ + command -v su > /dev/null && \ + for binary in \ + /usr/bin/coolwsd \ + /usr/bin/coolforkit-caps \ + /usr/bin/coolforkit-ns \ + /usr/bin/coolmount \ + /opt/collaboraoffice/program/soffice.bin \ + /opt/collaboraoffice/program/libmergedlo.so; do \ + libs="$(ldd "$binary" 2>&1)"; \ + case "$libs" in \ + *"not found"*) echo "Unresolved libraries in ${binary}:"; echo "$libs"; exit 1 ;; \ + esac; \ + done ################ # 4 Entrypoint # diff --git a/collabora/README.md b/collabora/README.md index 51c96cf83f..c6f04f87eb 100644 --- a/collabora/README.md +++ b/collabora/README.md @@ -52,22 +52,63 @@ Webui can be found at `https://homeassistant:9980/browser/dist/admin/admin.html` | Option | Type | Default | Description | |--------|------|---------|-------------| -| `aliasgroup1` | str | | Nextcloud external domain with escaped dots using two \ (e.g. `nextcloud_domain\\.com`) | -| `domain1` | str | | Collabora external domain with escaped dots using two \ (e.g. `code_domain\\.com`) | +| `aliasgroup1` | str | | External address of the **Nextcloud** server allowed to use this Collabora (e.g. `https://nextcloud_domain\.com:443`) | +| `aliasgroup2` | str | | A second Nextcloud server, same format as `aliasgroup1` | +| `aliasgroup3` | str | | A third Nextcloud server, same format as `aliasgroup1` | +| `server_name` | str | | External hostname (and port) of **this Collabora** server, as the browser reaches it (e.g. `code_domain.com:9980`). Set it when Collabora sits behind a reverse proxy | +| `ssl_termination` | bool | `false` | Set to `true` when `ssl` is `false` but the browser reaches Collabora over `https` through a reverse proxy | | `extra_params` | str | | Extra parameters passed to the Collabora start script | | `ssl` | bool | `false` | Enable SSL using certificates from /ssl | | `certfile` | str | `fullchain.pem` | Certificate file name located in /ssl | | `keyfile` | str | `privkey.pem` | Private key file name located in /ssl | +| `cert_domain` | str | | Common name of the self-signed certificate generated when `ssl` is `false` | | `username` | str | | Username for the Collabora admin console | | `password` | str | | Password for the Collabora admin console | | `dictionaries` | str | | Space-separated list of dictionary languages to install | +| `domain1` | str | | **Deprecated**, use `server_name` instead | + +#### About the escaped dots in `aliasgroup*` + +Collabora matches the `aliasgroup*` addresses as **regular expressions**, so a dot +has to be escaped with a **single** backslash: `next\.duckdns\.org`, not +`next\\.duckdns\\.org`. A doubled backslash means "a literal backslash followed by +any character", which never matches a real hostname, and Collabora then rejects the +Nextcloud server. + +Earlier versions of this page asked for two backslashes, which was wrong. The add-on +now normalises whatever you type, so `next.duckdns.org`, `next\.duckdns\.org` and +`next\\.duckdns\\.org` all end up as the same correct pattern. The value that is +really handed to Collabora is printed in the add-on log at startup: + +```text +Allowed Nextcloud host aliasgroup1: https://next\.duckdns\.org:443 +``` + +Values containing other regex characters (`*`, `|`, `(`, `[`, …) are left untouched, +so hand-written patterns keep working. + +`server_name` is **not** a regular expression: write it as a plain hostname, without +backslashes. ### Example configuration +Nextcloud on `https://next.duckdns.org` and Collabora reachable on +`https://code.duckdns.org:9980`, with a reverse proxy handling the certificates: + ```yaml -aliasgroup1: nextcloud_domain\\.com -domain1: code_domain\\.com -extra_params: "" +aliasgroup1: https://next\.duckdns\.org:443 +server_name: code.duckdns.org:9980 +ssl_termination: true +ssl: false +username: admin +password: changeme +``` + +Same setup, but letting the add-on serve the certificates itself from `/ssl`: + +```yaml +aliasgroup1: https://next\.duckdns\.org:443 +server_name: code.duckdns.org:9980 ssl: true certfile: fullchain.pem keyfile: privkey.pem @@ -81,7 +122,19 @@ password: changeme 1. Start the add-on and expose the Collabora server to an external domain. 1. Install and configure the Nextcloud add-on. 1. Inside Nextcloud, install the **Nextcloud Office** app. -1. In Nextcloud **Administration Settings → Office**, set the Collabora server URL to `https://yourdomain:9980` and enable **Disable certificate validation**. +1. In Nextcloud **Administration Settings → Office**, set the Collabora server URL to + the **Collabora** address, not the Nextcloud one — with the example above that is + `https://code.duckdns.org:9980` — and enable **Disable certificate validation** if + the add-on serves a self-signed certificate. +1. Add both hostnames to the Nextcloud `trusted_domains`. + +The two hostnames have different roles, and swapping them is the most common cause of +`Could not establish connection to the Collabora Online server`: + +- `aliasgroup1` is the **Nextcloud** address, it tells Collabora which server is + allowed to ask it to open documents. +- `server_name` is the **Collabora** address, it tells Collabora which URL to hand + back to the browser. ### Custom Scripts and Environment Variables diff --git a/collabora/config.yaml b/collabora/config.yaml index a152277ecb..22ac07fc4d 100644 --- a/collabora/config.yaml +++ b/collabora/config.yaml @@ -15,7 +15,7 @@ options: env_vars: [] aliasgroup1: "" certfile: fullchain.pem - domain1: "" + server_name: "" extra_params: --o:ssl.enable=false --o:user_interface.use_integration_theme=false --o:net.proto=IPv4 @@ -33,7 +33,9 @@ schema: value: str? TZ: str? aliasgroup1: str - cert_domain: bool? + aliasgroup2: str? + aliasgroup3: str? + cert_domain: str? certfile: str dictionaries: str? domain1: str? @@ -42,8 +44,9 @@ schema: password: password server_name: str? ssl: bool + ssl_termination: bool? username: str slug: collabora url: https://github.com/alexbelgium/hassio-addons -version: "1.3.0" +version: "26.04.2.4.1" webui: "[PROTO:ssl]://[HOST]:[PORT:9980]/browser/dist/admin/admin.html" diff --git a/collabora/rootfs/etc/cont-init.d/99-run.sh b/collabora/rootfs/etc/cont-init.d/99-run.sh index c09ba1f182..95b0d33240 100755 --- a/collabora/rootfs/etc/cont-init.d/99-run.sh +++ b/collabora/rootfs/etc/cont-init.d/99-run.sh @@ -2,9 +2,58 @@ # shellcheck shell=bash set -e -if bashio::config.has_value 'domain'; then - domain="$(bashio::config 'domain')" - export domain +# coolwsd matches storage.wopi.alias_groups host/alias entries as regular +# expressions, so every dot has to be escaped with a single backslash. The value +# is typed by hand in the add-on options, where it is easy to end up with no +# escaping at all or with doubled backslashes, and a wrong pattern silently +# never matches: Collabora then refuses the Nextcloud host. Accept all three +# spellings and always hand coolwsd the canonical single-escaped form. +REGEX_METACHARACTERS='][(){}|*+?^$' +normalise_wopi_host() { + local value="$1" + + # A value containing regex metacharacters was written by someone who knows + # what they are doing, leave it exactly as-is. + if [[ "$value" == *["$REGEX_METACHARACTERS"]* ]]; then + printf '%s' "$value" + return + fi + + value="${value//\\/}" # drop whatever escaping was typed, at any depth + value="${value//./\\.}" # re-escape every dot exactly once + printf '%s' "$value" +} + +# server_name is a literal "hostname[:port]", not a regex and not a URL +normalise_server_name() { + local value="$1" + value="${value//\\/}" # never escaped, drop backslashes if any were copied over + value="${value#*://}" # strip the scheme + value="${value%%/*}" # strip any path + printf '%s' "$value" +} + +for index in 1 2 3; do + if bashio::config.has_value "aliasgroup${index}"; then + aliasgroup="$(normalise_wopi_host "$(bashio::config "aliasgroup${index}")")" + export "aliasgroup${index}=${aliasgroup}" + bashio::log.info "Allowed Nextcloud host aliasgroup${index}: ${aliasgroup}" + fi +done + +if bashio::config.has_value 'server_name'; then + server_name="$(normalise_server_name "$(bashio::config 'server_name')")" + export server_name +elif bashio::config.has_value 'domain1'; then + # domain1 predates server_name and was documented as "the Collabora external + # domain", which is what server_name means to coolwsd. It was never actually + # passed to Collabora, so honour it here rather than keep ignoring it. + server_name="$(normalise_server_name "$(bashio::config 'domain1')")" + export server_name + bashio::log.warning "domain1 is deprecated, please use server_name instead" +fi +if [ -n "${server_name:-}" ]; then + bashio::log.info "Collabora public hostname (server_name): ${server_name}" fi if bashio::config.has_value 'username'; then @@ -17,9 +66,9 @@ if bashio::config.has_value 'password'; then export password fi -if bashio::config.has_value 'aliasgroup1'; then - aliasgroup1="$(bashio::config 'aliasgroup1')" - export aliasgroup1 +if bashio::config.has_value 'cert_domain'; then + cert_domain="$(bashio::config 'cert_domain')" + export cert_domain fi if bashio::config.has_value 'dictionaries'; then @@ -32,6 +81,12 @@ if bashio::config.has_value 'extra_params'; then extra_params="$(bashio::config 'extra_params')" fi +# The add-on ssl option is authoritative. coolwsd defaults ssl.enable to true, +# so merely clearing extra_params used to re-enable its self-signed HTTPS even +# when ssl was false, which breaks reverse proxies expecting plain HTTP. +extra_params="${extra_params//--o:ssl.enable=false/}" +extra_params="${extra_params//--o:ssl.enable=true/}" + if bashio::config.true 'ssl'; then export DONT_GEN_SSL_CERT=true bashio::config.require.ssl @@ -45,16 +100,31 @@ if bashio::config.true 'ssl'; then bashio::log.error "Key file /ssl/${keyfile} not found" exit 1 fi - cp -f /ssl/${keyfile} /etc/coolwsd/key.pem - cp -f /ssl/${certfile} /etc/coolwsd/cert.pem - cp -f /ssl/${certfile} /etc/coolwsd/ca-chain.cert.pem - extra_params="${extra_params/--o:ssl.enable=false/}" + # Point Collabora at the copies rather than at /ssl. coolwsd runs as uid + # 1001 and /ssl is mounted read-only with whatever ownership the certificate + # tooling left behind, which for a private key is commonly root-only. These + # copies are picked up by the chown below, so they are readable regardless. + cp -f "/ssl/${keyfile}" /etc/coolwsd/key.pem + cp -f "/ssl/${certfile}" /etc/coolwsd/cert.pem + cp -f "/ssl/${certfile}" /etc/coolwsd/ca-chain.cert.pem + chmod 600 /etc/coolwsd/key.pem extra_params="${extra_params} \ - --o:ssl.enable=true + --o:ssl.enable=true \ --o:ssl.termination=false \ - --o:ssl.cert_file_path=/ssl/${certfile} \ - --o:ssl.key_file_path=/ssl/${keyfile} \ - --o:ssl.ca_file_path=/ssl/${certfile}" + --o:ssl.cert_file_path=/etc/coolwsd/cert.pem \ + --o:ssl.key_file_path=/etc/coolwsd/key.pem \ + --o:ssl.ca_file_path=/etc/coolwsd/ca-chain.cert.pem" +else + extra_params="${extra_params} --o:ssl.enable=false" + if [[ "$extra_params" != *ssl.termination* ]]; then + # With SSL disabled, termination must be enabled when a reverse proxy + # exposes Collabora over https, otherwise it advertises http/ws URLs. + if bashio::config.true 'ssl_termination'; then + extra_params="${extra_params} --o:ssl.termination=true" + elif ! bashio::config.has_value 'ssl_termination'; then + bashio::log.notice "If Collabora is reached over https through a reverse proxy, set ssl_termination to true" + fi + fi fi export extra_params @@ -83,4 +153,9 @@ chown -R 1001 /etc/coolwsd chmod -R 755 /opt/cool/systemplate bashio::log.info "Starting Collabora Online..." -su -p -s /bin/bash "$(getent passwd 1001 | cut -d: -f1)" -c "/start-collabora-online.sh" +# coolwsd refuses to run as root. The official image used to ship +# /start-collabora-online.sh, which is gone since it became distroless, so the +# add-on provides its own launcher. It reads everything from the environment, +# which su -p preserves. +export HOME=/opt/cool +su -p -s /bin/bash cool -c /usr/local/bin/collabora-run.sh diff --git a/collabora/rootfs/usr/local/bin/collabora-run.sh b/collabora/rootfs/usr/local/bin/collabora-run.sh new file mode 100644 index 0000000000..a3264ebe11 --- /dev/null +++ b/collabora/rootfs/usr/local/bin/collabora-run.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# shellcheck shell=bash +# +# Launch coolwsd. +# +# The official image used to ship /start-collabora-online.sh and set it as its +# entrypoint. Since the move to a distroless image that script is gone, so the +# add-on provides its own equivalent. It is invoked as uid 1001 by +# /etc/cont-init.d/99-run.sh and takes everything from the environment, which +# avoids re-quoting extra_params through su. +set -e + +# Collabora serves https itself unless the add-on already installed real +# certificates, in which case 99-run.sh exports DONT_GEN_SSL_CERT. +cert_params="" +if [ -z "${DONT_GEN_SSL_CERT:-}" ]; then + SSL_DIR="/tmp/ssl" + mkdir -p "${SSL_DIR}/certs/ca" "${SSL_DIR}/certs/servers/localhost" "${SSL_DIR}/certs/tmp" + + openssl genrsa -out "${SSL_DIR}/certs/ca/root.key.pem" 2048 + openssl req -x509 -new -nodes \ + -key "${SSL_DIR}/certs/ca/root.key.pem" -days 9131 \ + -out "${SSL_DIR}/certs/ca/root.crt.pem" \ + -subj "/C=DE/ST=BW/L=Stuttgart/O=Dummy Authority/CN=Dummy Authority" + + openssl genrsa -out "${SSL_DIR}/certs/servers/localhost/privkey.pem" 2048 + openssl req -new -sha256 \ + -key "${SSL_DIR}/certs/servers/localhost/privkey.pem" \ + -out "${SSL_DIR}/certs/tmp/localhost.csr.pem" \ + -subj "/C=DE/ST=BW/L=Stuttgart/O=Dummy Authority/CN=${cert_domain:-localhost}" + openssl x509 -req -days 9131 \ + -in "${SSL_DIR}/certs/tmp/localhost.csr.pem" \ + -CA "${SSL_DIR}/certs/ca/root.crt.pem" \ + -CAkey "${SSL_DIR}/certs/ca/root.key.pem" -CAcreateserial \ + -out "${SSL_DIR}/certs/servers/localhost/cert.pem" + + cert_params="--o:ssl.cert_file_path=${SSL_DIR}/certs/servers/localhost/cert.pem \ + --o:ssl.key_file_path=${SSL_DIR}/certs/servers/localhost/privkey.pem \ + --o:ssl.ca_file_path=${SSL_DIR}/certs/ca/root.crt.pem" +fi + +# Flags mirror the entrypoint of the official image. extra_params is expanded +# last so that add-on options and user overrides win. +# shellcheck disable=SC2086 +exec /usr/bin/coolwsd \ + --version \ + --use-env-vars \ + ${cert_params} \ + --o:sys_template_path=/opt/cool/systemplate \ + --o:child_root_path=/opt/cool/child-roots \ + --o:file_server_root_path=/usr/share/coolwsd \ + --o:cache_files.path=/opt/cool/cache \ + --o:logging.color=false \ + --o:stop_on_config_change=true \ + ${extra_params:-} diff --git a/collabora/updater.json b/collabora/updater.json index 35f757568b..c8f8b13ede 100644 --- a/collabora/updater.json +++ b/collabora/updater.json @@ -1,8 +1,9 @@ { - "last_update": "2026-07-16", + "github_exclude": "sha256", + "last_update": "2026-07-26", "repository": "alexbelgium/hassio-addons", "slug": "collabora", - "source": "github", - "upstream_repo": "CollaboraOnline/online", - "upstream_version": "1.3.0" + "source": "dockerhub", + "upstream_repo": "collabora/code", + "upstream_version": "26.04.2.4.1" }