feat(talk/turn/signaling/hpb): add role for Talk with backend services
This commit is contained in:
parent
78095cca1d
commit
27255a4bfa
25 changed files with 930 additions and 0 deletions
78
roles/talk/README.md
Normal file
78
roles/talk/README.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
# talk
|
||||
|
||||
Deploys the Nextcloud Talk High Performance Backend (HPB) stack:
|
||||
|
||||
- `nextcloud-spreed-signaling` (Strukturag)
|
||||
- `janus-gateway` (canyan build, WebRTC MCU)
|
||||
- `nats` (internal message broker)
|
||||
|
||||
Designed to be paired with the `digitalboard.core.coturn` role (TURN/STUN) and registered in
|
||||
Nextcloud via the new `digitalboard.core.nextcloud` `talk.yml` task.
|
||||
|
||||
## Required variables
|
||||
|
||||
| Variable | Description |
|
||||
|---|---|
|
||||
| `talk_domain` | Public host name (e.g. `signaling.digitalboard.ch`) |
|
||||
| `talk_nextcloud_url` | Base URL of the Nextcloud instance the HPB talks back to |
|
||||
| `talk_janus_public_ip` | Public IP used by Janus for ICE candidate gathering (nat_1_1_mapping) |
|
||||
| `talk_backend_secret` | HMAC secret shared with Nextcloud Talk; loaded from `secrets/{host}/talk_backend_secret` |
|
||||
| `talk_turn_secret` | Shared secret with coturn; loaded from `secrets/{host}/talk_turn_secret` (must equal `coturn_static_auth_secret`) |
|
||||
| `talk_session_hashkey` | 32-byte hex; loaded from `secrets/{host}/talk_session_hashkey` |
|
||||
| `talk_session_blockkey` | 32-byte hex; loaded from `secrets/{host}/talk_session_blockkey` |
|
||||
|
||||
## Important variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
|---|---|---|
|
||||
| `talk_internal_domain` | `""` | Optional split-horizon FQDN (matches the second SAN on the coturn cert) |
|
||||
| `talk_turn_servers` | `turns:.../443?transport=tcp,turn:.../443` | Comma-separated TURN URI list passed to the signaling server |
|
||||
| `talk_turn_realm` | `stun.example.test` | Realm advertised to clients |
|
||||
| `talk_janus_stun_server` | `stun.int.example.test` | STUN endpoint Janus uses for its own ICE; default points at the internal coturn name |
|
||||
| `talk_janus_rtp_port_min/max` | `20000`/`21000` | UDP/TCP relay range opened on the Janus container |
|
||||
| `talk_nextcloud_extra_host_ip` | `""` | Optional pin: bind the Nextcloud FQDN to a specific backend IP (bypasses hairpin/SNI) |
|
||||
| `talk_signaling_image` | `strukturag/nextcloud-spreed-signaling:1.3.4` | Pinned |
|
||||
| `talk_janus_image` | `canyan/janus-gateway:1.2.4` | Pinned |
|
||||
| `talk_nats_image` | `nats:2.10-alpine` | Pinned |
|
||||
|
||||
All defaults can be overridden per host_vars. The configurable image variables exist explicitly because
|
||||
this stack is still under active development upstream and you may want to roll forward independently.
|
||||
|
||||
## Secrets
|
||||
|
||||
The role expects these files under `playbooks/secrets/{{ inventory_hostname }}/`, mode 0600:
|
||||
|
||||
```
|
||||
talk_backend_secret # shared with Nextcloud Talk app (HPB shared secret)
|
||||
talk_turn_secret # = coturn_static_auth_secret on the TURN host
|
||||
talk_session_hashkey # 32-byte hex (openssl rand -hex 32)
|
||||
talk_session_blockkey # 32-byte hex (openssl rand -hex 32)
|
||||
```
|
||||
|
||||
If you prefer a different secret store, override the variables directly in host_vars.
|
||||
|
||||
## What gets registered in Nextcloud
|
||||
|
||||
The matching `digitalboard.core.nextcloud` task `talk.yml` runs:
|
||||
|
||||
- `php occ talk:signaling:add <talk_domain> <talk_backend_secret>` — register HPB
|
||||
- `php occ talk:turn:add` for each entry in `nextcloud_talk_turn_servers` — register TURN
|
||||
|
||||
That part lives in the **nextcloud** role and runs when `nextcloud_enable_talk: true`.
|
||||
|
||||
## Traefik
|
||||
|
||||
The role assumes a `digitalboard.core.traefik` instance in `backend` mode runs on the same host
|
||||
(picks up Docker container labels). The public `talk_domain` then needs to be exposed via the
|
||||
**DMZ Traefik**, by adding an entry to `traefik_dmz_exposed_services` in the signaling host's
|
||||
`host_vars`:
|
||||
|
||||
```yaml
|
||||
traefik_dmz_exposed_services:
|
||||
- name: signaling
|
||||
domain: signaling.digitalboard.ch
|
||||
port: 443
|
||||
protocol: https
|
||||
```
|
||||
|
||||
(The DMZ proxy aggregates exposed services from all `backend_servers` host_vars.)
|
||||
74
roles/talk/defaults/main.yml
Normal file
74
roles/talk/defaults/main.yml
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#SPDX-License-Identifier: MIT-0
|
||||
---
|
||||
# defaults file for talk (Nextcloud Talk High Performance Backend)
|
||||
|
||||
# Base directories (inherited from base role)
|
||||
docker_compose_base_dir: /etc/docker/compose
|
||||
docker_volume_base_dir: /srv/data
|
||||
|
||||
talk_service_name: signaling
|
||||
talk_docker_compose_dir: "{{ docker_compose_base_dir }}/{{ talk_service_name }}"
|
||||
talk_docker_volume_dir: "{{ docker_volume_base_dir }}/{{ talk_service_name }}"
|
||||
|
||||
# --- Container images (pinned) ---
|
||||
talk_signaling_image: "strukturag/nextcloud-spreed-signaling:1.3.4"
|
||||
talk_janus_image: "canyan/janus-gateway:1.2.4"
|
||||
talk_nats_image: "nats:2.10-alpine"
|
||||
|
||||
# --- Networking ---
|
||||
talk_traefik_network: "proxy"
|
||||
talk_internal_network: "hpb_internal"
|
||||
|
||||
# --- Public exposure ---
|
||||
talk_use_ssl: true
|
||||
talk_cert_resolver: "dns"
|
||||
talk_domain: "signaling.example.test" # public domain (over DMZ Traefik)
|
||||
talk_internal_domain: "" # optional split-horizon "int" domain (e.g. signaling.int.example.test)
|
||||
|
||||
# --- Backend (Nextcloud) registration ---
|
||||
# Nextcloud base URL the HPB talks back to. Must be reachable from the HPB container.
|
||||
talk_nextcloud_url: "https://cloud.example.test"
|
||||
# Pin Nextcloud domain to a backend IP via extra_hosts to bypass DMZ hairpin/SNI issues
|
||||
talk_nextcloud_extra_host_ip: "" # e.g. "172.16.9.88" — empty disables the pin
|
||||
|
||||
# Backend HMAC secret shared with Nextcloud Talk.
|
||||
# Pattern follows playbooks/secrets/{host}/<name>; override the lookup with vault if desired.
|
||||
talk_backend_secret: "{{ lookup('file', playbook_dir ~ '/secrets/' ~ inventory_hostname ~ '/talk_backend_secret') }}"
|
||||
|
||||
# --- TURN integration ---
|
||||
# Shared secret with coturn (--static-auth-secret). Must match coturn_static_auth_secret on the TURN host.
|
||||
talk_turn_secret: "{{ lookup('file', playbook_dir ~ '/secrets/' ~ inventory_hostname ~ '/talk_turn_secret') }}"
|
||||
# TURN server URI list as understood by the signaling server.
|
||||
# Defaults follow IANA standards (3478/5349). Override to ":443" in restrictive
|
||||
# network environments where coturn binds on 443.
|
||||
talk_turn_servers: "turns:stun.example.test:5349?transport=tcp,turn:stun.example.test:3478"
|
||||
talk_turn_realm: "stun.example.test"
|
||||
talk_turn_apikey: "" # optional; if empty a random one is generated on first run
|
||||
|
||||
# --- Session keys (server.conf [sessions]) ---
|
||||
# 32-byte hex strings. Loaded from secrets dir like the other shared secrets.
|
||||
talk_session_hashkey: "{{ lookup('file', playbook_dir ~ '/secrets/' ~ inventory_hostname ~ '/talk_session_hashkey') }}"
|
||||
talk_session_blockkey: "{{ lookup('file', playbook_dir ~ '/secrets/' ~ inventory_hostname ~ '/talk_session_blockkey') }}"
|
||||
|
||||
# --- MCU (Janus) ---
|
||||
talk_mcu_type: "janus"
|
||||
talk_janus_public_ip: "" # set in host_vars; goes into janus nat_1_1_mapping
|
||||
talk_janus_rtp_port_min: 20000
|
||||
talk_janus_rtp_port_max: 21000
|
||||
# STUN server Janus uses for its own ICE candidate gathering. Default points to internal coturn DNS name.
|
||||
talk_janus_stun_server: "stun.int.example.test"
|
||||
talk_janus_stun_port: 5349
|
||||
talk_janus_ice_lite: true
|
||||
talk_janus_ice_tcp: true
|
||||
|
||||
# --- Trusted proxies / allowed hosts for the signaling [app] section ---
|
||||
talk_trusted_proxies:
|
||||
- "172.16.0.0/12"
|
||||
- "192.168.0.0/16"
|
||||
- "10.0.0.0/8"
|
||||
talk_allowed_hosts:
|
||||
- "172.16.0.0/12"
|
||||
|
||||
# --- Extra hosts forwarded to all three containers ---
|
||||
# Pre-populated with the Nextcloud pin if talk_nextcloud_extra_host_ip is set; you can append more here.
|
||||
talk_extra_hosts: []
|
||||
8
roles/talk/handlers/main.yml
Normal file
8
roles/talk/handlers/main.yml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#SPDX-License-Identifier: MIT-0
|
||||
---
|
||||
# handlers file for talk
|
||||
|
||||
- name: Restart signaling stack
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ talk_docker_compose_dir }}"
|
||||
state: restarted
|
||||
15
roles/talk/meta/main.yml
Normal file
15
roles/talk/meta/main.yml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#SPDX-License-Identifier: MIT-0
|
||||
galaxy_info:
|
||||
author: Digital Board Team
|
||||
description: Deploy Nextcloud Talk High Performance Backend (nextcloud-spreed-signaling + Janus + NATS)
|
||||
company: digitalboard.ch
|
||||
license: GPL-2.0-or-later
|
||||
min_ansible_version: "2.14"
|
||||
galaxy_tags:
|
||||
- nextcloud
|
||||
- talk
|
||||
- signaling
|
||||
- hpb
|
||||
- janus
|
||||
- webrtc
|
||||
dependencies: []
|
||||
85
roles/talk/tasks/main.yml
Normal file
85
roles/talk/tasks/main.yml
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
#SPDX-License-Identifier: MIT-0
|
||||
---
|
||||
# tasks file for talk (HPB)
|
||||
|
||||
- name: Assert minimum configuration
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- talk_domain | length > 0
|
||||
- talk_nextcloud_url | length > 0
|
||||
- talk_backend_secret | length > 0
|
||||
- talk_turn_secret | length > 0
|
||||
- talk_janus_public_ip | length > 0
|
||||
- talk_session_hashkey | length > 0
|
||||
- talk_session_blockkey | length > 0
|
||||
fail_msg: >
|
||||
Required talk_* variables missing.
|
||||
Set talk_domain, talk_nextcloud_url, talk_janus_public_ip in host_vars
|
||||
and place backend/turn/session secrets in playbooks/secrets/{{ inventory_hostname }}/.
|
||||
|
||||
- name: Create talk compose directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ talk_docker_compose_dir }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Create signaling subdirectories (signaling + janus configs)
|
||||
ansible.builtin.file:
|
||||
path: "{{ talk_docker_compose_dir }}/{{ item }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
loop:
|
||||
- signaling
|
||||
- janus
|
||||
|
||||
- name: Create signaling data directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ talk_docker_volume_dir }}/signaling/data"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Ensure proxy network exists (created externally by Traefik role normally)
|
||||
community.docker.docker_network:
|
||||
name: "{{ talk_traefik_network }}"
|
||||
state: present
|
||||
|
||||
- name: Render signaling server.conf
|
||||
ansible.builtin.template:
|
||||
src: server.conf.j2
|
||||
dest: "{{ talk_docker_compose_dir }}/signaling/server.conf"
|
||||
mode: "0640"
|
||||
no_log: true
|
||||
notify: Restart signaling stack
|
||||
|
||||
- name: Render Janus main config
|
||||
ansible.builtin.template:
|
||||
src: janus.jcfg.j2
|
||||
dest: "{{ talk_docker_compose_dir }}/janus/janus.jcfg"
|
||||
mode: "0644"
|
||||
notify: Restart signaling stack
|
||||
|
||||
- name: Render Janus websockets transport config
|
||||
ansible.builtin.template:
|
||||
src: janus.transport.websockets.jcfg.j2
|
||||
dest: "{{ talk_docker_compose_dir }}/janus/janus.transport.websockets.jcfg"
|
||||
mode: "0644"
|
||||
notify: Restart signaling stack
|
||||
|
||||
- name: Render Janus logger config
|
||||
ansible.builtin.template:
|
||||
src: janus.logger.jcfg.j2
|
||||
dest: "{{ talk_docker_compose_dir }}/janus/janus.logger.jcfg"
|
||||
mode: "0644"
|
||||
notify: Restart signaling stack
|
||||
|
||||
- name: Render docker-compose.yml
|
||||
ansible.builtin.template:
|
||||
src: docker-compose.yml.j2
|
||||
dest: "{{ talk_docker_compose_dir }}/docker-compose.yml"
|
||||
mode: "0644"
|
||||
notify: Restart signaling stack
|
||||
|
||||
- name: Start signaling stack
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ talk_docker_compose_dir }}"
|
||||
state: present
|
||||
124
roles/talk/templates/docker-compose.yml.j2
Normal file
124
roles/talk/templates/docker-compose.yml.j2
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
{# Build the effective extra_hosts list once #}
|
||||
{% set _extra_hosts = [] %}
|
||||
{% if talk_nextcloud_extra_host_ip | length > 0 %}
|
||||
{% set _ = _extra_hosts.append((talk_nextcloud_url | urlsplit('hostname')) ~ ':' ~ talk_nextcloud_extra_host_ip) %}
|
||||
{% endif %}
|
||||
{% for h in talk_extra_hosts %}
|
||||
{% set _ = _extra_hosts.append(h) %}
|
||||
{% endfor %}
|
||||
networks:
|
||||
{{ talk_traefik_network }}:
|
||||
external: true
|
||||
{{ talk_internal_network }}:
|
||||
driver: bridge
|
||||
|
||||
services:
|
||||
nats:
|
||||
image: {{ talk_nats_image }}
|
||||
container_name: nats
|
||||
restart: unless-stopped
|
||||
{% if _extra_hosts | length > 0 %}
|
||||
extra_hosts:
|
||||
{% for h in _extra_hosts %}
|
||||
- "{{ h }}"
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
command: >
|
||||
-js
|
||||
-m 8222
|
||||
-p 4222
|
||||
healthcheck:
|
||||
test: ["CMD", "nc", "-z", "localhost", "4222"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 10
|
||||
networks:
|
||||
- {{ talk_internal_network }}
|
||||
|
||||
janus:
|
||||
image: {{ talk_janus_image }}
|
||||
container_name: janus
|
||||
restart: unless-stopped
|
||||
{% if _extra_hosts | length > 0 %}
|
||||
extra_hosts:
|
||||
{% for h in _extra_hosts %}
|
||||
- "{{ h }}"
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
environment:
|
||||
PUBLIC_IP: "{{ talk_janus_public_ip }}"
|
||||
RTP_RANGE: "{{ talk_janus_rtp_port_min }}-{{ talk_janus_rtp_port_max }}"
|
||||
volumes:
|
||||
- ./janus/janus.jcfg:/usr/local/etc/janus/janus.jcfg:ro
|
||||
- ./janus/janus.transport.websockets.jcfg:/usr/local/etc/janus/janus.transport.websockets.jcfg:ro
|
||||
- ./janus/janus.logger.jcfg:/usr/local/etc/janus/janus.logger.jcfg:ro
|
||||
networks:
|
||||
- {{ talk_internal_network }}
|
||||
ports:
|
||||
- "{{ talk_janus_rtp_port_min }}-{{ talk_janus_rtp_port_max }}:{{ talk_janus_rtp_port_min }}-{{ talk_janus_rtp_port_max }}/udp"
|
||||
- "{{ talk_janus_rtp_port_min }}-{{ talk_janus_rtp_port_max }}:{{ talk_janus_rtp_port_min }}-{{ talk_janus_rtp_port_max }}/tcp"
|
||||
ulimits:
|
||||
nofile:
|
||||
soft: 65536
|
||||
hard: 65536
|
||||
|
||||
signaling:
|
||||
image: {{ talk_signaling_image }}
|
||||
container_name: signaling
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
nats:
|
||||
condition: service_healthy
|
||||
{% if _extra_hosts | length > 0 %}
|
||||
extra_hosts:
|
||||
{% for h in _extra_hosts %}
|
||||
- "{{ h }}"
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
volumes:
|
||||
- ./signaling/server.conf:/config/server.conf:ro
|
||||
- {{ talk_docker_volume_dir }}/signaling/data:/var/lib/signaling
|
||||
networks:
|
||||
- {{ talk_traefik_network }}
|
||||
- {{ talk_internal_network }}
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.docker.network={{ talk_traefik_network }}
|
||||
|
||||
# Public WebSocket route (/spreed)
|
||||
- traefik.http.routers.signal-public.rule=Host(`{{ talk_domain }}`) && PathPrefix(`/spreed`)
|
||||
- traefik.http.routers.signal-public.entrypoints={{ 'websecure' if talk_use_ssl else 'web' }}
|
||||
{% if talk_use_ssl %}
|
||||
- traefik.http.routers.signal-public.tls=true
|
||||
- traefik.http.routers.signal-public.tls.certresolver={{ talk_cert_resolver }}
|
||||
{% endif %}
|
||||
- traefik.http.routers.signal-public.service=signal-svc
|
||||
- traefik.http.routers.signal-public.middlewares=signal-ws
|
||||
|
||||
# Public backend API route (/api/)
|
||||
- traefik.http.routers.signal-backend.rule=Host(`{{ talk_domain }}`) && PathPrefix(`/api/`)
|
||||
- traefik.http.routers.signal-backend.entrypoints={{ 'websecure' if talk_use_ssl else 'web' }}
|
||||
{% if talk_use_ssl %}
|
||||
- traefik.http.routers.signal-backend.tls=true
|
||||
- traefik.http.routers.signal-backend.tls.certresolver={{ talk_cert_resolver }}
|
||||
{% endif %}
|
||||
- traefik.http.routers.signal-backend.service=signal-svc
|
||||
|
||||
{% if talk_internal_domain | length > 0 %}
|
||||
# Internal split-horizon route (full host on int domain, WebSocket-aware)
|
||||
- traefik.http.routers.signal-int.rule=Host(`{{ talk_internal_domain }}`)
|
||||
- traefik.http.routers.signal-int.entrypoints={{ 'websecure' if talk_use_ssl else 'web' }}
|
||||
{% if talk_use_ssl %}
|
||||
- traefik.http.routers.signal-int.tls=true
|
||||
- traefik.http.routers.signal-int.tls.certresolver={{ talk_cert_resolver }}
|
||||
{% endif %}
|
||||
- traefik.http.routers.signal-int.service=signal-svc
|
||||
- traefik.http.routers.signal-int.middlewares=signal-ws
|
||||
{% endif %}
|
||||
|
||||
# Common service
|
||||
- traefik.http.services.signal-svc.loadbalancer.server.port=8181
|
||||
|
||||
# WebSocket upgrade headers
|
||||
- traefik.http.middlewares.signal-ws.headers.customrequestheaders.Upgrade=websocket
|
||||
- traefik.http.middlewares.signal-ws.headers.customrequestheaders.Connection=Upgrade
|
||||
28
roles/talk/templates/janus.jcfg.j2
Normal file
28
roles/talk/templates/janus.jcfg.j2
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
general: {
|
||||
configs_folder = "/usr/local/etc/janus"
|
||||
log_to_stdout = true
|
||||
}
|
||||
|
||||
nat: {
|
||||
nat_1_1_mapping = "{{ talk_janus_public_ip }}"
|
||||
ice_lite = {{ talk_janus_ice_lite | string | lower }}
|
||||
ice_tcp = {{ talk_janus_ice_tcp | string | lower }}
|
||||
|
||||
stun_server = "{{ talk_janus_stun_server }}"
|
||||
stun_port = {{ talk_janus_stun_port }}
|
||||
|
||||
rtp_port_range = "{{ talk_janus_rtp_port_min }}-{{ talk_janus_rtp_port_max }}"
|
||||
}
|
||||
|
||||
media: {
|
||||
rtp_port_range = "{{ talk_janus_rtp_port_min }}-{{ talk_janus_rtp_port_max }}"
|
||||
}
|
||||
|
||||
transports: {
|
||||
websockets: {
|
||||
ws = true
|
||||
ws_port = 8188
|
||||
ws_interface = "0.0.0.0"
|
||||
ws_ip = "0.0.0.0"
|
||||
}
|
||||
}
|
||||
3
roles/talk/templates/janus.logger.jcfg.j2
Normal file
3
roles/talk/templates/janus.logger.jcfg.j2
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
general: {
|
||||
enabled = true
|
||||
}
|
||||
7
roles/talk/templates/janus.transport.websockets.jcfg.j2
Normal file
7
roles/talk/templates/janus.transport.websockets.jcfg.j2
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
general: {
|
||||
ws = true
|
||||
ws_port = 8188
|
||||
ws_interface = "0.0.0.0"
|
||||
ws_pingpong_trigger = 60
|
||||
ws_pingpong_timeout = 30
|
||||
}
|
||||
33
roles/talk/templates/server.conf.j2
Normal file
33
roles/talk/templates/server.conf.j2
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
[http]
|
||||
listen = 0.0.0.0:8181
|
||||
base_url = https://{{ talk_domain }}
|
||||
|
||||
[backend]
|
||||
backends = cloud
|
||||
|
||||
[cloud]
|
||||
secret = {{ talk_backend_secret }}
|
||||
url = {{ talk_nextcloud_url }}
|
||||
|
||||
[nats]
|
||||
url = nats://nats:4222
|
||||
|
||||
[mcu]
|
||||
type = {{ talk_mcu_type }}
|
||||
url = ws://janus:8188/
|
||||
|
||||
[sessions]
|
||||
hashkey = {{ talk_session_hashkey }}
|
||||
blockkey = {{ talk_session_blockkey }}
|
||||
|
||||
[turn]
|
||||
servers = {{ talk_turn_servers }}
|
||||
realm = {{ talk_turn_realm }}
|
||||
{% if talk_turn_apikey | length > 0 %}
|
||||
apikey = {{ talk_turn_apikey }}
|
||||
{% endif %}
|
||||
secret = {{ talk_turn_secret }}
|
||||
|
||||
[app]
|
||||
trustedproxies = {{ talk_trusted_proxies | join(',') }}
|
||||
allowedhosts = {{ talk_allowed_hosts | join(',') }}
|
||||
2
roles/talk/tests/inventory
Normal file
2
roles/talk/tests/inventory
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#SPDX-License-Identifier: MIT-0
|
||||
localhost
|
||||
6
roles/talk/tests/test.yml
Normal file
6
roles/talk/tests/test.yml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#SPDX-License-Identifier: MIT-0
|
||||
---
|
||||
- hosts: localhost
|
||||
remote_user: root
|
||||
roles:
|
||||
- talk
|
||||
3
roles/talk/vars/main.yml
Normal file
3
roles/talk/vars/main.yml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#SPDX-License-Identifier: MIT-0
|
||||
---
|
||||
# vars file for httpbin
|
||||
Loading…
Add table
Add a link
Reference in a new issue