-------------------------------------------
* **talk-hpb**
* **Jonathan Haack**
* **Haack's Networking**
* **webmaster@haacksnetworking.org**
-------------------------------------------
//Talk HPB//
-------------------------------------------
~~NOTOC~~
==== Introduction ====
This tutorial is for Debian users who want or need to spin up a high performance back-end for Nextcloud Talk. This helps with multi-user calls and/or nasty NAT situations. Here's the layout:
^ Role ^ Bind ^ Public ^
| Signaling | ''127.0.0.1:8088'' → container ''8081'' | ''https://talk.haacksnetworking.org'' (Apache) |
| TURN | ''0.0.0.0:3478/tcp'' + ''3478/udp'' | ''talk.haacksnetworking.org:3478'' |
We will use the following image:
* Image: ''ghcr.io/nextcloud-releases/aio-talk:latest''
This image is basically signaling, NATS, Janus, and eturnal. Let's make sure the host is setup properly.
==== 0. Host firewall (root) ====
We need to open turn on udp 3478 and its fallback, tcp 3478. This helps clients behind nasty NAT. The signaling stays on localhost. Let's open the ports:
ufw allow 3478/tcp
ufw allow 3478/udp
==== 1. Directories and secrets (worker) ====
mkdir -p ~/talk-hpb
umask 077
openssl rand -hex 32 > ~/talk-hpb/signaling.secret
openssl rand -hex 32 > ~/talk-hpb/turn.secret
openssl rand -hex 32 > ~/talk-hpb/internal.secret
Keep these stable for yearly or longer rotations. No need to rotate if no compromise is suspected, etc., and usage is tightly monitored and restricted.
==== 2. Quadlet ====
Create the quadlet for monitoring and starting/stopping the service as the ''worker'' user ''nano ~/.config/containers/systemd/container-talk-hpb.container''
mkdir -p ~/.config/containers/systemd
cat > ~/.config/containers/systemd/container-talk-hpb.container << 'EOF'
[Container]
ContainerName=talk-hpb
Image=ghcr.io/nextcloud-releases/aio-talk:latest
PublishPort=127.0.0.1:8088:8081
PublishPort=3478:3478/tcp
PublishPort=3478:3478/udp
Environment=NC_DOMAIN=cloud.haacksnetworking.org
Environment=TALK_HOST=talk.haacksnetworking.org
Environment=TALK_PORT=3478
Environment=TZ=America/Denver
Environment=TURN_SECRET=replace-with-your-turn-secret
Environment=SIGNALING_SECRET=replace-with-your-signaling-secret
Environment=INTERNAL_SECRET=replace-with-your-internal-secret
Environment=SKIP_CERT_VERIFY=false
PodmanArgs=--init --cpus=2 --memory=4g
[Service]
Restart=always
TimeoutStopSec=120
[Install]
WantedBy=default.target
EOF
systemctl --user daemon-reload
systemctl --user reset-failed container-talk-hpb.service
systemctl --user start container-talk-hpb.service
sleep 25
==== 3. Extra Nextcloud backends (after every start) ====
The HPB container can only be built with one endpoint when it is updated, so the following is needed to add xx amount of endpoints to use the HPB with:
podman exec talk-hpb sh -c '
printf "\n[backend-2]\nurls = https://cloud.gnulinux.vip\nsecret = replace-with-your-signaling-secret\nmaxstreambitrate = 1048576\nmaxscreenbitrate = 2097152\n" >> /conf/signaling.conf
printf "\n[backend-3]\nurls = https://inside.outsidebox.club\nsecret = replace-with-your-signaling-secret\nmaxstreambitrate = 1048576\nmaxscreenbitrate = 2097152\n" >> /conf/signaling.conf
printf "\n[backend-4]\nurls = https://cloud.friend.info\nsecret = replace-with-your-signaling-secret\nmaxstreambitrate = 1048576\nmaxscreenbitrate = 2097152\n" >> /conf/signaling.conf
sed -i "s/backends = backend-1/backends = backend-1, backend-2, backend-3, backend-4/" /conf/signaling.conf
'
podman exec talk-hpb sh -c 'kill $(ps | awk "/nextcloud-spreed-signaling|[s]ignaling/{print \$1; exit}")'
podman exec talk-hpb grep -A5 '^\[backend' /conf/signaling.conf
When you run this, you get something like:
[backend]
backends = backend-1, backend-2, backend-3, backend-4
...
[backend-1]
urls = https://cloud.haacksnetworking.org
...
[backend-2]
urls = https://cloud.gnulinux.vip
...
[backend-3]
urls = https://inside.outsidebox.club
...
[backend-4]
urls = https://cloud.friend.info
==== 4. Verify ====
Once your back-ends are all specified, let's verify the service is healthy and the api endpoint is reachable:
systemctl --user is-active container-talk-hpb.service
podman inspect talk-hpb --format '{{.Name}} cpus={{.HostConfig.NanoCpus}} memory={{.HostConfig.Memory}}'
curl -sI http://127.0.0.1:8088/standalone-signaling/api/v1/welcome
We should see something like ''active'', ''cpus=2000000000'', ''memory=4294967296'', and an HTTP response from the welcome endpoint.
==== 5. Upgrade script ====
Let's create an upgrade script at ''nano /usr/local/bin/upgrade-high-performance.sh''. Inside it, let's put something like this:
#!/bin/bash
set -euo pipefail
export XDG_RUNTIME_DIR=/run/user/$(id -u)
export DBUS_SESSION_BUS_ADDRESS=unix:path=${XDG_RUNTIME_DIR}/bus
podman pull ghcr.io/nextcloud-releases/aio-talk:latest
systemctl --user stop container-talk-hpb.service
systemctl --user daemon-reload
systemctl --user reset-failed container-talk-hpb.service
systemctl --user start container-talk-hpb.service
sleep 25
podman exec talk-hpb sh -c '
printf "\n[backend-2]\nurls = https://cloud.gnulinux.vip\nsecret = replace-with-your-signaling-secret\nmaxstreambitrate = 1048576\nmaxscreenbitrate = 2097152\n" >> /conf/signaling.conf
printf "\n[backend-3]\nurls = https://inside.outsidebox.club\nsecret = replace-with-your-signaling-secret\nmaxstreambitrate = 1048576\nmaxscreenbitrate = 2097152\n" >> /conf/signaling.conf
printf "\n[backend-4]\nurls = https://cloud.friend.info\nsecret = replace-with-your-signaling-secret\nmaxstreambitrate = 1048576\nmaxscreenbitrate = 2097152\n" >> /conf/signaling.conf
sed -i "s/backends = backend-1/backends = backend-1, backend-2, backend-3, backend-4/" /conf/signaling.conf
'
podman exec talk-hpb sh -c 'kill $(ps | awk "/nextcloud-spreed-signaling|[s]ignaling/{print \$1; exit}")'
curl -sI http://127.0.0.1:8088/standalone-signaling/api/v1/welcome
If your curl output is unhealthy, stop and debug before proceeding.
==== 6. Apache reverse proxy (root) ====
We can now setup our reverse proxy and associated virtual hosts and Let's Encrypt cert:
sudo a2enmod proxy proxy_http proxy_wstunnel headers rewrite ssl authz_host
sudo certbot certonly --apache -d talk.haacksnetworking.org
Inside ''nano /etc/apache2/sites-available/talk.haacksnetworking.org.conf'' let's put something like:
ServerName talk.haacksnetworking.org
RewriteEngine On
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
And, inside the TLS virtual host, ''nano /etc/apache2/sites-available/talk.haacksnetworking.org-ssl.conf'' let's drop something like:
ServerName talk.haacksnetworking.org
ServerAdmin support@haacksnetworking.org
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/talk.haacksnetworking.org/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/talk.haacksnetworking.org/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
ProxyPreserveHost On
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"
RewriteEngine On
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule ^/?(.*) ws://127.0.0.1:8088/$1 [P,L]
ProxyPass / http://127.0.0.1:8088/
ProxyPassReverse / http://127.0.0.1:8088/
ErrorLog ${APACHE_LOG_DIR}/talk.haacksnetworking.org-error.log
CustomLog ${APACHE_LOG_DIR}/talk.haacksnetworking.org-access.log combined
Once the virtual hosts are built, let's enable it, check the config, and then check the endpoint.
a2ensite talk.haacksnetworking.org.conf
apache2ctl configtest && systemctl reload apache2
curl -sI http://talk.haacksnetworking.org/
curl -sI https://talk.haacksnetworking.org/
Check your output and make sure everything is accessible and running. If not, debug until it works. FYI, the endpoint for clients is ''wss://talk.haacksnetworking.org/spreed''. More updates if/when rebuilds are done will be posted. Reach out on Matrix if you have questions.
--- //[[alerts@haacksnetworking.org|oemb1905]] 2026/10/10 05:16//