add Mautrix Linkedin bridge

This commit is contained in:
Aine
2026-07-26 17:10:11 +01:00
committed by Slavi Pantaleev
parent eeabc623d7
commit 254773bf3c
18 changed files with 1283 additions and 0 deletions
@@ -0,0 +1,25 @@
# SPDX-FileCopyrightText: 2026 MDAD project contributors
# SPDX-FileCopyrightText: 2026 Nikita Chernyi
#
# SPDX-License-Identifier: AGPL-3.0-or-later
---
- tags:
- setup-all
- setup-mautrix-linkedin
- install-all
- install-mautrix-linkedin
block:
- when: matrix_bridge_mautrix_linkedin_enabled | bool
ansible.builtin.include_tasks: "{{ role_path }}/tasks/validate_config.yml"
- when: matrix_bridge_mautrix_linkedin_enabled | bool
ansible.builtin.include_tasks: "{{ role_path }}/tasks/setup_install.yml"
- tags:
- setup-all
- setup-mautrix-linkedin
block:
- when: not matrix_bridge_mautrix_linkedin_enabled | bool
ansible.builtin.include_tasks: "{{ role_path }}/tasks/setup_uninstall.yml"
@@ -0,0 +1,176 @@
# SPDX-FileCopyrightText: 2026 MDAD project contributors
# SPDX-FileCopyrightText: 2026 Nikita Chernyi
#
# SPDX-License-Identifier: AGPL-3.0-or-later
---
- ansible.builtin.set_fact:
matrix_bridge_mautrix_linkedin_migration_requires_restart: false
- when: "matrix_bridge_mautrix_linkedin_database_engine == 'postgres'"
block:
- name: Check if an SQLite database already exists
ansible.builtin.stat:
path: "{{ matrix_bridge_mautrix_linkedin_sqlite_database_path_local }}"
register: matrix_bridge_mautrix_linkedin_sqlite_database_path_local_stat_result
- when: "matrix_bridge_mautrix_linkedin_sqlite_database_path_local_stat_result.stat.exists | bool"
block:
- ansible.builtin.include_role:
name: galaxy/postgres
tasks_from: migrate_db_to_postgres
vars:
postgres_db_migration_request:
src: "{{ matrix_bridge_mautrix_linkedin_sqlite_database_path_local }}"
dst: "{{ matrix_bridge_mautrix_linkedin_database_connection_string }}"
caller: "{{ role_path | basename }}"
engine_variable_name: 'matrix_bridge_mautrix_linkedin_database_engine'
engine_old: 'sqlite'
systemd_services_to_stop: ['matrix-mautrix-linkedin.service']
pgloader_options: ['--with "quote identifiers"']
- ansible.builtin.set_fact:
matrix_bridge_mautrix_linkedin_migration_requires_restart: true
- name: Ensure Mautrix linkedin paths exists
ansible.builtin.file:
path: "{{ item.path }}"
state: directory
mode: '0750'
owner: "{{ matrix_user_name }}"
group: "{{ matrix_group_name }}"
with_items:
- {path: "{{ matrix_bridge_mautrix_linkedin_base_path }}", when: true}
- {path: "{{ matrix_bridge_mautrix_linkedin_config_path }}", when: true}
- {path: "{{ matrix_bridge_mautrix_linkedin_data_path }}", when: true}
- {path: "{{ matrix_bridge_mautrix_linkedin_container_src_files_path }}", when: "{{ matrix_bridge_mautrix_linkedin_container_image_self_build }}"}
when: item.when | bool
- name: Ensure Mautrix linkedin image is pulled
community.docker.docker_image_pull:
name: "{{ matrix_bridge_mautrix_linkedin_container_image }}"
pull: always
when: not matrix_bridge_mautrix_linkedin_container_image_self_build
register: matrix_bridge_mautrix_linkedin_container_image_pull_result
retries: "{{ devture_playbook_help_container_retries_count }}"
delay: "{{ devture_playbook_help_container_retries_delay }}"
until: matrix_bridge_mautrix_linkedin_container_image_pull_result is not failed
- name: Ensure Mautrix linkedin repository is present on self-build
ansible.builtin.git:
repo: "{{ matrix_bridge_mautrix_linkedin_container_image_self_build_repo }}"
dest: "{{ matrix_bridge_mautrix_linkedin_container_src_files_path }}"
version: "{{ matrix_bridge_mautrix_linkedin_container_image_self_build_branch }}"
force: "yes"
become: true
become_user: "{{ matrix_user_name }}"
register: matrix_bridge_mautrix_linkedin_git_pull_results
when: "matrix_bridge_mautrix_linkedin_container_image_self_build | bool"
- name: Ensure Mautrix linkedin Docker image is built
community.docker.docker_image_build:
name: "{{ matrix_bridge_mautrix_linkedin_container_image }}"
dockerfile: Dockerfile
path: "{{ matrix_bridge_mautrix_linkedin_container_src_files_path }}"
pull: true
rebuild: "{{ 'always' if matrix_bridge_mautrix_linkedin_git_pull_results.changed | bool else 'never' }}"
when: "matrix_bridge_mautrix_linkedin_container_image_self_build | bool"
register: matrix_bridge_mautrix_linkedin_container_image_build_result
- name: Check if an old database file exists
ansible.builtin.stat:
path: "{{ matrix_bridge_mautrix_linkedin_base_path }}/mautrix-linkedin.db"
register: matrix_bridge_mautrix_linkedin_stat_database
- name: Check if an old Matrix state file exists
ansible.builtin.stat:
path: "{{ matrix_bridge_mautrix_linkedin_base_path }}/mx-state.json"
register: matrix_bridge_mautrix_linkedin_stat_mx_state
- name: (Data relocation) Ensure matrix-mautrix-linkedin.service is stopped
ansible.builtin.service:
name: matrix-mautrix-linkedin
state: stopped
enabled: false
daemon_reload: true
failed_when: false
when: "matrix_bridge_mautrix_linkedin_stat_database.stat.exists"
- name: (Data relocation) Move mautrix-linkedin database file to ./data directory
ansible.builtin.command:
cmd: "mv {{ matrix_bridge_mautrix_linkedin_base_path }}/mautrix-linkedin.db {{ matrix_bridge_mautrix_linkedin_data_path }}/mautrix-linkedin.db"
creates: "{{ matrix_bridge_mautrix_linkedin_data_path }}/mautrix-linkedin.db"
removes: "{{ matrix_bridge_mautrix_linkedin_base_path }}/mautrix-linkedin.db"
when: "matrix_bridge_mautrix_linkedin_stat_database.stat.exists"
- name: (Data relocation) Move mautrix-linkedin mx-state file to ./data directory
ansible.builtin.command:
cmd: "mv {{ matrix_bridge_mautrix_linkedin_base_path }}/mx-state.json {{ matrix_bridge_mautrix_linkedin_data_path }}/mx-state.json"
creates: "{{ matrix_bridge_mautrix_linkedin_data_path }}/mx-state.json"
removes: "{{ matrix_bridge_mautrix_linkedin_base_path }}/mx-state.json"
when: "matrix_bridge_mautrix_linkedin_stat_mx_state.stat.exists"
- name: Ensure mautrix-linkedin config.yaml installed
ansible.builtin.copy:
content: "{{ matrix_bridge_mautrix_linkedin_configuration | to_nice_yaml(indent=2, width=999999) }}"
dest: "{{ matrix_bridge_mautrix_linkedin_config_path }}/config.yaml"
mode: '0644'
owner: "{{ matrix_user_name }}"
group: "{{ matrix_group_name }}"
register: matrix_bridge_mautrix_linkedin_config_result
- name: Ensure mautrix-linkedin registration.yaml installed
ansible.builtin.copy:
content: "{{ matrix_bridge_mautrix_linkedin_registration | to_nice_yaml(indent=2, width=999999) }}"
dest: "{{ matrix_bridge_mautrix_linkedin_config_path }}/registration.yaml"
mode: '0644'
owner: "{{ matrix_user_name }}"
group: "{{ matrix_group_name }}"
register: matrix_bridge_mautrix_linkedin_registration_result
- name: Ensure matrix-mautrix-linkedin.service installed
ansible.builtin.template:
src: "{{ role_path }}/templates/systemd/matrix-mautrix-linkedin.service.j2"
dest: "{{ devture_systemd_docker_base_systemd_path }}/matrix-mautrix-linkedin.service"
mode: '0644'
register: matrix_bridge_mautrix_linkedin_systemd_service_result
- name: Ensure mautrix-linkedin support files installed
ansible.builtin.template:
src: "{{ role_path }}/templates/{{ item }}.j2"
dest: "{{ matrix_bridge_mautrix_linkedin_base_path }}/{{ item }}"
mode: '0640'
owner: "{{ matrix_user_name }}"
group: "{{ matrix_group_name }}"
with_items:
- labels
register: matrix_bridge_mautrix_linkedin_support_files_result
- name: Ensure matrix-mautrix-linkedin container network is created
when: matrix_bridge_mautrix_linkedin_container_network != 'host'
community.general.docker_network:
enable_ipv6: "{{ devture_systemd_docker_base_ipv6_enabled }}"
name: "{{ matrix_bridge_mautrix_linkedin_container_network }}"
driver: bridge
driver_options: "{{ devture_systemd_docker_base_container_networks_driver_options }}"
- name: Determine whether matrix-mautrix-linkedin needs a restart
ansible.builtin.set_fact:
matrix_bridge_mautrix_linkedin_restart_necessary: >-
{{
matrix_bridge_mautrix_linkedin_migration_requires_restart | default(false)
or matrix_bridge_mautrix_linkedin_config_result.changed | default(false)
or matrix_bridge_mautrix_linkedin_registration_result.changed | default(false)
or matrix_bridge_mautrix_linkedin_support_files_result.changed | default(false)
or matrix_bridge_mautrix_linkedin_systemd_service_result.changed | default(false)
or matrix_bridge_mautrix_linkedin_container_image_pull_result.changed | default(false)
or matrix_bridge_mautrix_linkedin_container_image_build_result.changed | default(false)
}}
- name: Ensure matrix-mautrix-linkedin.service restarted, if necessary
ansible.builtin.service:
name: "matrix-mautrix-linkedin.service"
state: restarted
daemon_reload: true
when: "matrix_bridge_mautrix_linkedin_migration_requires_restart | bool"
@@ -0,0 +1,25 @@
# SPDX-FileCopyrightText: 2026 MDAD project contributors
# SPDX-FileCopyrightText: 2026 Nikita Chernyi
#
# SPDX-License-Identifier: AGPL-3.0-or-later
---
- name: Check existence of matrix-mautrix-linkedin service
ansible.builtin.stat:
path: "{{ devture_systemd_docker_base_systemd_path }}/matrix-mautrix-linkedin.service"
register: matrix_bridge_mautrix_linkedin_service_stat
- when: matrix_bridge_mautrix_linkedin_service_stat.stat.exists | bool
block:
- name: Ensure matrix-mautrix-linkedin is stopped
ansible.builtin.service:
name: matrix-mautrix-linkedin
state: stopped
enabled: false
daemon_reload: true
- name: Ensure matrix-mautrix-linkedin.service doesn't exist
ansible.builtin.file:
path: "{{ devture_systemd_docker_base_systemd_path }}/matrix-mautrix-linkedin.service"
state: absent
@@ -0,0 +1,39 @@
# SPDX-FileCopyrightText: 2026 MDAD project contributors
# SPDX-FileCopyrightText: 2026 Nikita Chernyi
#
# SPDX-License-Identifier: AGPL-3.0-or-later
---
- name: (Deprecation) Catch and report renamed settings
ansible.builtin.fail:
msg: >-
Your configuration contains a variable, which now has a different name.
Please rename the variable (`{{ item.old }}` -> `{{ item.new }}`) on your configuration file (vars.yml).
when: "lookup('ansible.builtin.varnames', ('^' + item.old + '$'), wantlist=True) | length > 0"
with_items: []
- name: Fail if required mautrix-linkedin settings not defined
ansible.builtin.fail:
msg: >-
You need to define a required configuration setting (`{{ item.name }}`).
when: "item.when | bool and lookup('vars', item.name, default='') | string | length == 0"
with_items:
- {'name': 'matrix_bridge_mautrix_linkedin_appservice_token', when: true}
- {'name': 'matrix_bridge_mautrix_linkedin_homeserver_address', when: true}
- {'name': 'matrix_bridge_mautrix_linkedin_homeserver_token', when: true}
- {'name': 'matrix_bridge_mautrix_linkedin_database_hostname', when: "{{ matrix_bridge_mautrix_linkedin_database_engine == 'postgres' }}"}
- {'name': 'matrix_bridge_mautrix_linkedin_metrics_proxying_hostname', when: "{{ matrix_bridge_mautrix_linkedin_metrics_proxying_enabled }}"}
- {'name': 'matrix_bridge_mautrix_linkedin_metrics_proxying_path_prefix', when: "{{ matrix_bridge_mautrix_linkedin_metrics_proxying_enabled }}"}
- {'name': 'matrix_bridge_mautrix_linkedin_container_network', when: true}
- name: Fail if the deprecated beeper-linkedin bridge is also enabled
ansible.builtin.fail:
msg: >-
Both `matrix_bridge_beeper_linkedin_enabled` and `matrix_bridge_mautrix_linkedin_enabled` are set.
Both register `@linkedinbot` and the `@linkedin_*` user range as exclusive appservice namespaces,
so running them together makes homeserver event routing for those users ambiguous and lets one
bridge act as the other's puppets. Disable the deprecated beeper-linkedin bridge
(`matrix_bridge_beeper_linkedin_enabled: false`) and re-run the playbook so its uninstall removes
the old registration, then enable this bridge.
when: "matrix_bridge_beeper_linkedin_enabled | default(false) | bool"