This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| computing:hpb-talk [2026/10/10 00:53] – oemb1905 | computing:hpb-talk [2026/10/10 05:21] (current) – oemb1905 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ------------------------------------------- | ||
| + | * **talk-hpb** | ||
| + | * **Jonathan Haack** | ||
| + | * **Haack' | ||
| + | * **webmaster@haacksnetworking.org** | ||
| + | ------------------------------------------- | ||
| + | //Talk HPB// | ||
| - | # Nextcloud Talk HPB (aio-talk) — Rootless Podman Quadlet | + | ------------------------------------------- |
| + | ~~NOTOC~~ | ||
| - | Rootless Podman as user `worker` on host `support`. Apache + Let's Encrypt run as `root`. Signaling is bound to localhost only. TURN is public. | + | ==== Introduction ==== |
| - | | Role | Bind | Public | | + | 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: |
| - | | --- | --- | --- | | + | |
| - | | Signaling | `127.0.0.1: | + | |
| - | | TURN | `0.0.0.0: | + | |
| - | Image: `ghcr.io/ | + | ^ Role ^ Bind ^ Public ^ |
| - | One container: | + | | Signaling | '' |
| - | The image rewrites `/conf/signaling.conf` on every start from `NC_DOMAIN` only. Extra Nextcloud backends must be re-added after every start. Do not mount `/conf`. | + | | TURN | '' |
| - | Do not use `podman generate systemd`. Units come from Quadlet files in `~/ | + | We will use the following image: |
| - | --- | + | * Image: '' |
| - | ## 0. Host firewall (root) | + | This image is basically signaling, NATS, Janus, and eturnal. Let's make sure the host is setup properly. |
| - | `3478/tcp` and `3478/udp` must be reachable from clients. Signaling stays on localhost. | + | ==== 0. Host firewall (root) ==== |
| - | ```bash | + | 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/tcp | ||
| ufw allow 3478/udp | ufw allow 3478/udp | ||
| - | ``` | + | </ |
| - | DNS: `talk.haacksnetworking.org` A/AAAA → this host. | + | ==== 1. Directories and secrets (worker) |
| - | + | < | |
| - | --- | + | |
| - | + | ||
| - | ## 1. Directories and secrets (worker) | + | |
| - | + | ||
| - | ```bash | + | |
| mkdir -p ~/talk-hpb | mkdir -p ~/talk-hpb | ||
| umask 077 | umask 077 | ||
| Line 41: | Line 43: | ||
| openssl rand -hex 32 > ~/ | openssl rand -hex 32 > ~/ | ||
| openssl rand -hex 32 > ~/ | openssl rand -hex 32 > ~/ | ||
| - | ``` | + | </ |
| - | + | ||
| - | Do not rotate these after Nextcloud has them. Update every Nextcloud that uses them if you do. | + | |
| - | + | ||
| - | Placeholders used below: | + | |
| - | + | ||
| - | ``` | + | |
| - | SIGNALING_SECRET=replace-with-your-signaling-secret | + | |
| - | TURN_SECRET=replace-with-your-turn-secret | + | |
| - | INTERNAL_SECRET=replace-with-your-internal-secret | + | |
| - | ``` | + | |
| - | + | ||
| - | --- | + | |
| - | ## 2. Quadlet | + | 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. |
| - | File: `~/.config/ | + | ==== 2. Quadlet ==== |
| - | ```bash | + | Create the quadlet for monitoring and starting/ |
| - | systemctl --user disable --now container-talk-hpb.service 2>/ | + | |
| - | rm -f ~/ | + | |
| - | podman rm -f talk-hpb | + | |
| + | < | ||
| mkdir -p ~/ | mkdir -p ~/ | ||
| cat > ~/ | cat > ~/ | ||
| Line 92: | Line 80: | ||
| systemctl --user start container-talk-hpb.service | systemctl --user start container-talk-hpb.service | ||
| sleep 25 | sleep 25 | ||
| - | ``` | + | </ |
| - | `WantedBy=default.target` starts it. Do not `systemctl enable` a Quadlet unit. Do not `podman generate systemd`. | + | ==== 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: |
| - | ## 3. Extra Nextcloud backends (after every start) | + | < |
| - | + | ||
| - | `start.sh` writes only `backend-1` = `NC_DOMAIN`. For the other three hosts, patch the running file and reload signaling. Do not `podman restart` after the patch. A restart rewrites the file and drops the extra backends. | + | |
| - | + | ||
| - | ```bash | + | |
| podman exec talk-hpb sh -c ' | podman exec talk-hpb sh -c ' | ||
| printf " | printf " | ||
| Line 111: | Line 95: | ||
| podman exec talk-hpb sh -c 'kill $(ps | awk "/ | podman exec talk-hpb sh -c 'kill $(ps | awk "/ | ||
| podman exec talk-hpb grep -A5 ' | podman exec talk-hpb grep -A5 ' | ||
| - | ``` | + | </ |
| - | Expected: | + | When you run this, you get something like: |
| - | ``` | + | < |
| [backend] | [backend] | ||
| backends = backend-1, backend-2, backend-3, backend-4 | backends = backend-1, backend-2, backend-3, backend-4 | ||
| Line 130: | Line 114: | ||
| [backend-4] | [backend-4] | ||
| urls = https:// | urls = https:// | ||
| - | ``` | + | </ |
| - | --- | + | ==== 4. Verify ==== |
| - | ## 4. Verify | + | Once your back-ends are all specified, let's verify the service is healthy and the api endpoint is reachable: |
| - | ```bash | + | < |
| systemctl --user is-active container-talk-hpb.service | systemctl --user is-active container-talk-hpb.service | ||
| podman inspect talk-hpb --format ' | podman inspect talk-hpb --format ' | ||
| curl -sI http:// | curl -sI http:// | ||
| - | ``` | + | </ |
| - | Expect `active`, `cpus=2000000000`, `memory=4294967296`, and an HTTP response from the welcome endpoint. The image has its own `HEALTHCHECK`. Podman Desktop shows that status. The other containers do not, because their images do not define one. | + | We should see something like '' |
| - | --- | + | ==== 5. Upgrade script ==== |
| - | ## 5. Upgrade | + | Let's create an upgrade |
| - | `/ | + | < |
| - | + | ||
| - | ```bash | + | |
| #!/bin/bash | #!/bin/bash | ||
| set -euo pipefail | set -euo pipefail | ||
| + | export XDG_RUNTIME_DIR=/ | ||
| + | export DBUS_SESSION_BUS_ADDRESS=unix: | ||
| podman pull ghcr.io/ | podman pull ghcr.io/ | ||
| Line 172: | Line 156: | ||
| curl -sI http:// | curl -sI http:// | ||
| - | ``` | + | </ |
| - | Run it as `worker`: | + | If your curl output is unhealthy, stop and debug before proceeding. |
| - | ```bash | + | ==== 6. Apache reverse proxy (root) ==== |
| - | su - worker -c '/ | + | |
| - | ``` | + | |
| - | Do not `sudo -u worker`. That drops the session bus. | + | 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 | ||
| + | </ | ||
| - | ## 6. Apache reverse proxy (root) | + | Inside '' |
| - | ```bash | + | < |
| - | a2enmod proxy proxy_http proxy_wstunnel headers rewrite ssl | + | |
| - | ``` | + | |
| - | + | ||
| - | `/ | + | |
| - | + | ||
| - | ```apache | + | |
| < | < | ||
| ServerName talk.haacksnetworking.org | ServerName talk.haacksnetworking.org | ||
| Line 198: | Line 177: | ||
| RewriteRule ^ https:// | RewriteRule ^ https:// | ||
| </ | </ | ||
| + | </ | ||
| + | |||
| + | And, inside the TLS virtual host, '' | ||
| + | < | ||
| < | < | ||
| ServerName talk.haacksnetworking.org | ServerName talk.haacksnetworking.org | ||
| ServerAdmin support@haacksnetworking.org | ServerAdmin support@haacksnetworking.org | ||
| SSLEngine on | SSLEngine on | ||
| - | SSLCertificateFile | + | SSLCertificateFile / |
| - | SSLCertificateKeyFile | + | SSLCertificateKeyFile / |
| Include / | Include / | ||
| ProxyPreserveHost On | ProxyPreserveHost On | ||
| Line 213: | Line 196: | ||
| RewriteCond %{HTTP: | RewriteCond %{HTTP: | ||
| RewriteRule ^/?(.*) ws:// | RewriteRule ^/?(.*) ws:// | ||
| - | ProxyPass | + | ProxyPass / http:// |
| ProxyPassReverse / http:// | ProxyPassReverse / http:// | ||
| - | ErrorLog | + | ErrorLog ${APACHE_LOG_DIR}/ |
| CustomLog ${APACHE_LOG_DIR}/ | CustomLog ${APACHE_LOG_DIR}/ | ||
| </ | </ | ||
| - | ``` | + | </ |
| - | ```bash | + | Once the virtual hosts are built, let's enable it, check the config, and then check the endpoint. |
| + | |||
| + | < | ||
| a2ensite talk.haacksnetworking.org.conf | a2ensite talk.haacksnetworking.org.conf | ||
| apache2ctl configtest && systemctl reload apache2 | apache2ctl configtest && systemctl reload apache2 | ||
| curl -sI http:// | curl -sI http:// | ||
| curl -sI https:// | curl -sI https:// | ||
| - | ``` | + | </code> |
| - | + | ||
| - | Clients use `wss:// | + | |
| - | --- | + | Check your output and make sure everything is accessible and running. If not, debug until it works. FYI, the endpoint for clients is '' |
| + | --- // | ||