Nextcloud Talk Signaling Server (WebSocket) Not Reachable Behind Nginx Proxy Manager – Host Offline with Custom Location

The Basics

Nextcloud Server version (e.g., 29.x.x):
Nextcloud Hub 10 (31.0.9)

Operating system and version (e.g., Ubuntu 24.04):
Debian 12 (host system)

Web server and version (e.g, Apache 2.4.25):
Nextcloud AIO integrated web server (uses Apache in container)

Reverse proxy and version (e.g. nginx 1.27.2):
Nginx Proxy Manager v2.12.6 (intern nginx version: openresty/1.27.1.2)

PHP version (e.g, 8.3):
PHP 8.3.25 (in Nextcloud AIO container)

Is this the first time you’ve seen this error? (Yes / No):
Yes

When did this problem seem to first start?
After initial setup of Nextcloud Talk behind Nginx Proxy Manager

Installation method (e.g. AlO, NCP, Bare Metal/Archive, etc.):
AIO (All-in-One Docker)

Are you using Cloudflare, mod_security, or similar? (Yes / No):
No


Summary of the issue you are facing:
Nextcloud Talk signaling server (/standalone-signaling/spreed) is not reachable from outside when running behind Nginx Proxy Manager.
Custom location blocks in Nginx Proxy Manager cause the proxy host to be marked as offline.
Without custom blocks, WebSocket upgrades for /standalone-signaling/spreed are not forwarded correctly.
The signaling server runs in the nextcloud-aio-talk container on port 8081, but this port cannot be configured directly in Proxy Manager.


Steps to replicate it (hint: details matter!):

  1. Install Nextcloud AIO on Debian 12 as Docker Image
  2. Set up Nginx Proxy Manager as reverse proxy, forwarding to Nextcloud AIO on port 11000.
  3. Enable “Websockets Support” in Nginx Proxy Manager.
  4. Try to use Nextcloud Talk from outside.
  5. Optionally, add a custom location block for /standalone-signaling/spreed in Nginx Proxy Manager (host will be marked offline).
  6. Without custom block, WebSocket connections to /standalone-signaling/spreed fail.

Log entries

Nextcloud
No relevant errors related to signaling server in Nextcloud logs.

Web Browser
WebSocket connection to /standalone-signaling/spreed fails (can provide browser console/network output if needed).


Web server / Reverse Proxy
No relevant errors in Nginx Proxy Manager logs. Can provide logs if needed.


Additionally:
My main concern is to ensure true end-to-end encryption (E2EE) for Nextcloud Talk.
Currently, all communication appears to be only transport-encrypted, and there is no indication in the Talk client, desktop app, or web interface that 1:1 chats and calls are protected by more than just transport encryption.

I would like to resolve this issue or at least understand why, despite having encryption enabled in the admin panel and all headers configured correctly, I do not have real E2EE.

If there are any additional steps required to activate or verify end-to-end encryption for 1:1 chats and calls in Nextcloud Talk, or if there are known limitations in the current setup (AIO behind Nginx Proxy Manager), I would appreciate any guidance or clarification.

Thank you!

I have now updated the Nginx .conf file to include the signaling server.
I am not sure if this was correct or if it could be the solution.
Apparently, with true end-to-end encryption, a lock icon should be shown in 1:1 chats in the Nextcloud Talk or Spreed web interface client.

Can anyone confirm this? It is not displayed for me! But I definitely want to use real end-to-end encryption.

Can someone tell me if I am approaching the problem correctly, or if I am completely mistaken?

My Nginx conf looks as follows:

[root@docker-Oo:/app]# cat /data/nginx/proxy_host/2.conf
# ------------------------------------------------------------
# Domain
# ------------------------------------------------------------



map $scheme $hsts_header {
    https   "max-age=63072000; preload";
}

server {
  set $forward_scheme http;
  set $server         "my.ip";
  set $port           11000;

  listen 80;
listen [::]:80;

listen 443 ssl;
listen [::]:443 ssl;


  server_my-domain;

  http2 on;


  # Let's Encrypt SSL
  include conf.d/include/letsencrypt-acme-challenge.conf;
  include conf.d/include/ssl-cache.conf;
  include conf.d/include/ssl-ciphers.conf;
  ssl_certificate /etc/letsencrypt/live/npm-5/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/npm-5/privkey.pem;






  # Block Exploits
  include conf.d/include/block-exploits.conf;







    # Force SSL
    include conf.d/include/force-ssl.conf;




proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_http_version 1.1;


  access_log /data/logs/proxy-host-2_access.log proxy;
  error_log /data/logs/proxy-host-2_error.log warn;







  location / {










    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $http_connection;
    proxy_http_version 1.1;


    # Proxy!
    include conf.d/include/proxy.conf;
  }


  location /standalone-signaling/spreed {

    proxy_pass http://my-ip:11000/standalone-signaling/spreed;

    proxy_http_version 1.1;

    proxy_set_header Upgrade $http_upgrade;

    proxy_set_header Connection "upgrade";

    proxy_set_header Host $host;

  }

  # Custom
  include /data/nginx/custom/server_proxy[.]conf;
}

:smirking_face::thinking:

Inserted was this section:

  location /standalone-signaling/spreed {

    proxy_pass http://my-ip:11000/standalone-signaling/spreed;

    proxy_http_version 1.1;

    proxy_set_header Upgrade $http_upgrade;

    proxy_set_header Connection "upgrade";

    proxy_set_header Host $host;

  }

I have now also tried to add the signaling server to the header in the nextcloud-aio-nextcloud container in /var/www/html/.htaccess.

What I added:

<IfModule mod_headers.c>
  <If "%{REQUEST_URI} =~ m#^/standalone-signaling/spreed#">
    Header always set Content-Security-Policy "default-src 'self'; connect-src 'self' wss://my.domain/standalone-signaling/spreed"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-Content-Type-Options "nosniff"
    Header always set Referrer-Policy "no-referrer"
  </If>
</IfModule>

Unfortunately, I still do not see a lock icon or any indication of real end-to-end encryption in the Talk client or Spreed. :confounded_face: I am stuck and don’t know what else to try.
Does anyone have a tip for me?