Add Synology DSM support (#5315)

Adds optional support for running the playbook on Synology DSM 7+, detected
automatically via /etc/synoinfo.conf so that non-Synology hosts are unaffected.

Includes DSM-native user/group management (synouser/synogroup), a requests
version constraint for Docker SDK compatibility, and a boot-fix service that
re-shares the volume mount and starts matrix services skipped by DSM's boot
ordering. The shared-mount volume path is configurable via
matrix_base_synology_volume_path, and the make-shared step only runs when the
volume is not already shared.

Co-authored-by: CKSit <sitchiuki@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
cksit
2026-06-30 00:45:01 +08:00
committed by GitHub
parent 4f9346e182
commit ee1cd217a8
13 changed files with 490 additions and 23 deletions
@@ -0,0 +1,54 @@
#!/bin/sh
# SPDX-FileCopyrightText: 2026 Chiu Ki Sit
#
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Boot recovery for Matrix services on Synology DSM.
#
# This script runs after multi-user.target (outside Container Manager's dependency
# chain) and does two things:
#
# 1. Makes {{ matrix_base_synology_volume_path }} mount-shared so Docker bind-propagation=slave mounts work.
# Inserting this into the systemd chain Before=pkg-ContainerManager-dockerd.service
# causes Container Manager to detect a broken dependency and prompt for repair,
# so it must run here instead, after Docker is already up.
#
# 2. Starts any enabled matrix-*.service that systemd skipped at boot.
# Synology's systemd drops services with multi-level dependency chains
# (e.g. traefik -> socket-proxy -> docker) from the boot activation queue.
# Services that need bind-propagation=slave (e.g. matrix-synapse) are
# created after step 1, so the propagation is already in effect.
# Wait up to 120s for Docker to be ready
i=0
while [ "$i" -lt 60 ]; do
{{ devture_systemd_docker_base_host_command_docker }} info >/dev/null 2>&1 && break
i=$((i + 1))
sleep 2
done
if ! {{ devture_systemd_docker_base_host_command_docker }} info >/dev/null 2>&1; then
echo "matrix-synology-boot-fix: Docker not ready after 120s, aborting" >&2
exit 1
fi
# Make {{ matrix_base_synology_volume_path }} shared so Docker bind-propagation=slave mounts work correctly.
# Must run after Docker is up to avoid interfering with Container Manager's
# integrity checks, but before matrix-synapse (and any other service using
# bind-propagation=slave) creates its containers.
/bin/mount --make-shared {{ matrix_base_synology_volume_path }}
echo "matrix-synology-boot-fix: {{ matrix_base_synology_volume_path }} set to shared mount propagation"
# Start any enabled matrix-*.service that is inactive or failed.
# Both states indicate the service did not come up at boot — either skipped by
# Synology's boot ordering or failed due to Docker/mount-propagation not being
# ready yet (the conditions above now satisfy those prerequisites).
{{ devture_systemd_docker_base_host_command_systemctl }} list-unit-files 'matrix-*.service' --state=enabled --no-legend 2>/dev/null | \
while read -r unit _state; do
[ "$unit" = "matrix-synology-boot-fix.service" ] && continue
status="$({{ devture_systemd_docker_base_host_command_systemctl }} is-active "$unit" 2>/dev/null)"
if [ "$status" = "inactive" ] || [ "$status" = "failed" ]; then
echo "matrix-synology-boot-fix: starting $unit (was $status)"
{{ devture_systemd_docker_base_host_command_systemctl }} start "$unit"
fi
done
@@ -0,0 +1,16 @@
# SPDX-FileCopyrightText: 2026 Chiu Ki Sit
#
# SPDX-License-Identifier: AGPL-3.0-or-later
[Unit]
Description=Matrix Services Boot Recovery (Synology)
# Run after multi-user.target so all matrix services have been attempted first.
After=multi-user.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart={{ matrix_bin_path }}/matrix-synology-boot-fix
[Install]
WantedBy=multi-user.target