Compare commits

..

8 Commits

Author SHA1 Message Date
renovate[bot] b0828528df chore(deps): update dependency ntfy to v2.17.0-0 2026-02-10 11:53:33 +02:00
Suguru Hirahara 96029bf916 Replace "EchoIP" with "echoip"
cf. https://github.com/mpolden/echoip

Signed-off-by: Suguru Hirahara <did:key:z6MkvVZk1A3KBApWJXv2Ju4H14ErDfRGxh8zxdXSZ4vACDg5>
2026-02-10 17:41:52 +09:00
Slavi Pantaleev ace086056f Upgrade Postgres (v18.1-4 -> v18.1-5) 2026-02-09 21:24:48 +02:00
Slavi Pantaleev 0e8ef8ef10 Add retry logic for Synapse user registration on Connection refused
When DB credentials change (derived from matrix_synapse_macaroon_secret_key),
a running Synapse container may fail to connect to its database and stop
serving requests. This causes register_new_matrix_user to fail with
"Connection refused" when the matrix-user-creator role tries to register users.

This extends the retry logic from 44b43a51b (which handled HMAC failures)
to also handle Connection refused errors: restart Synapse (picking up the
new config with updated credentials), wait for it to start, and retry.

Caused by c21a80d232

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 17:36:59 +02:00
Slavi Pantaleev 2c2738a48f Remove passlib dependency by making matrix-media-repo datastore IDs user-provided
These IDs were incorrectly auto-derived from matrix_homeserver_generic_secret_key,
which is meant for secrets that are OK to change. Datastore IDs are static
identifiers that must never change after first use.

The playbook now requires users to explicitly set matrix_media_repo_datastore_file_id
(and matrix_media_repo_datastore_s3_id when S3 is enabled) in vars.yml, with
validation that fails early if they are missing.

This was the last usage of passlib, which is now removed from prerequisites.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 16:56:51 +02:00
Suguru Hirahara 09914bf338 Set ddclient_uid and ddclient_gid
Signed-off-by: Suguru Hirahara <did:key:z6MkvVZk1A3KBApWJXv2Ju4H14ErDfRGxh8zxdXSZ4vACDg5>
2026-02-09 19:49:59 +09:00
Slavi Pantaleev 44b43a51b9 Add retry logic for Synapse user registration on HMAC failure
When the registration_shared_secret changes (derived from
matrix_synapse_macaroon_secret_key), a running Synapse container still
has the old secret in its config. This causes register_new_matrix_user
to fail with "HMAC incorrect" when the matrix-user-creator role tries
to register users.

This mirrors the approach from 2a581cce (which added similar retry
logic for the Matrix Authentication Service on database auth failure):
if the initial registration attempt fails with an HMAC error, restart
Synapse (picking up the new config with the updated secret), wait for
it to start, and retry.

Caused by c21a80d232

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 06:29:14 +02:00
Aine 5f8235f44a remove Zulip bridge 2026-02-08 20:34:56 +02:00
9 changed files with 92 additions and 14 deletions
+27
View File
@@ -1,3 +1,30 @@
# 2026-02-09
## (BC Break) matrix-media-repo datastore IDs are now required in `vars.yml`
**Affects**: users with [matrix-media-repo](docs/configuring-playbook-matrix-media-repo.md) enabled (`matrix_media_repo_enabled: true`)
The `matrix_media_repo_datastore_file_id` and `matrix_media_repo_datastore_s3_id` variables are no longer auto-configured with values. They must now be explicitly defined in your `vars.yml` file. The playbook will fail with a helpful error if they are not set (when needed).
These were never meant to be auto-configured. They were derived from `matrix_homeserver_generic_secret_key`, which is intended for secrets that are OK to change subsequently (and Ansible would assist in propagating these changes). matrix-media-repo datastore IDs are not secrets — they are static identifiers linking media to storage backends, and **must not change** after first use.
**For existing installations**, retrieve your current values from the server:
```sh
grep 'id:' /matrix/media-repo/config/media-repo.yaml
```
Then add to your `vars.yml`:
```yaml
matrix_media_repo_datastore_file_id: "YOUR_FILE_DATASTORE_ID_HERE"
# Only if you use S3 storage:
# matrix_media_repo_datastore_s3_id: "YOUR_S3_DATASTORE_ID_HERE"
```
**Why do this?**: This change allows us to **remove the [passlib](https://passlib.readthedocs.io/en/stable/index.html) Python library** from the [prerequisites](docs/prerequisites.md), as it was the last component that depended on it.
# 2026-02-08
## Zulip bridge has been removed from the playbook
@@ -24,8 +24,21 @@ To enable matrix-media-repo, add the following configuration to your `inventory/
```yaml
matrix_media_repo_enabled: true
# Any unique alphanumeric string. Cannot be changed after first use.
# For new installations, generate one with: pwgen -s 64 1
# For existing installations, see below.
matrix_media_repo_datastore_file_id: "CHANGE_ME_TO_A_UNIQUE_VALUE"
```
**For existing installations**: retrieve the current datastore ID from the server's config file before proceeding:
```sh
grep 'id:' /matrix/media-repo/config/media-repo.yaml
```
Then use that value for `matrix_media_repo_datastore_file_id`. This is not a secret — it is a plain identifier used by matrix-media-repo to link media files to their storage backend.
By default, the media-repo will use the local filesystem for data storage. You can alternatively use a `s3` cloud backend as well. Access token caching is also enabled by default since the logout endpoints are proxied through the media repo.
### Enable metrics
@@ -109,6 +122,11 @@ matrix_media_repo_admins: []
matrix_media_repo_datastore_file_for_kinds: ["thumbnails", "remote_media", "local_media", "archives"]
matrix_media_repo_datastore_s3_for_kinds: []
# Required when S3 storage is enabled (matrix_media_repo_datastore_s3_for_kinds is non-empty).
# Any unique alphanumeric string. Cannot be changed after first use.
# For new installations, generate one with: pwgen -s 64 1
# matrix_media_repo_datastore_s3_id: ""
# The s3 uploader needs a temporary location to buffer files to reduce memory usage on
# small file uploads. If the file size is unknown, the file is written to this location
# before being uploaded to s3 (then the file is deleted). If you aren't concerned about
+1 -1
View File
@@ -26,7 +26,7 @@ If you'd rather use a local IP for `ansible_host`, add the following configurati
matrix_coturn_turn_external_ip_address: "YOUR_PUBLIC_IP"
```
If you'd like to rely on external IP address auto-detection (not recommended unless you need it), set an empty value to the variable. The playbook will automatically contact an [EchoIP](https://github.com/mpolden/echoip)-compatible service (`https://ifconfig.co/json` by default) to determine your server's IP address. This API endpoint is configurable via the `matrix_coturn_turn_external_ip_address_auto_detection_echoip_service_url` variable.
If you'd like to rely on external IP address auto-detection (not recommended unless you need it), set an empty value to the variable. The playbook will automatically contact an [echoip](https://github.com/mpolden/echoip)-compatible service (`https://ifconfig.co/json` by default) to determine your server's IP address. This API endpoint is configurable via the `matrix_coturn_turn_external_ip_address_auto_detection_echoip_service_url` variable.
If your server has multiple external IP addresses, the coturn role offers a different variable for specifying them:
-2
View File
@@ -23,8 +23,6 @@ We will be using `example.com` as the domain in the following instruction. Pleas
- [Ansible](http://ansible.com/) program. It's used to run this playbook and configures your server for you. Take a look at [our guide about Ansible](ansible.md) for more information, as well as [version requirements](ansible.md#supported-ansible-versions) and alternative ways to run Ansible.
- [passlib](https://passlib.readthedocs.io/en/stable/index.html) Python library. See [this official documentation](https://passlib.readthedocs.io/en/stable/install.html#installation-instructions) for an instruction to install it. On most distros, you need to install some `python-passlib` or `py3-passlib` package, etc.
- [`git`](https://git-scm.com/) as the recommended way to download the playbook. `git` may also be required on the server if you will be [self-building](self-building.md) components.
- [`just`](https://github.com/casey/just) for running `just roles`, `just update`, etc. (see [`justfile`](../justfile)), although you can also run these commands manually. Take a look at this documentation for more information: [Running `just` commands](just.md).
+4 -1
View File
@@ -3105,7 +3105,7 @@ matrix_coturn_container_image_self_build: "{{ matrix_architecture not in ['amd64
# We make the assumption that `ansible_host` points to an external IP address, which may not always be the case.
# Users are free to set `matrix_coturn_turn_external_ip_address` to an empty string
# to allow auto-detection (via an EchoIP service) to happen at runtime.
# to allow auto-detection (via an echoip service) to happen at runtime.
matrix_coturn_turn_external_ip_address: "{{ ansible_host }}"
matrix_coturn_turn_static_auth_secret: "{{ ((matrix_homeserver_generic_secret_key + ':coturn.sas') | hash('sha512') | to_uuid) if matrix_coturn_authentication_method == 'auth-secret' else '' }}"
@@ -3299,6 +3299,9 @@ ddclient_identifier: matrix-dynamic-dns
ddclient_base_path: "{{ matrix_base_data_path }}/dynamic-dns"
ddclient_uid: "{{ matrix_user_uid }}"
ddclient_gid: "{{ matrix_user_gid }}"
ddclient_container_image_registry_prefix: "{{ 'localhost/' if ddclient_container_image_self_build else ddclient_container_image_registry_prefix_upstream }}"
ddclient_container_image_registry_prefix_upstream: "{{ matrix_container_global_registry_prefix_override if matrix_container_global_registry_prefix_override else ddclient_docker_image_registry_prefix_upstream_default }}"
+2 -2
View File
@@ -38,7 +38,7 @@
version: v1.9.11-0
name: livekit_server
- src: git+https://github.com/mother-of-all-self-hosting/ansible-role-ntfy.git
version: v2.16.0-1
version: v2.17.0-0
name: ntfy
- src: git+https://github.com/devture/com.devture.ansible.role.playbook_help.git
version: 8630e4f1749bcb659c412820f754473f09055052
@@ -50,7 +50,7 @@
version: dd6e15246b7a9a2d921e0b3f9cd8a4a917a1bb2f
name: playbook_state_preserver
- src: git+https://github.com/mother-of-all-self-hosting/ansible-role-postgres.git
version: v18.1-4
version: v18.1-5
name: postgres
- src: git+https://github.com/mother-of-all-self-hosting/ansible-role-postgres-backup.git
version: v18-0
@@ -414,8 +414,9 @@ matrix_media_repo_shared_secret_auth_token: "PutSomeRandomSecureValueHere"
# thumbnails and other misc data is also stored in these places. The media repo, when looking
# for a datastore to use, will always use the smallest datastore first.
# ID for the file datastore (cannot change). Alphanumeric recommended.
matrix_media_repo_datastore_file_id: "{{ '%s' | format(matrix_homeserver_generic_secret_key) | password_hash('sha512', 'filestore.db', rounds=655555) | to_uuid }}"
# ID for the file datastore. Any unique alphanumeric string (e.g. generated via `pwgen -s 64 1`).
# This value CANNOT be changed after media has been stored — matrix-media-repo ties media to this ID.
matrix_media_repo_datastore_file_id: ""
# Datastores can be split into many areas when handling uploads. Media is still de-duplicated
# across all datastores (local content which duplicates remote content will re-use the remote
@@ -434,8 +435,9 @@ matrix_media_repo_datastore_file_for_kinds: ["thumbnails", "remote_media", "loca
# Path to datastore, relative to matrix-media-repo directory root
matrix_media_repo_datastore_opts_path: "/data/media"
# ID for the s3 datastore (cannot change). Alphanumeric recommended.
matrix_media_repo_datastore_s3_id: "{{ '%s' | format(matrix_homeserver_generic_secret_key) | password_hash('sha512', 's3store.db', rounds=655555) | to_uuid }}"
# ID for the S3 datastore. Any unique alphanumeric string (e.g. generated via `pwgen -s 64 1`).
# This value CANNOT be changed after media has been stored — matrix-media-repo ties media to this ID.
matrix_media_repo_datastore_s3_id: ""
# Datastores can be split into many areas when handling uploads. Media is still de-duplicated
# across all datastores (local content which duplicates remote content will re-use the remote
@@ -15,6 +15,8 @@
- {'name': 'matrix_media_repo_database_hostname', when: true}
- {'name': 'matrix_media_repo_container_labels_traefik_internal_media_entrypoints', when: "{{ matrix_media_repo_container_labels_traefik_internal_media_enabled }}"}
- {'name': 'matrix_media_repo_container_labels_traefik_internal_matrix_client_media_entrypoints', when: "{{ matrix_media_repo_container_labels_traefik_internal_matrix_client_media_enabled }}"}
- {'name': 'matrix_media_repo_datastore_file_id', when: "{{ (matrix_media_repo_datastore_file_for_kinds | length) > 0 }}"}
- {'name': 'matrix_media_repo_datastore_s3_id', when: "{{ (matrix_media_repo_datastore_s3_for_kinds | length) > 0 }}"}
- name: (Deprecation) Catch and report renamed matrix-media-repo settings
ansible.builtin.fail:
@@ -4,9 +4,9 @@
---
- name: Ensure Synapse user registered - {{ user.username | quote }}
ansible.builtin.command:
cmd: |-
- name: Build Synapse user registration command - {{ user.username | quote }}
ansible.builtin.set_fact:
matrix_synapse_register_user_command: |-
{{ devture_systemd_docker_base_host_command_docker }} exec matrix-synapse
register_new_matrix_user
-u {{ user.username | quote }}
@@ -21,6 +21,34 @@
{% endif %}
{% endif %}
http://localhost:{{ matrix_synapse_container_client_api_port }}
- name: Ensure Synapse user registered - {{ user.username | quote }}
ansible.builtin.command:
cmd: "{{ matrix_synapse_register_user_command }}"
register: matrix_synapse_register_user_result
changed_when: matrix_synapse_register_user_result.rc == 0 and 'User ID already taken' not in matrix_synapse_register_user_result.stdout
failed_when: matrix_synapse_register_user_result.rc != 0 and 'User ID already taken' not in matrix_synapse_register_user_result.stdout
failed_when: >-
matrix_synapse_register_user_result.rc != 0
and 'User ID already taken' not in matrix_synapse_register_user_result.stdout
and 'HMAC incorrect' not in matrix_synapse_register_user_result.stdout
and 'Connection refused' not in matrix_synapse_register_user_result.stderr | default('')
- when: >-
'HMAC incorrect' in matrix_synapse_register_user_result.stdout | default('')
or 'Connection refused' in matrix_synapse_register_user_result.stderr | default('')
block:
- name: Restart Synapse due to registration failure (likely a registration_shared_secret or DB credentials change)
ansible.builtin.service:
name: "matrix-synapse.service"
state: restarted
- name: Wait for Synapse to start after restart
ansible.builtin.pause:
seconds: "{{ matrix_user_creator_homeserver_start_wait_time_seconds }}"
- name: Retry Synapse user registration - {{ user.username | quote }}
ansible.builtin.command:
cmd: "{{ matrix_synapse_register_user_command }}"
register: matrix_synapse_register_user_result
changed_when: matrix_synapse_register_user_result.rc == 0 and 'User ID already taken' not in matrix_synapse_register_user_result.stdout
failed_when: matrix_synapse_register_user_result.rc != 0 and 'User ID already taken' not in matrix_synapse_register_user_result.stdout