diff --git a/playbooks/linux/ubuntu-server/nextcloud_full_deployment/deploy_nc_talk_hpb.yml b/playbooks/linux/ubuntu-server/nextcloud_full_deployment/deploy_nc_talk_hpb.yml
index a1665bb..9f01c7b 100644
--- a/playbooks/linux/ubuntu-server/nextcloud_full_deployment/deploy_nc_talk_hpb.yml
+++ b/playbooks/linux/ubuntu-server/nextcloud_full_deployment/deploy_nc_talk_hpb.yml
@@ -1,5 +1,5 @@
- name: Temporary workaround for sudo-rs
- hosts: nextcloud
+ hosts: nextcloud_talk_hpb
gather_facts: false
become: false
tasks:
@@ -12,3 +12,394 @@
ansible.builtin.set_fact:
ansible_become_exe: "{{ 'sudo.ws' if sudo_ws_check.stdout | trim | length > 0 else 'sudo' }}"
+# ================================================================
+# PLAY 0 — Bootstrap: install acl BEFORE any become_user is used.
+# ================================================================
+- name: Bootstrap – ensure acl is installed
+ hosts: nextcloud_talk_hpb
+ gather_facts: true
+ become: true
+
+ tasks:
+ - name: Update apt cache
+ ansible.builtin.apt:
+ update_cache: true
+ cache_valid_time: 3600
+
+ - name: Install acl (required for Ansible become_user on Linux)
+ ansible.builtin.apt:
+ name: acl
+ state: present
+
+# ================================================================
+# PLAY 1 — Install Docker Engine and the Compose plugin
+# ================================================================
+- name: Install Docker
+ hosts: nextcloud_talk_hpb
+ gather_facts: true
+ become: true
+
+ tasks:
+ - name: Ensure the apt keyrings directory exists
+ ansible.builtin.file:
+ path: /etc/apt/keyrings
+ state: directory
+ mode: "0755"
+
+ - name: Download Docker GPG signing key
+ ansible.builtin.get_url:
+ url: https://download.docker.com/linux/ubuntu/gpg
+ dest: /etc/apt/keyrings/docker.asc
+ mode: "0644"
+
+ - name: Add Docker APT repository
+ ansible.builtin.deb822_repository:
+ name: docker
+ types: [deb]
+ uris: ["https://download.docker.com/linux/ubuntu"]
+ suites: ["{{ ansible_distribution_release }}"]
+ components: [stable]
+ signed_by: /etc/apt/keyrings/docker.asc
+ state: present
+
+ - name: Install Docker Engine and Compose plugin
+ ansible.builtin.apt:
+ name:
+ - docker-ce
+ - docker-ce-cli
+ - containerd.io
+ - docker-buildx-plugin
+ - docker-compose-plugin
+ state: present
+ update_cache: true
+
+ - name: Enable and start Docker service
+ ansible.builtin.systemd:
+ name: docker
+ enabled: true
+ state: started
+
+# ================================================================
+# PLAY 2 — Deploy the HPB stack: NATS, Janus Gateway, Signaling
+# ================================================================
+- name: Deploy Nextcloud Talk High-Performance Backend stack
+ hosts: nextcloud_talk_hpb
+ gather_facts: true
+ become: true
+
+ vars_files:
+ - vars/shared_vars.yml
+
+ tasks:
+ - name: Create HPB config directory structure
+ ansible.builtin.file:
+ path: "{{ item }}"
+ state: directory
+ mode: "0750"
+ loop:
+ - "{{ nc_talk_hpb_install_dir }}/config/janus"
+
+ - name: Deploy NATS configuration
+ ansible.builtin.copy:
+ dest: "{{ nc_talk_hpb_install_dir }}/config/nats.conf"
+ mode: "0640"
+ content: |
+ listen: 127.0.0.1:4222
+ notify: Restart HPB stack
+
+ - name: Deploy Janus main configuration
+ ansible.builtin.copy:
+ dest: "{{ nc_talk_hpb_install_dir }}/config/janus/janus.jcfg"
+ mode: "0640"
+ content: |
+ general: {
+ configs_folder = "/usr/local/etc/janus"
+ plugins_folder = "/usr/local/lib/janus/plugins"
+ transports_folder = "/usr/local/lib/janus/transports"
+ events_folder = "/usr/local/lib/janus/events"
+ loggers_folder = "/usr/local/lib/janus/loggers"
+ debug_level = 4
+ log_to_stdout = true
+ }
+
+ nat: {
+ ice_lite = false
+ ice_tcp = false
+ full_trickle = true
+ rtp_port_range = "{{ nc_talk_hpb_rtp_port_range }}"
+ }
+
+ media: {
+ ipv6 = false
+ }
+
+ plugins: {
+ }
+
+ transports: {
+ }
+ notify: Restart HPB stack
+
+ - name: Deploy Janus WebSocket transport configuration
+ ansible.builtin.copy:
+ dest: "{{ nc_talk_hpb_install_dir }}/config/janus/janus.transport.websockets.jcfg"
+ mode: "0640"
+ content: |
+ general: {
+ }
+
+ admin: {
+ admin_ws = true
+ admin_ws_port = 7188
+ }
+
+ ws: {
+ ws = true
+ ws_port = 8188
+ ws_interface = "127.0.0.1"
+ }
+
+ wss: {
+ wss = false
+ }
+ notify: Restart HPB stack
+
+ - name: Deploy Janus VideoRoom plugin configuration
+ ansible.builtin.copy:
+ dest: "{{ nc_talk_hpb_install_dir }}/config/janus/janus.plugin.videoroom.jcfg"
+ mode: "0640"
+ content: |
+ general: {
+ admin_key = "{{ nc_talk_hpb_janus_admin_key }}"
+ }
+ notify: Restart HPB stack
+
+ # NOTE: only nextcloud_domain is wired up as a backend here, matching
+ # the single-Nextcloud-instance scope of the rest of this playbook
+ # stack. To serve more Nextcloud instances from this HPB, add further
+ # backendN blocks below by hand and list them in [backend] backends -
+ # they must all share the same signaling secret.
+ - name: Deploy signaling server configuration
+ ansible.builtin.copy:
+ dest: "{{ nc_talk_hpb_install_dir }}/config/server.conf"
+ mode: "0640"
+ content: |
+ [http]
+ listen = 0.0.0.0:8081
+
+ [app]
+ secret = {{ nc_talk_hpb_signaling_secret }}
+
+ [sessions]
+ hashkey = {{ nc_talk_hpb_hash_key }}
+ blockkey = {{ nc_talk_hpb_block_key }}
+
+ [nats]
+ url = nats://127.0.0.1:4222
+
+ [mcu]
+ type = janus
+ url = ws://127.0.0.1:8188
+
+ [backend]
+ backends = backend1
+
+ [backend1]
+ url = https://{{ nextcloud_domain }}
+ secret = {{ nc_talk_hpb_signaling_secret }}
+
+ [turn]
+ api = static
+ secret = {{ nc_talk_hpb_turn_secret }}
+ servers = turn:{{ nc_talk_hpb_domain }}:3478?transport=udp,turn:{{ nc_talk_hpb_domain }}:3478?transport=tcp
+ notify: Restart HPB stack
+
+ - name: Deploy HPB Docker Compose stack definition
+ ansible.builtin.copy:
+ dest: "{{ nc_talk_hpb_install_dir }}/docker-compose.yml"
+ mode: "0640"
+ content: |
+ name: 'hpb'
+ services:
+ nats:
+ container_name: nats_server
+ image: nats:latest
+ command: ["-c", "/config/nats.conf"]
+ volumes:
+ - {{ nc_talk_hpb_install_dir }}/config/nats.conf:/config/nats.conf:ro
+ network_mode: host
+ restart: unless-stopped
+
+ janus:
+ container_name: janus_gateway
+ image: canyan/janus-gateway:latest
+ network_mode: host
+ environment:
+ - JANUS_API_HTTP=yes
+ - JANUS_API_HTTPS=no
+ - JANUS_API_WS=yes
+ - JANUS_API_ADMIN_WS=yes
+ - JANUS_RTP_PORT_RANGE={{ nc_talk_hpb_rtp_port_range }}
+ volumes:
+ - {{ nc_talk_hpb_install_dir }}/config/janus:/usr/local/etc/janus:ro
+ restart: unless-stopped
+
+ signaling:
+ container_name: spreed_signaling
+ image: strukturag/nextcloud-spreed-signaling:latest
+ depends_on:
+ - nats
+ - janus
+ network_mode: host
+ volumes:
+ - {{ nc_talk_hpb_install_dir }}/config/server.conf:/config/server.conf:ro
+ command: ["-config", "/config/server.conf"]
+ restart: unless-stopped
+ notify: Restart HPB stack
+
+ - name: Deploy HPB stack with Docker Compose
+ community.docker.docker_compose_v2:
+ project_src: "{{ nc_talk_hpb_install_dir }}"
+ state: present
+
+ # ---------------------------------------------------------------
+ # Handlers
+ # ---------------------------------------------------------------
+ handlers:
+ - name: Restart HPB stack
+ community.docker.docker_compose_v2:
+ project_src: "{{ nc_talk_hpb_install_dir }}"
+ state: restarted
+
+# ================================================================
+# PLAY 3 — Apache reverse proxy (TLS termination) and firewall
+# ================================================================
+- name: Configure Apache reverse proxy and firewall for Talk HPB
+ hosts: nextcloud_talk_hpb
+ gather_facts: true
+ become: true
+
+ vars_files:
+ - vars/shared_vars.yml
+
+ tasks:
+ - name: Generate self-signed TLS certificate (10-year validity)
+ ansible.builtin.command:
+ cmd: >
+ openssl req -x509 -nodes -days 3650
+ -newkey rsa:4096
+ -keyout {{ nc_talk_hpb_ssl_key }}
+ -out {{ nc_talk_hpb_ssl_cert }}
+ -subj "/CN={{ nc_talk_hpb_domain }}/O=Talk HPB/C=DE"
+ -addext "subjectAltName=DNS:{{ nc_talk_hpb_domain }}"
+ creates: "{{ nc_talk_hpb_ssl_key }}"
+
+ - name: Restrict private key permissions
+ ansible.builtin.file:
+ path: "{{ nc_talk_hpb_ssl_key }}"
+ owner: root
+ group: root
+ mode: "0600"
+
+ - name: Install apache2
+ ansible.builtin.apt:
+ name: apache2
+ state: present
+
+ - name: Enable required Apache modules
+ community.general.apache2_module:
+ name: "{{ item }}"
+ state: present
+ loop:
+ - proxy
+ - proxy_http
+ - proxy_wstunnel
+ - rewrite
+ - headers
+ - ssl
+ notify: Restart Apache
+
+ - name: Enable Apache service
+ ansible.builtin.systemd:
+ name: apache2
+ enabled: true
+ state: started
+
+ # NOTE: coolwsd-style TLS termination happens here in Apache; the
+ # signaling container listens on plain HTTP/WS on 127.0.0.1:8081
+ # (see server.conf's [http] listen), so the proxy targets ws/http,
+ # not wss/https.
+ - name: Deploy Talk HPB Apache virtual host (HTTP redirect + HTTPS proxy)
+ ansible.builtin.copy:
+ dest: /etc/apache2/sites-available/nc-talk-hpb.conf
+ mode: "0644"
+ content: |
+
+ ServerName {{ nc_talk_hpb_domain }}
+ RewriteEngine On
+ RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
+
+
+
+ ServerName {{ nc_talk_hpb_domain }}
+
+ SSLEngine on
+ SSLCertificateFile {{ nc_talk_hpb_ssl_cert }}
+ SSLCertificateKeyFile {{ nc_talk_hpb_ssl_key }}
+
+ ProxyPreserveHost On
+
+ RewriteEngine On
+ RewriteCond %{HTTP:Upgrade} =websocket [NC]
+ RewriteRule /standalone-signaling/(.*) ws://127.0.0.1:8081/$1 [P,L]
+
+ ProxyPass /standalone-signaling/ http://127.0.0.1:8081/
+ ProxyPassReverse /standalone-signaling/ http://127.0.0.1:8081/
+
+ ErrorLog ${APACHE_LOG_DIR}/nc_talk_hpb_error.log
+ CustomLog ${APACHE_LOG_DIR}/nc_talk_hpb_access.log combined
+
+ notify: Restart Apache
+
+ - name: Disable default Apache site
+ ansible.builtin.command: a2dissite 000-default
+ args:
+ removes: /etc/apache2/sites-enabled/000-default.conf
+ notify: Restart Apache
+
+ - name: Enable Talk HPB Apache site
+ ansible.builtin.command: a2ensite nc-talk-hpb
+ args:
+ creates: /etc/apache2/sites-enabled/nc-talk-hpb.conf
+ notify: Restart Apache
+
+ - name: Ensure ufw is installed
+ ansible.builtin.apt:
+ name: ufw
+ state: present
+
+ - name: Allow TURN/STUN port through the firewall
+ community.general.ufw:
+ rule: allow
+ port: "3478"
+ proto: "{{ item }}"
+ loop:
+ - tcp
+ - udp
+
+ - name: Allow RTP port range through the firewall
+ community.general.ufw:
+ rule: allow
+ port: "{{ nc_talk_hpb_rtp_port_range | replace('-', ':') }}"
+ proto: udp
+
+ # ---------------------------------------------------------------
+ # Handlers
+ # ---------------------------------------------------------------
+ handlers:
+ - name: Restart Apache
+ ansible.builtin.systemd:
+ name: apache2
+ state: restarted
+
+# This file was written by Ebbe Baß (umpi) - ebbe@ping-mee.de