Provision extra Jitsi JVB services on additional hosts (#2166)

* Add task to configure a standalone JVB on a different server

* add missing file

* set nginx config

* update prosody file and expose port 5222

* change variable name to server id

* formatting change

* use server id of jvb-1 for the main server

* adding documentation

* adding more jvbs

* rename variable

* revert file

* fix yaml error

* minor doc fixes

* renaming tags and introducing a common tag

* remove duplicates

* add mapping for jvb to hostname/ip

* missed a jvb_server

* Update roles/matrix-nginx-proxy/templates/nginx/conf.d/matrix-jitsi.conf.j2

Co-authored-by: Slavi Pantaleev <slavi@devture.com>

* PR review comments and additional documentation

* iterate on dict items

* Update docs/configuring-playbook-jitsi.md

Co-authored-by: Slavi Pantaleev <slavi@devture.com>

* Update docs/configuring-playbook-jitsi.md

Co-authored-by: Slavi Pantaleev <slavi@devture.com>

* Update docs/configuring-playbook-jitsi.md

Co-authored-by: Slavi Pantaleev <slavi@devture.com>

* Update docs/configuring-playbook-jitsi.md

Co-authored-by: Slavi Pantaleev <slavi@devture.com>

* Update docs/configuring-playbook-jitsi.md

Co-authored-by: Slavi Pantaleev <slavi@devture.com>

* Update docs/configuring-playbook-jitsi.md

Co-authored-by: Slavi Pantaleev <slavi@devture.com>

* Update docs/configuring-playbook-jitsi.md

Co-authored-by: Slavi Pantaleev <slavi@devture.com>

* adding documentation around the xmpp setting

* add common after

* reduce the number of services during init of the additional jvb

* remove rogue i

* revert change to jitsi init as it's needed

* only run the jvb service on the additional jvb host

* updating docs

* reset default and add documentation about the websocket port

* fix issue rather merge with master

* add missing role introduced in master

* this role is required too

* Adding new jitsi jvb playbook, moving setup.yml to matrix.yml and creating soft link

* updating documentation

* revert accidental change to file

* add symlink back to roles to aid running of the jitsi playbook

* Remove extra space

* Delete useless playbooks/roles symlink

* Remove blank lines

Co-authored-by: Slavi Pantaleev <slavi@devture.com>
This commit is contained in:
Warren Bailey 2022-11-18 12:00:27 +00:00 committed by GitHub
parent 45c0467745
commit 84c74136ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 258 additions and 128 deletions

View File

@ -127,6 +127,70 @@ Read how it works [here](https://github.com/jitsi/jitsi-videobridge/blob/master/
You may want to **limit the maximum video resolution**, to save up resources on both server and clients.
## (Optional) Additional JVBs
By default, a single JVB ([Jitsi VideoBridge](https://github.com/jitsi/jitsi-videobridge)) is deployed on the same host as the Matrix server. To allow more video-conferences to happen at the same time, you may need to provision additional JVB services on other hosts.
There is an ansible playbook that can be run with the following tag:
` ansible-playbook -i inventory/hosts --limit jitsi_jvb_servers jitsi_jvb.yml --tags=common,setup-additional-jitsi-jvb,start`
For this role to work you will need an additional section in the ansible hosts file with the details of the JVB hosts, for example:
```
[jitsi_jvb_servers]
<your jvb hosts> ansible_host=<ip address of the jvb host>
```
Each JVB will require a server id to be set so that it can be uniquely identified and this allows Jitsi to keep track of which conferences are on which JVB.
The server id is set with the variable `matrix_jitsi_jvb_server_id` which ends up as the JVB_WS_SERVER_ID environment variables in the JVB docker container.
This variable can be set via the host file, a parameter to the ansible command or in the `vars.yaml` for the host which will have the additional JVB. For example:
``` yaml
matrix_jitsi_jvb_server_id: 'jvb-2'
```
``` INI
[jitsi_jvb_servers]
jvb-2.example.com ansible_host=192.168.0.2 matrix_jitsi_jvb_server_id=jvb-2
jvb-3.example.com ansible_host=192.168.0.3 matrix_jitsi_jvb_server_id=jvb-2
```
Note that the server id `jvb-1` is reserved for the JVB instance running on the Matrix host and therefore should not be used as the id of an additional jvb host.
The additional JVB will also need to expose the colibri web socket port and this can be done with the following variable:
```yaml
matrix_jitsi_jvb_container_colibri_ws_host_bind_port: 9090
```
The JVB will also need to know where the prosody xmpp server is located, similar to the server id this can be set in the vars for the JVB by using the variable
`matrix_jitsi_xmpp_server`. The Jitsi prosody container is deployed on the matrix server by default so the value can be set to the matrix domain. For example:
```yaml
matrix_jitsi_xmpp_server: "{{ matrix_domain }}"
```
However, it can also be set the ip address of the matrix server. This can be useful if you wish to use a private ip. For example:
```yaml
matrix_jitsi_xmpp_server: "192.168.0.1"
```
The nginx configuration will also need to be updated in order to deal with the additional JVB servers. This is achieved via its own configuration variable
`matrix_nginx_proxy_proxy_jitsi_additional_jvbs`, which contains a dictionary of server ids to ip addresses.
For example,
``` yaml
matrix_nginx_proxy_proxy_jitsi_additional_jvbs:
jvb-2: 192.168.0.2
jvb-3: 192.168.0.3
```
Applied together this will allow you to provision extra JVB instances which will register themselves with the prosody service and be available for jicofo
to route conferences too.
## Apply changes

12
playbooks/jitsi_jvb.yml Normal file
View File

@ -0,0 +1,12 @@
---
- name: "Set up additional Jitsi JVB servers"
hosts: "jitsi_jvb_servers"
become: true
roles:
- role: galaxy/com.devture.ansible.role.playbook_help
- role: galaxy/com.devture.ansible.role.systemd_docker_base
- custom/matrix-base
- custom/matrix-jitsi
- custom/matrix-common-after

95
playbooks/matrix.yml Executable file
View File

@ -0,0 +1,95 @@
---
- name: "Set up a Matrix server"
hosts: "{{ target if target is defined else 'matrix_servers' }}"
become: true
roles:
# Most of the roles below are not distributed with the playbook, but downloaded separately using `ansible-galaxy` via the `make roles` command (see `Makefile`).
- role: galaxy/com.devture.ansible.role.playbook_help
- role: galaxy/com.devture.ansible.role.systemd_docker_base
- role: custom/matrix_playbook_migration
- when: devture_timesync_installation_enabled | bool
role: galaxy/com.devture.ansible.role.timesync
tags:
- setup-timesync
- setup-all
- custom/matrix-base
- custom/matrix-dynamic-dns
- custom/matrix-mailer
- custom/matrix-postgres
- custom/matrix-redis
- custom/matrix-corporal
- custom/matrix-bridge-appservice-discord
- custom/matrix-bridge-appservice-slack
- custom/matrix-bridge-appservice-webhooks
- custom/matrix-bridge-appservice-irc
- custom/matrix-bridge-appservice-kakaotalk
- custom/matrix-bridge-beeper-linkedin
- custom/matrix-bridge-go-skype-bridge
- custom/matrix-bridge-mautrix-facebook
- custom/matrix-bridge-mautrix-twitter
- custom/matrix-bridge-mautrix-hangouts
- custom/matrix-bridge-mautrix-googlechat
- custom/matrix-bridge-mautrix-instagram
- custom/matrix-bridge-mautrix-signal
- custom/matrix-bridge-mautrix-telegram
- custom/matrix-bridge-mautrix-whatsapp
- custom/matrix-bridge-mautrix-discord
- custom/matrix-bridge-mx-puppet-discord
- custom/matrix-bridge-mx-puppet-groupme
- custom/matrix-bridge-mx-puppet-steam
- custom/matrix-bridge-mx-puppet-slack
- custom/matrix-bridge-mx-puppet-twitter
- custom/matrix-bridge-mx-puppet-instagram
- custom/matrix-bridge-sms
- custom/matrix-bridge-heisenbridge
- custom/matrix-bridge-hookshot
- custom/matrix-bot-matrix-reminder-bot
- custom/matrix-bot-matrix-registration-bot
- custom/matrix-bot-maubot
- custom/matrix-bot-buscarron
- custom/matrix-bot-honoroit
- custom/matrix-bot-postmoogle
- custom/matrix-bot-go-neb
- custom/matrix-bot-mjolnir
- custom/matrix-cactus-comments
- custom/matrix-synapse
- custom/matrix-dendrite
- custom/matrix-conduit
- custom/matrix-synapse-admin
- custom/matrix-prometheus-node-exporter
- custom/matrix-prometheus-postgres-exporter
- custom/matrix-prometheus
- custom/matrix-grafana
- custom/matrix-registration
- custom/matrix-client-element
- custom/matrix-client-hydrogen
- custom/matrix-client-cinny
- custom/matrix-jitsi
- custom/matrix-ldap-registration-proxy
- custom/matrix-ma1sd
- custom/matrix-dimension
- custom/matrix-etherpad
- custom/matrix-email2matrix
- custom/matrix-sygnal
- custom/matrix-ntfy
- custom/matrix-nginx-proxy
- custom/matrix-coturn
- custom/matrix-aux
- custom/matrix-postgres-backup
- custom/matrix-backup-borg
- custom/matrix-user-creator
- custom/matrix-common-after
# This is pretty much last, because we want it to better serve as a "last known good configuration".
# See: https://github.com/spantaleev/matrix-docker-ansible-deploy/pull/2217#issuecomment-1301487601
- when: devture_playbook_state_preserver_enabled | bool
role: galaxy/com.devture.ansible.role.playbook_state_preserver
tags:
- setup-all
- role: galaxy/com.devture.ansible.role.playbook_runtime_messages

View File

@ -1,18 +1,24 @@
---
- ansible.builtin.import_tasks: "{{ role_path }}/tasks/system_check.yml"
tags:
- always
- ansible.builtin.import_tasks: "{{ role_path }}/tasks/sanity_check.yml"
tags:
- always
- setup-all
- ansible.builtin.import_tasks: "{{ role_path }}/tasks/clean_up_old_files.yml"
when: run_setup | bool
tags:
- setup-all
- common
- ansible.builtin.import_tasks: "{{ role_path }}/tasks/server_base/setup.yml"
when: run_setup | bool
tags:
- setup-all
- common
# This needs to always run, because it populates `matrix_user_uid` and `matrix_user_gid`,
# which are required by many other roles.
@ -21,11 +27,13 @@
tags:
- always
- setup-system-user
- common
- ansible.builtin.import_tasks: "{{ role_path }}/tasks/setup_matrix_base.yml"
when: run_setup | bool
tags:
- setup-all
- common
- ansible.builtin.import_tasks: "{{ role_path }}/tasks/setup_well_known.yml"
when: run_setup | bool

View File

@ -5,21 +5,6 @@
msg: "You need to set a valid homeserver implementation in `matrix_homeserver_implementation`"
when: "matrix_homeserver_implementation not in ['synapse', 'dendrite', 'conduit']"
# We generally support Ansible 2.7.1 and above.
- name: Fail if running on Ansible < 2.7.1
ansible.builtin.fail:
msg: "You are running on Ansible {{ ansible_version.string }}, which is not supported. See our guide about Ansible: https://github.com/spantaleev/matrix-docker-ansible-deploy/blob/master/docs/ansible.md"
when:
- "(ansible_version.major < 2) or (ansible_version.major == 2 and ansible_version.minor < 7) or (ansible_version.major == 2 and ansible_version.minor == 7 and ansible_version.revision < 1)"
# Though we do not support Ansible 2.9.6 which is buggy
- name: Fail if running on Ansible 2.9.6 on Ubuntu
ansible.builtin.fail:
msg: "You are running on Ansible {{ ansible_version.string }}, which is not supported. See our guide about Ansible: https://github.com/spantaleev/matrix-docker-ansible-deploy/blob/master/docs/ansible.md"
when:
- ansible_distribution == 'Ubuntu'
- "ansible_version.major == 2 and ansible_version.minor == 9 and ansible_version.revision == 6"
- name: (Deprecation) Catch and report renamed settings
ansible.builtin.fail:
msg: >-
@ -66,20 +51,6 @@
- "{{ matrix_server_fqn_element }}"
when: "item != item | lower"
- name: Fail if using python2 on Archlinux
ansible.builtin.fail:
msg: "Detected that you're using python2 when installing onto Archlinux. Archlinux by default only supports python3."
when:
- ansible_distribution == 'Archlinux'
- ansible_python.version.major != 3
- name: Fail if architecture is set incorrectly
ansible.builtin.fail:
msg: "Detected that variable matrix_architecture {{ matrix_architecture }} appears to be set incorrectly. See docs/alternative-architectures.md. Server appears to be {{ ansible_architecture }}."
when: (ansible_architecture == "x86_64" and matrix_architecture != "amd64") or
(ansible_architecture == "aarch64" and matrix_architecture != "arm64") or
(ansible_architecture.startswith("armv") and matrix_architecture != "arm32")
- name: Fail if encountering usage of removed role (mx-puppet-skype)
ansible.builtin.fail:
msg: >-

View File

@ -0,0 +1,30 @@
---
# We generally support Ansible 2.7.1 and above.
- name: Fail if running on Ansible < 2.7.1
ansible.builtin.fail:
msg: "You are running on Ansible {{ ansible_version.string }}, which is not supported. See our guide about Ansible: https://github.com/spantaleev/matrix-docker-ansible-deploy/blob/master/docs/ansible.md"
when:
- "(ansible_version.major < 2) or (ansible_version.major == 2 and ansible_version.minor < 7) or (ansible_version.major == 2 and ansible_version.minor == 7 and ansible_version.revision < 1)"
# Though we do not support Ansible 2.9.6 which is buggy
- name: Fail if running on Ansible 2.9.6 on Ubuntu
ansible.builtin.fail:
msg: "You are running on Ansible {{ ansible_version.string }}, which is not supported. See our guide about Ansible: https://github.com/spantaleev/matrix-docker-ansible-deploy/blob/master/docs/ansible.md"
when:
- ansible_distribution == 'Ubuntu'
- "ansible_version.major == 2 and ansible_version.minor == 9 and ansible_version.revision == 6"
- name: Fail if using python2 on Archlinux
ansible.builtin.fail:
msg: "Detected that you're using python2 when installing onto Archlinux. Archlinux by default only supports python3."
when:
- ansible_distribution == 'Archlinux'
- ansible_python.version.major != 3
- name: Fail if architecture is set incorrectly
ansible.builtin.fail:
msg: "Detected that variable matrix_architecture {{ matrix_architecture }} appears to be set incorrectly. See docs/alternative-architectures.md. Server appears to be {{ ansible_architecture }}."
when: (ansible_architecture == "x86_64" and matrix_architecture != "amd64") or
(ansible_architecture == "aarch64" and matrix_architecture != "arm64") or
(ansible_architecture.startswith("armv") and matrix_architecture != "arm32")

View File

@ -189,6 +189,8 @@ matrix_jitsi_prosody_systemd_required_services_list: ['docker.service']
# Neccessary Port binding for those disabling the integrated nginx proxy
matrix_jitsi_prosody_container_http_host_bind_port: ''
matrix_jitsi_prosody_container_jvb_host_bind_port: 5222
matrix_jitsi_jicofo_docker_image: "{{ matrix_container_global_registry_prefix }}jitsi/jicofo:{{ matrix_jitsi_container_image_tag }}"
matrix_jitsi_jicofo_docker_image_force_pull: "{{ matrix_jitsi_jicofo_docker_image.endswith(':latest') }}"
@ -218,7 +220,7 @@ matrix_jitsi_jvb_config_path: "{{ matrix_jitsi_jvb_base_path }}/config"
matrix_jitsi_jvb_container_extra_arguments: []
# List of systemd services that matrix-jitsi-jvb.service depends on
matrix_jitsi_jvb_systemd_required_services_list: ['docker.service', 'matrix-jitsi-prosody.service']
matrix_jitsi_jvb_systemd_required_services_list: ['docker.service']
matrix_jitsi_jvb_auth_user: jvb
matrix_jitsi_jvb_auth_password: ''
@ -233,6 +235,8 @@ matrix_jitsi_jvb_stun_servers: ['meet-jit-si-turnrelay.jitsi.net:443']
matrix_jitsi_jvb_brewery_muc: jvbbrewery
matrix_jitsi_jvb_rtp_udp_port: 10000
matrix_jitsi_jvb_rtp_tcp_port: 4443
matrix_jitsi_jvb_server_id: 'jvb-1'
# Custom configuration to be injected into `custom-sip-communicator.properties`, passed to Jitsi JVB.
# This configuration gets appended to the final configuration that Jitsi JVB uses.

View File

@ -0,0 +1,5 @@
---
- ansible.builtin.set_fact:
matrix_systemd_services_list: "{{ ['matrix-jitsi-jvb.service'] }}"
when: matrix_jitsi_enabled | bool

View File

@ -4,17 +4,23 @@
tags:
- always
- ansible.builtin.import_tasks: "{{ role_path }}/tasks/init_additional_jvb.yml"
tags:
- setup-additional-jitsi-jvb
- ansible.builtin.import_tasks: "{{ role_path }}/tasks/validate_config.yml"
when: "run_setup | bool and matrix_jitsi_enabled | bool"
tags:
- setup-all
- setup-jitsi
- setup-additional-jitsi-jvb
- ansible.builtin.import_tasks: "{{ role_path }}/tasks/setup_jitsi_base.yml"
when: run_setup | bool
tags:
- setup-all
- setup-jitsi
- setup-additional-jitsi-jvb
- ansible.builtin.import_tasks: "{{ role_path }}/tasks/setup_jitsi_web.yml"
when: run_setup | bool
@ -39,3 +45,4 @@
tags:
- setup-all
- setup-jitsi
- setup-additional-jitsi-jvb

View File

@ -16,7 +16,7 @@ JVB_OCTO_PUBLIC_ADDRESS
JVB_OCTO_BIND_PORT
JVB_OCTO_REGION
JVB_WS_DOMAIN
JVB_WS_SERVER_ID
JVB_WS_SERVER_ID={{ matrix_jitsi_jvb_server_id }}
PUBLIC_URL={{ matrix_jitsi_web_public_url }}
SENTRY_DSN={{ matrix_jitsi_jvb_sentry_dsn }}
SENTRY_ENVIRONMENT

View File

@ -20,6 +20,9 @@ ExecStart={{ devture_systemd_docker_base_host_command_docker }} run --rm --name
{% if matrix_jitsi_prosody_container_http_host_bind_port %}
-p {{ matrix_jitsi_prosody_container_http_host_bind_port }}:5280 \
{% endif %}
{% if matrix_jitsi_prosody_container_jvb_host_bind_port %}
-p {{ matrix_jitsi_prosody_container_jvb_host_bind_port }}:5222 \
{% endif %}
--env-file={{ matrix_jitsi_prosody_base_path }}/env \
--mount type=bind,src={{ matrix_jitsi_prosody_config_path }},dst=/config \
--mount type=bind,src={{ matrix_jitsi_prosody_plugins_path }},dst=/prosody-plugins-custom \

View File

@ -667,3 +667,12 @@ matrix_nginx_proxy_synapse_cache_proxy_cache_valid_time: "24h"
# http://nginx.org/en/docs/ngx_core_module.html#worker_connections
matrix_nginx_proxy_worker_processes: auto
matrix_nginx_proxy_worker_connections: 1024
# A mapping of JVB server ids to hostname/ipa addresses used to add additional jvb blocks
# to the Jitsi's server configuration (matrix-jitsi.conf)
# Note: avoid using the JVB server id "jvb-1" as this is reserved for the main host.
# Example:
# matrix_nginx_proxy_proxy_jitsi_additional_jvbs:
# jvb-2: 192.168.0.1
# jvb-3: 192.168.0.2
matrix_nginx_proxy_proxy_jitsi_additional_jvbs: {}

View File

@ -34,7 +34,7 @@
}
# colibri (JVB) websockets
location ~ ^/colibri-ws/([a-zA-Z0-9-\.]+)/(.*) {
location ~ ^/colibri-ws/jvb-1/(.*) {
{% if matrix_nginx_proxy_enabled %}
resolver {{ matrix_nginx_proxy_http_level_resolver }} valid=5s;
set $backend "matrix-jitsi-jvb:9090";
@ -53,6 +53,22 @@
tcp_nodelay on;
}
{% for id, ip_address in matrix_nginx_proxy_proxy_jitsi_additional_jvbs.items() %}
# colibri (JVB) websockets for additional JVBs
location ~ ^/colibri-ws/{{ id | regex_escape }}/(.*) {
proxy_pass http://{{ ip_address }}:9090/colibri-ws/{{ id }}/$1$is_args$args;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For {{ matrix_nginx_proxy_x_forwarded_for }};
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
tcp_nodelay on;
}
{% endfor %}
# XMPP websocket
location = /xmpp-websocket {

View File

@ -1,95 +0,0 @@
---
- name: "Set up a Matrix server"
hosts: "{{ target if target is defined else 'matrix_servers' }}"
become: true
roles:
# Most of the roles below are not distributed with the playbook, but downloaded separately using `ansible-galaxy` via the `make roles` command (see `Makefile`).
- role: galaxy/com.devture.ansible.role.playbook_help
- role: galaxy/com.devture.ansible.role.systemd_docker_base
- role: custom/matrix_playbook_migration
- when: devture_timesync_installation_enabled | bool
role: galaxy/com.devture.ansible.role.timesync
tags:
- setup-timesync
- setup-all
- custom/matrix-base
- custom/matrix-dynamic-dns
- custom/matrix-mailer
- custom/matrix-postgres
- custom/matrix-redis
- custom/matrix-corporal
- custom/matrix-bridge-appservice-discord
- custom/matrix-bridge-appservice-slack
- custom/matrix-bridge-appservice-webhooks
- custom/matrix-bridge-appservice-irc
- custom/matrix-bridge-appservice-kakaotalk
- custom/matrix-bridge-beeper-linkedin
- custom/matrix-bridge-go-skype-bridge
- custom/matrix-bridge-mautrix-facebook
- custom/matrix-bridge-mautrix-twitter
- custom/matrix-bridge-mautrix-hangouts
- custom/matrix-bridge-mautrix-googlechat
- custom/matrix-bridge-mautrix-instagram
- custom/matrix-bridge-mautrix-signal
- custom/matrix-bridge-mautrix-telegram
- custom/matrix-bridge-mautrix-whatsapp
- custom/matrix-bridge-mautrix-discord
- custom/matrix-bridge-mx-puppet-discord
- custom/matrix-bridge-mx-puppet-groupme
- custom/matrix-bridge-mx-puppet-steam
- custom/matrix-bridge-mx-puppet-slack
- custom/matrix-bridge-mx-puppet-twitter
- custom/matrix-bridge-mx-puppet-instagram
- custom/matrix-bridge-sms
- custom/matrix-bridge-heisenbridge
- custom/matrix-bridge-hookshot
- custom/matrix-bot-matrix-reminder-bot
- custom/matrix-bot-matrix-registration-bot
- custom/matrix-bot-maubot
- custom/matrix-bot-buscarron
- custom/matrix-bot-honoroit
- custom/matrix-bot-postmoogle
- custom/matrix-bot-go-neb
- custom/matrix-bot-mjolnir
- custom/matrix-cactus-comments
- custom/matrix-synapse
- custom/matrix-dendrite
- custom/matrix-conduit
- custom/matrix-synapse-admin
- custom/matrix-prometheus-node-exporter
- custom/matrix-prometheus-postgres-exporter
- custom/matrix-prometheus
- custom/matrix-grafana
- custom/matrix-registration
- custom/matrix-client-element
- custom/matrix-client-hydrogen
- custom/matrix-client-cinny
- custom/matrix-jitsi
- custom/matrix-ldap-registration-proxy
- custom/matrix-ma1sd
- custom/matrix-dimension
- custom/matrix-etherpad
- custom/matrix-email2matrix
- custom/matrix-sygnal
- custom/matrix-ntfy
- custom/matrix-nginx-proxy
- custom/matrix-coturn
- custom/matrix-aux
- custom/matrix-postgres-backup
- custom/matrix-backup-borg
- custom/matrix-user-creator
- custom/matrix-common-after
# This is pretty much last, because we want it to better serve as a "last known good configuration".
# See: https://github.com/spantaleev/matrix-docker-ansible-deploy/pull/2217#issuecomment-1301487601
- when: devture_playbook_state_preserver_enabled | bool
role: galaxy/com.devture.ansible.role.playbook_state_preserver
tags:
- setup-all
- role: galaxy/com.devture.ansible.role.playbook_runtime_messages

1
setup.yml Symbolic link
View File

@ -0,0 +1 @@
playbooks/matrix.yml