Compare commits

...

13 Commits

Author SHA1 Message Date
github-actions
37f73b124b GitHub bot: sanitize (spaces + LF endings) & chmod [nobuild] 2026-07-26 19:58:42 +00:00
Alexandre
497691007b Merge pull request #2905 from alexbelgium/fix/collabora-domain-options
fix(collabora): fix domain/aliasgroup options, rebuild on Debian base (upstream went distroless)
2026-07-26 21:57:50 +02:00
Alexandre
f79ae66d73 docs(collabora): document authoritative ssl handling 2026-07-26 19:48:57 +02:00
Alexandre
ff4df36fba fix(collabora): enforce the ssl option independently of extra_params 2026-07-26 19:47:15 +02:00
Alexandre
ae2c19074a fix(collabora): stop masking required setup failures 2026-07-26 19:41:22 +02:00
Claude
c10801ae75 fix(collabora): pin BUILD_FROM per arch and restore the payload capabilities
build.json named the multi-arch collabora/code:latest for both architectures.
The builder never passes --platform -- it runs each architecture on its own
native runner -- so BUILD_FROM is the only thing selecting which binaries end
up in the add-on. That resolves correctly today only because the runner
architecture happens to match the target. Name collabora/code:latest-amd64 and
collabora/code:latest-arm64, which are published in lockstep with latest.

The official image sets file capabilities on two binaries, and COPY --from does
not carry extended attributes, so they arrived stripped:

  coolforkit-caps  cap_chown,cap_fowner,cap_sys_chroot=ep
  coolmount        cap_sys_admin=ep

Without them coolwsd starts and serves the admin console, but cannot chroot a
kit process, so no document ever opens. Reapply and verify them.

Replace the smoke test, which is why the build is currently red: coolwsd
refuses to run as root (exit 78), and --version does not exit anyway, since the
official entrypoint passes it to the long-running server. Check instead that
every binary resolves its libraries against the Debian base.

For ssl: true, hand Collabora the certificate copies in /etc/coolwsd rather
than /ssl. coolwsd runs as uid 1001 and a private key in /ssl is commonly
root-only, so it could not be read; the copies were already being made and
chowned, but nothing pointed at them.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-26 19:34:30 +02:00
alexbelgium
c203703ead fix(collabora): declare SHELL with pipefail explicitly
The base image already sets it, but hadolint cannot see an inherited SHELL
(DL4006), and the ldd linkage check relies on pipefail to notice a failing ldd.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-26 19:26:22 +02:00
alexbelgium
eef927d485 fix(collabora): check linkage with ldd instead of booting coolwsd
"coolwsd --version" does not short-circuit: it runs a full initialisation and
tries to create a jail, which fails in a build layer because the --o: paths the
launcher passes are absent, so it looked for /usr/bin/jails. It did prove the
binaries link against the Debian base, but booting Collabora is the wrong check
for a build step.

ldd asserts the same thing directly: every NEEDED library of coolwsd,
coolforkit-ns and coolmount resolves on this base. The loop uses an if rather
than "grep && exit 1" so that a clean result does not leave the loop with
grep's non-zero status and fail the good case.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-26 19:26:01 +02:00
alexbelgium
0e431c8281 fix(collabora): run the build smoke test as the cool user
coolwsd refuses to start as root, so "coolwsd --version" failed the build even
though it proved what it was there to prove: the payload copied out of the
distroless image links and executes on the Debian base. Run it through su as
uid 1001, which is also exactly how 99-run.sh launches it.

Also drop --system from the useradd/groupadd, which only produced a
"uid 1001 is greater than SYS_UID_MAX 999" warning.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-26 18:54:27 +02:00
alexbelgium
10d32afa69 fix(collabora): keep collabora/code:latest as BUILD_FROM in build.json
build.json is where every add-on in this repo records the upstream image it
tracks, and it is what the updater bot rewrites. Hardcoding the Collabora tag in
the Dockerfile and putting the Debian base in build.json inverted that.

BUILD_FROM is now collabora/code:latest again and feeds the build stage the
payload is copied from; the Debian runtime base is named in the Dockerfile,
where it is an implementation detail of the add-on rather than the upstream
being tracked.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-26 18:30:45 +02:00
alexbelgium
789f8813d3 fix(collabora): rebuild on a Debian base, upstream image is now distroless
Upstream rebuilt collabora/code as a Nix distroless image between 26.04.2.1.1
(2026-07-01) and 26.04.2.2.1 (2026-07-18): /bin and /sbin are empty and the
entrypoint is coolwsd itself. It can no longer serve as BUILD_FROM, since every
RUN, s6-overlay and bashio need a shell. The addon build has been failing since,
which is independent of the option fixes in this branch.

Collabora is now taken from the official image as a build stage and copied onto
ghcr.io/hassio-addons/debian-base:

- Only the payload is copied: /usr/bin/cool*, /usr/share/coolwsd, /etc/coolwsd,
  /opt/collaboraoffice and /opt/cool. /etc and /nix are deliberately left out:
  in the distroless image /etc/resolv.conf, /etc/hosts, /etc/passwd, /etc/group
  and /etc/nsswitch.conf are symlinks into /nix/store, so importing them would
  break DNS and wipe the base image users.
- coolwsd links only against glibc, libstdc++, libgcc and libm, and needs at
  most GLIBCXX_3.4.22, so the Debian base satisfies it; the office engine
  bundles its own cairo, fontconfig, curl, icu and fonts. Only openssl,
  fontconfig, libcap2-bin, cpio, findutils and ca-certificates are installed.
- The uid/gid 1001 cool user is recreated, matching the official image.
- /start-collabora-online.sh is gone, so the addon ships an equivalent launcher
  which also regenerates the self-signed certificate when ssl is off.
- The build now runs "coolwsd --version" so a payload that cannot link fails the
  build instead of shipping an image that will not start.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-26 18:23:14 +02:00
alexbelgium
dd650156f3 fix(collabora): simplify server_name log condition
Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-26 17:28:12 +02:00
alexbelgium
6a27361cef fix(collabora): pass server_name to Collabora, fix aliasgroup escaping and version numbering
Reported in #2768: several users could not get Collabora to talk to
Nextcloud, and the two options meant to configure it had no effect.

- 99-run.sh read a `domain` option that does not exist in the schema (the
  option is `domain1`), and recent Collabora releases dropped the `domain`
  environment variable entirely, so `domain1` was inert. It now maps to
  `server_name` with a deprecation warning.
- `server_name` and `cert_domain` were in the schema but never passed to
  Collabora. `server_name` is what fixes "Your browser has been unable to
  connect to the Collabora server" behind a reverse proxy.
- `aliasgroup*` entries are matched by Collabora as regular expressions, so
  a dot needs a single backslash. The README asked for two, which can never
  match a real hostname. Values are now normalised (unescaped, escaped and
  double-escaped all give the same correct pattern) and logged at startup.
  Values containing other regex metacharacters are left untouched.
- Added `ssl_termination`, needed when `ssl` is false but Collabora is
  reached over https through a reverse proxy, and `aliasgroup2`/`aliasgroup3`.
- `cert_domain` is a certificate common name, so it is a string, not a bool.
- 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 from the
  Supervisor. Version tracking moves back to the collabora/code Docker Hub
  tags.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-26 17:26:24 +02:00
7 changed files with 348 additions and 31 deletions

View File

@@ -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)

View File

@@ -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 #

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View File

@@ -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:-}

View File

@@ -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"
}