diff --git a/roles/jitsi/README.md b/roles/jitsi/README.md index 57f5f8e6..b3392c6a 100644 --- a/roles/jitsi/README.md +++ b/roles/jitsi/README.md @@ -35,8 +35,14 @@ Should work on Debian-based distributions. - `jitsi__timezone`: The time zone for the containers. Defaults to `Europe/Berlin`. -- `jitsi__jvb_advertise_ips`: List of IP addresses the JVB should advertise for media (`JVB_ADVERTISE_IPS`). +- `jitsi__jvb_advertise_ips`: List of IP addresses the JVB should advertise for media. + IPv4 addresses are put into `JVB_ADVERTISE_IPS`, which docker-jitsi-meet maps to the IPv4 address of the JVB container. + IPv6 addresses are mapped to the IPv6 address of the JVB container in `custom-jvb.conf` instead, for which the `meet.jitsi` network gets a fixed IPv6 subnet and the JVB a fixed IPv6 address. Defaults to `[ ]`. +- `jitsi__ipv6_subnet`: The IPv6 subnet of the `meet.jitsi` network, if IPv6 addresses are advertised. + Defaults to `fd4a:7c1e:93b5:1::/64`. +- `jitsi__jvb_ipv6_address`: The IPv6 address of the JVB container within `jitsi__ipv6_subnet`. + Defaults to `fd4a:7c1e:93b5:1::10`. - `jitsi__whiteboard`: Whether to deploy the Excalidraw whiteboard backend (`whiteboard.yml`). Defaults to `false`. - `jitsi__turn`: Whether to deploy coturn and configure Jitsi to use it. diff --git a/roles/jitsi/defaults/main.yaml b/roles/jitsi/defaults/main.yaml index 5bed993e..8532b275 100644 --- a/roles/jitsi/defaults/main.yaml +++ b/roles/jitsi/defaults/main.yaml @@ -1,5 +1,7 @@ jitsi__timezone: Europe/Berlin jitsi__jvb_advertise_ips: [ ] +jitsi__ipv6_subnet: fd4a:7c1e:93b5:1::/64 +jitsi__jvb_ipv6_address: fd4a:7c1e:93b5:1::10 jitsi__whiteboard: false jitsi__turn: false jitsi__prometheus_exporter: false diff --git a/roles/jitsi/handlers/main.yaml b/roles/jitsi/handlers/main.yaml index 7bde7f02..6f0eb2e3 100644 --- a/roles/jitsi/handlers/main.yaml +++ b/roles/jitsi/handlers/main.yaml @@ -8,6 +8,16 @@ state: restarted become: true +- name: restart jitsi jvb + community.docker.docker_compose_v2: + project_src: "{{ jitsi__base_dir }}" + project_name: jitsi + files: "{{ jitsi__compose_files }}" + services: + - jvb + state: restarted + become: true + - name: restart jitsi coturn community.docker.docker_compose_v2: project_src: "{{ jitsi__base_dir }}" diff --git a/roles/jitsi/meta/argument_specs.yaml b/roles/jitsi/meta/argument_specs.yaml index 36ee25b6..e2df54fe 100644 --- a/roles/jitsi/meta/argument_specs.yaml +++ b/roles/jitsi/meta/argument_specs.yaml @@ -27,6 +27,14 @@ argument_specs: elements: str required: false default: [ ] + jitsi__ipv6_subnet: + type: str + required: false + default: fd4a:7c1e:93b5:1::/64 + jitsi__jvb_ipv6_address: + type: str + required: false + default: fd4a:7c1e:93b5:1::10 jitsi__whiteboard: type: bool required: false diff --git a/roles/jitsi/tasks/main.yaml b/roles/jitsi/tasks/main.yaml index 92b9da83..4846ad5a 100644 --- a/roles/jitsi/tasks/main.yaml +++ b/roles/jitsi/tasks/main.yaml @@ -110,6 +110,25 @@ label: "{{ item.name }}" notify: restart jitsi web +- name: deploy custom JVB configuration + ansible.builtin.template: + src: custom-jvb.conf.j2 + dest: "{{ jitsi__config_dir }}/jvb/custom-jvb.conf" + mode: "0644" + owner: root + group: root + become: true + when: jitsi__jvb_advertise_ipv6s | length > 0 + notify: restart jitsi jvb + +- name: remove unconfigured custom JVB configuration + ansible.builtin.file: + path: "{{ jitsi__config_dir }}/jvb/custom-jvb.conf" + state: absent + become: true + when: jitsi__jvb_advertise_ipv6s | length == 0 + notify: restart jitsi jvb + - name: make sure the coturn directory exists ansible.builtin.file: path: "{{ jitsi__base_dir }}/coturn" diff --git a/roles/jitsi/templates/compose.override.yaml.j2 b/roles/jitsi/templates/compose.override.yaml.j2 index 628b83bc..2cefd134 100644 --- a/roles/jitsi/templates/compose.override.yaml.j2 +++ b/roles/jitsi/templates/compose.override.yaml.j2 @@ -6,8 +6,20 @@ networks: meet.jitsi: enable_ipv6: true +{% if jitsi__jvb_advertise_ipv6s | length > 0 %} + # A fixed subnet, so the JVB can have a fixed IPv6 address to map the public ones to. + ipam: + config: + - subnet: {{ jitsi__ipv6_subnet }} +{% endif %} services: +{% if jitsi__jvb_advertise_ipv6s | length > 0 %} + jvb: + networks: + meet.jitsi: + ipv6_address: {{ jitsi__jvb_ipv6_address }} +{% endif %} {% if jitsi__web_files | length > 0 %} web: volumes: @@ -42,6 +54,6 @@ services: networks: meet.jitsi: {% endif %} -{% if not (jitsi__web_files or jitsi__turn or jitsi__prometheus_exporter) %} +{% if not (jitsi__jvb_advertise_ipv6s or jitsi__web_files or jitsi__turn or jitsi__prometheus_exporter) %} {} {% endif %} diff --git a/roles/jitsi/templates/custom-jvb.conf.j2 b/roles/jitsi/templates/custom-jvb.conf.j2 new file mode 100644 index 00000000..050511a9 --- /dev/null +++ b/roles/jitsi/templates/custom-jvb.conf.j2 @@ -0,0 +1,11 @@ +# {{ ansible_managed }} +# Included at the end of the generated jvb.conf. +# Map the advertised IPv6 addresses to the pinned IPv6 address of the JVB, in addition to +# the mappings of the IPv4 addresses generated from JVB_ADVERTISE_IPS. +{% for ip in jitsi__jvb_advertise_ipv6s %} +ice4j.harvest.mapping.static-mappings += { + local-address = "{{ jitsi__jvb_ipv6_address }}" + public-address = "{{ ip }}" + name = "ipv6-{{ loop.index0 }}" +} +{% endfor %} diff --git a/roles/jitsi/templates/jitsi.env.j2 b/roles/jitsi/templates/jitsi.env.j2 index f09b0414..f5d8a447 100644 --- a/roles/jitsi/templates/jitsi.env.j2 +++ b/roles/jitsi/templates/jitsi.env.j2 @@ -19,8 +19,8 @@ ENABLE_LETSENCRYPT=1 LETSENCRYPT_DOMAIN={{ jitsi__domain }} LETSENCRYPT_EMAIL={{ jitsi__letsencrypt_email }} LETSENCRYPT_ACME_SERVER=letsencrypt -{% if jitsi__jvb_advertise_ips | length > 0 %} -JVB_ADVERTISE_IPS={{ jitsi__jvb_advertise_ips | join(',') }} +{% if jitsi__jvb_advertise_ipv4s | length > 0 %} +JVB_ADVERTISE_IPS={{ jitsi__jvb_advertise_ipv4s | join(',') }} {% endif %} {% if jitsi__whiteboard %} diff --git a/roles/jitsi/vars/main.yaml b/roles/jitsi/vars/main.yaml index 21fe76b6..993aa412 100644 --- a/roles/jitsi/vars/main.yaml +++ b/roles/jitsi/vars/main.yaml @@ -1,4 +1,8 @@ jitsi__base_dir: /opt/jitsi jitsi__config_dir: "{{ jitsi__base_dir }}/config" jitsi__release_dir: "{{ jitsi__base_dir }}/releases/docker-jitsi-meet-{{ jitsi__version }}" +# docker-jitsi-meet maps all JVB_ADVERTISE_IPS to the container's IPv4 address, so IPv6 +# addresses are mapped to the pinned IPv6 address of the JVB in custom-jvb.conf instead. +jitsi__jvb_advertise_ipv4s: "{{ jitsi__jvb_advertise_ips | reject('search', ':') | list }}" +jitsi__jvb_advertise_ipv6s: "{{ jitsi__jvb_advertise_ips | select('search', ':') | list }}" jitsi__compose_files: "{{ ['release/docker-compose.yml'] + (['release/whiteboard.yml'] if jitsi__whiteboard else []) + ['compose.override.yaml'] }}"