--- - name: turn hosts: all tasks: - name: Create /home/docker/turn.{{inventory_hostname}} dir ansible.builtin.file: path: /home/docker/turn.{{inventory_hostname}} owner: root group: docker state: directory mode: '0550' - name: Create /home/docker/turn.{{inventory_hostname}}/coturn dir ansible.builtin.file: path: /home/docker/turn.{{inventory_hostname}}/coturn owner: nobody group: docker state: directory mode: '0550' - name: /home/docker/turn.{{inventory_hostname}}/coturn/turnserver.conf blockinfile: path: /home/docker/turn.{{inventory_hostname}}/coturn/turnserver.conf mode: "0400" owner: nobody group: root create: yes marker: "# {mark} ANSIBLE MANAGED BLOCK" block: | use-auth-secret realm=turn.{{inventory_hostname}} listening-port=3479 tls-listening-port=5349 min-port=49160 max-port=49200 verbose #allow-loopback-peers log-file=stdout new-log-timestamp tls-listening-port=5349 cert=/etc/coturn/cert.pem pkey=/etc/coturn/key.pem no-sslv3 no-tlsv1 no-tlsv1_1 no-tlsv1_2 backup: yes notify: Restart turn - name: /home/docker/turn.{{inventory_hostname}}/genpw.sh (generate Random PW for Turn) blockinfile: path: /home/docker/turn.{{inventory_hostname}}/genpw.sh create: yes mode: 0550 owner: root group: docker marker: "# {mark} ANSIBLE MANAGED BLOCK" block: | cd /home/docker/turn.{{inventory_hostname}} turn_secret=$(pwgen -s 32 1) turn_cli_secret=$(pwgen -s 32 1) [ -f env ] || echo "TURN_SECRET=!TURN_SECRET! TURN_CLI_SECRET=!TURN_CLI_SECRET! " >env chmod 440 env chown root:docker env sed -i "s/\!TURN_SECRET\!/$turn_secret/g" env sed -i "s/\!TURN_CLI_SECRET\!/$turn_cli_secret/g" env . ./env grep -q 'static-auth-secret=' coturn/turnserver.conf || echo "static-auth-secret=$TURN_SECRET" >>coturn/turnserver.conf grep -q 'cli-password=' coturn/turnserver.conf || echo "cli-password=$TURN_CLI_SECRET" >>coturn/turnserver.conf backup: yes validate: /bin/bash -n %s notify: run genpw.sh - name: /home/docker/turn.{{inventory_hostname}}/genpw.sh shebang lineinfile: path: /home/docker/turn.{{inventory_hostname}}/genpw.sh insertbefore: BOF line: "#!/bin/bash -e" - name: Gen initial passwords if not exists ansible.builtin.shell: ./genpw.sh args: chdir: /home/docker/turn.{{inventory_hostname}} creates: /home/docker/turn.{{inventory_hostname}}/env - name: /home/docker/turn.{{inventory_hostname}}/newip.sh (define external and local IP in turnserver.conf) blockinfile: path: /home/docker/turn.{{inventory_hostname}}/newip.sh create: yes mode: 0550 owner: root group: docker marker: "# {mark} ANSIBLE MANAGED BLOCK" block: | . /etc/bash/gaboshlib.include cd /home/docker/turn.{{inventory_hostname}}/coturn #local_ip=$(ip route get 1 | grep " src " | head -n1 | cut -d" " -f7) #g_valid_ipv4 "$local_ip" || g_echo_error_exit "Invalid local_ip $local_ip" external_ip=$(curl -s https://checkipv4.dedyn.io) g_valid_ipv4 "$external_ip" || g_echo_error_exit "Invalid external_ip $external_ip" if ! grep -q "external-ip=$local_ip/$external_ip" turnserver.conf then sed -i '/^external-ip=.*/d' turnserver.conf #echo "external-ip=$local_ip/$external_ip" >>turnserver.conf echo "external-ip=$external_ip" >>turnserver.conf fi [ -f /home/docker/turn.{{inventory_hostname}}/docker-compose.yml ] && \ docker compose -f /home/docker/turn.{{inventory_hostname}}/docker-compose.yml restart exit 0 backup: yes validate: /bin/bash -n %s notify: run newip.sh - name: /home/docker/turn.{{inventory_hostname}}/newip.sh shebang lineinfile: path: /home/docker/turn.{{inventory_hostname}}/newip.sh insertbefore: BOF line: "#!/bin/bash -e" - name: Update external and local IP in turnserver.conf ansible.builtin.shell: ./newip.sh args: chdir: /home/docker/turn.{{inventory_hostname}} changed_when: false - name: /home/docker/turn.{{inventory_hostname}}/docker-compose.yml Container Configuration blockinfile: path: /home/docker/turn.{{inventory_hostname}}/docker-compose.yml create: yes mode: 0440 owner: root group: docker marker: "# {mark} ANSIBLE MANAGED BLOCK" block: | version: '3.6' services: turn.{{inventory_hostname}}: image: coturn/coturn:latest restart: unless-stopped volumes: - /etc/localtime:/etc/localtime:ro - ./coturn:/etc/coturn ports: - 49160-49200:49160-49200/udp - 5349:5349 - 5349:5349/udp # Workaround for getting a letsencrypt-cert by traefik turn.{{inventory_hostname}}--ssl: image: nginx:latest restart: unless-stopped volumes: - ./htdocs:/usr/share/nginx/html:ro - /etc/localtime:/etc/localtime:ro networks: - traefik labels: - traefik.enable=true # HTTPS - traefik.http.routers.turn-{{ ansible_facts['hostname'] }}.rule=Host(`turn.{{inventory_hostname}}`) - traefik.http.routers.turn-{{ ansible_facts['hostname'] }}.entrypoints=https - traefik.http.routers.turn-{{ ansible_facts['hostname'] }}.tls=true # Proxy to service-port - traefik.http.services.turn-{{ ansible_facts['hostname'] }}.loadbalancer.server.port=80 - traefik.http.routers.turn-{{ ansible_facts['hostname'] }}.service=turn-{{ ansible_facts['hostname'] }} # cert via letsencrypt - traefik.http.routers.turn-{{ ansible_facts['hostname'] }}.tls.certresolver=letsencrypt # activate secHeaders@file - traefik.http.routers.turn-{{ ansible_facts['hostname'] }}.middlewares=secHeaders@file # Traefik network - traefik.docker.network=traefik networks: traefik: external: true notify: Restart turn - name: /usr/local/sbin/autoupdate.d/turn.update (workaround for valid ssl-certs) blockinfile: path: /usr/local/sbin/autoupdate.d/turn.update mode: "0400" owner: root group: root create: yes marker: "# {mark} ANSIBLE MANAGED BLOCK" block: | # take letsencrypt-certs from traefik cd /home/docker/turn.{{inventory_hostname}}/coturn # cleanup rm -f key.pem cert.pem touch key.pem cert.pem chown nobody key.pem cert.pem chmod 400 key.pem cert.pem # run ssl-container docker compose -f /home/docker/turn.{{inventory_hostname}}/docker-compose.yml up turn.{{inventory_hostname}}--ssl -d # get cert function getcert { cat /home/docker/traefik/letsencrypt/acme.json | jq -r ".letsencrypt.Certificates[] | select(.domain.main==\"turn.{{inventory_hostname}}\") | .certificate" | base64 -d >cert.pem } function getkey { cat /home/docker/traefik/letsencrypt/acme.json | jq -r ".letsencrypt.Certificates[] | select(.domain.main==\"turn.{{inventory_hostname}}\") | .key" | base64 -d >key.pem } getkey getcert until [ -s cert.pem ] do getcert sleep 31 done until [ -s key.pem ] do getkey sleep 32 done docker compose -f /home/docker/turn.{{inventory_hostname}}/docker-compose.yml up -d --force-recreate backup: yes validate: /bin/bash -n %s notify: run turn.update - name: Allow turn for audio/video 5349/tcp community.general.ufw: rule: allow port: '5349' proto: tcp - name: Allow turn for audio/video 5349/udp community.general.ufw: rule: allow port: '5349' proto: udp - name: Allow turn for audio/video 49160-49200/udp community.general.ufw: rule: allow port: '49160:49200' proto: udp handlers: - name: run genpw.sh ansible.builtin.shell: ./genpw.sh args: chdir: /home/docker/turn.{{inventory_hostname}} notify: Restart turn - name: run newip.sh ansible.builtin.shell: ./newip.sh args: chdir: /home/docker/turn.{{inventory_hostname}} notify: Restart turn - name: run turn.update ansible.builtin.shell: bash /usr/local/sbin/autoupdate.d/turn.update notify: Restart turn - name: Restart turn ansible.builtin.shell: docker-compose up -d --force-recreate args: chdir: /home/docker/turn.{{inventory_hostname}}