You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
Go to file
Joachim Bauch e4f7fc3020
Merge pull request #451 from strukturag/dependabot/github_actions/coverallsapp/github-action-2.0.0
build(deps): Bump coverallsapp/github-action from 1.2.4 to 2.0.0
2 weeks ago
.github build(deps): Bump coverallsapp/github-action from 1.2.4 to 2.0.0 2 weeks ago
client Add hello version "2.0" that authenticates connections using a JWT. 8 months ago
dist/init/systemd remove @resources from SystemCallFilter 7 months ago
docker docker: Don't rely on default values when updating TURN settings. 4 weeks ago
docs Merge pull request #390 from strukturag/dependabot/pip/docs/sphinx-6.1.3 1 month ago
proxy Add common code to handle allowed IPs. 2 weeks ago
scripts Fix issues reported by revive. 1 year ago
server Allow configuring backends through etcd. 9 months ago
.dockerignore Add official docker images. 8 months ago
.gitignore Add initial clustering support. 9 months ago
.golangci.yml CI: Ignore "error-strings" for revive linter. 1 year ago
.readthedocs.yaml CI: Pin dependencies to fix readthedocs build. 1 year ago
CHANGELOG.md Update changelog for 1.1.2 3 weeks ago
LICENSE Initial commit of the OpenSource version. 3 years ago
Makefile tarball: Copy more "google.golang.org/protobuf" modules to vendor. 3 weeks ago
README.md No longer support Golang 1.17. 1 month ago
allowed_ips.go Add common code to handle allowed IPs. 2 weeks ago
allowed_ips_test.go Add common code to handle allowed IPs. 2 weeks ago
api_async.go Send initial user flags to internal sessions asynchronously. 9 months ago
api_backend.go Implement switchto messages. 2 months ago
api_backend_test.go Switch dependency tracking to Go modules. 2 years ago
api_grpc.go Allow configuring GRPC targets through etcd. 9 months ago
api_proxy.go Add hello version "2.0" that authenticates connections using a JWT. 8 months ago
api_signaling.go Allow internal clients to set / change the "inCall" flags. 1 month ago
api_signaling_test.go Add hello version "2.0" that authenticates connections using a JWT. 8 months ago
async_events.go Trigger "joined" events through async messages. 9 months ago
async_events_nats.go Use empty struct for close channel. 1 month ago
async_events_test.go Refactor asynchronous events to central location. 9 months ago
backend_client.go Improve handling of throttled responses from Nextcloud. 2 months ago
backend_client_test.go Improve handling of throttled responses from Nextcloud. 2 months ago
backend_configuration.go Implement per-backend session limit for clusters. 9 months ago
backend_configuration_stats_prometheus.go Add more metrics on rooms / sessions / backends. 2 years ago
backend_configuration_test.go Allow configuring backends through etcd. 9 months ago
backend_server.go Add common code to handle allowed IPs. 2 weeks ago
backend_server_test.go stats: Support configuring subnets for allowed IPs. 2 weeks ago
backend_storage_etcd.go Implement per-backend session limit for clusters. 9 months ago
backend_storage_static.go Implement per-backend session limit for clusters. 9 months ago
backoff.go Add helper to wait with exponential backoff. 9 months ago
backoff_test.go Add helper to wait with exponential backoff. 9 months ago
capabilities.go Update capabilities if no hello v2 token key is found in cache. 8 months ago
capabilities_test.go Update capabilities if no hello v2 token key is found in cache. 8 months ago
certificate_reloader.go Add certificate reloader class. 9 months ago
certificate_reloader_test.go Add certificate reloader class. 9 months ago
channel_waiter.go Add helper class for channel waiters. 1 month ago
channel_waiter_test.go Add helper class for channel waiters. 1 month ago
client.go Use interface for client callbacks. 1 month ago
client_stats_prometheus.go Add more metrics on rooms / sessions / backends. 2 years ago
clientsession.go Migrate to channel waiter helper class. 1 month ago
clientsession_test.go Allow internal clients to set / change the "inCall" flags. 1 month ago
closer.go Add helper class to handle close channels. 1 month ago
closer_test.go Add helper class to handle close channels. 1 month ago
concurrentmap.go Switch dependency tracking to Go modules. 2 years ago
concurrentmap_test.go Switch dependency tracking to Go modules. 2 years ago
continentmap.go Fix issues reported by revive. 1 year ago
deferred_executor.go Simplify stopping of deferred executor. 1 month ago
deferred_executor_test.go Simplify stopping of deferred executor. 1 month ago
etcd_client.go etcd: Fix race in initialized event. 9 months ago
etcd_client_test.go etcd: Fix race in initialized event. 9 months ago
geoip.go Stop using deprecated ioutil package. 1 year ago
geoip_test.go Stop using deprecated ioutil package. 1 year ago
gnatsd.conf Initial commit of the OpenSource version. 3 years ago
go.mod build(deps): Bump google.golang.org/protobuf from 1.29.1 to 1.30.0 2 weeks ago
go.sum build(deps): Bump google.golang.org/protobuf from 1.29.1 to 1.30.0 2 weeks ago
grpc_backend.proto Implement per-backend session limit for clusters. 9 months ago
grpc_client.go Implement per-backend session limit for clusters. 9 months ago
grpc_client_test.go Test: add timeout while waiting for etcd event. 2 months ago
grpc_common.go grpc: Always use reloadable credentials. 9 months ago
grpc_common_test.go Make sure replaced files have different modification times. 9 months ago
grpc_internal.proto grpc: Automatically detect if a target is the current server itself. 9 months ago
grpc_mcu.proto Add initial clustering support. 9 months ago
grpc_server.go Implement per-backend session limit for clusters. 9 months ago
grpc_server_test.go Make sure replaced files have different modification times. 9 months ago
grpc_sessions.proto Disconnect sessions with the same room session id synchronously. 9 months ago
grpc_stats_prometheus.go Add metrics for GRPC calls. 9 months ago
http_client_pool.go Use proxy from environment for backend client requests. 7 months ago
http_client_pool_test.go Move capabilities handling to own file and refactor http client pool. 11 months ago
hub.go Use interface for client callbacks. 1 month ago
hub_stats_prometheus.go Add more metrics on rooms / sessions / backends. 2 years ago
hub_test.go Allow internal clients to set / change the "inCall" flags. 1 month ago
janus_client.go Migrate to closer helper class. 1 month ago
lru.go Switch dependency tracking to Go modules. 2 years ago
lru_test.go Switch dependency tracking to Go modules. 2 years ago
mcu_common.go Add specific ID for connections 11 months ago
mcu_common_test.go Lint prometheus stats. 2 years ago
mcu_janus.go Support toggling audio/video in subscribed streams. 11 months ago
mcu_janus_test.go Lint prometheus stats. 2 years ago
mcu_proxy.go Migrate to channel waiter helper class. 1 month ago
mcu_proxy_test.go Update tests for new continent map. 1 year ago
mcu_stats_prometheus.go Also track subscriber streams by type. 2 years ago
mcu_test.go Fix handling of "unshareScreen" messages and add test. 9 months ago
mkdocs.yml Add documentation on the available metrics. 1 year ago
mock_data_test.go Check individual audio/video permissions on change. 1 year ago
natsclient.go Refactor asynchronous events to central location. 9 months ago
natsclient_loopback.go Remove unnecessary variable to flag closed loopback client. 1 month ago
natsclient_loopback_test.go Run function to test for goroutine leaks as subtest. 2 months ago
natsclient_test.go Run function to test for goroutine leaks as subtest. 2 months ago
notifier.go Use simpler implementation without Context for notifier. 1 month ago
notifier_test.go Support multiple waiters for the same key. 2 years ago
proxy.conf.in Move etcd configuration to common section. 9 months ago
room.go Migrate to closer helper class. 1 month ago
room_ping.go Migrate to closer helper class. 1 month ago
room_ping_test.go Allow configuring backends through etcd. 9 months ago
room_stats_prometheus.go Add more metrics on rooms / sessions / backends. 2 years ago
room_test.go Refactor asynchronous events to central location. 9 months ago
roomsessions.go Disconnect sessions with the same room session id synchronously. 9 months ago
roomsessions_builtin.go Disconnect sessions with the same room session id synchronously. 9 months ago
roomsessions_builtin_test.go Add initial clustering support. 9 months ago
roomsessions_test.go Fix various issues found by golangci-lint. 2 years ago
server.conf.in grpc: Reload certificate if file has changed and support mutual authentication. 9 months ago
session.go Add "permission" for sessions that may not receive display names. 11 months ago
session_test.go Mark functions as test helpers. 2 months ago
single_notifier.go Use simpler implementation without Context for notifier. 1 month ago
single_notifier_test.go Add SingleNotifier class. 9 months ago
stats_prometheus.go Add prometheus metrics. 2 years ago
stats_prometheus_test.go Add more metrics on rooms / sessions / backends. 2 years ago
syscallconn.go Explicitly use type "sysConn". 2 months ago
testclient_test.go Allow internal clients to set / change the "inCall" flags. 1 month ago
testutils_test.go Test: log number of active read/write pumps in case of error. 2 months ago
transient_data.go Add API for transient room data. 1 year ago
transient_data_test.go Also return in-order list of "join" events. 12 months ago
vendor_helper_test.go vendor: Automatically vendor protobuf modules. 8 months ago
virtualsession.go Allow internal clients to set / change the "inCall" flags. 1 month ago
virtualsession_test.go Allow internal clients to set / change the "inCall" flags. 1 month ago

README.md

Spreed standalone signaling server

Build Status Coverage Status Documentation Status Go Report

This repository contains the standalone signaling server which can be used for Nextcloud Talk (https://apps.nextcloud.com/apps/spreed).

See https://nextcloud-spreed-signaling.readthedocs.io/en/latest/ for further information on the API of the signaling server.

Building

The following tools are required for building the signaling server.

  • git
  • go >= 1.18 (usually the last three versions of go are supported)
  • make
  • protobuf-compiler >= 3

All other dependencies are fetched automatically while building.

$ make build

or on FreeBSD

$ gmake build

Afterwards the binary is created as bin/signaling.

Configuration

A default configuration file is included as server.conf.in. Copy this to server.conf and adjust as necessary for the local setup. See the file for comments about the different parameters that can be changed.

Running

The signaling server connects to a NATS server (https://nats.io/) to distribute messages between different instances. See the NATS documentation on how to set up a server and run it.

Once the NATS server is running (and the URL to it is configured for the signaling server), you can start the signaling server.

$ ./bin/signaling

By default, the configuration is loaded from server.conf in the current directory, but a different path can be passed through the --config option.

$ ./bin/signaling --config /etc/signaling/server.conf

Running as daemon

systemd

Create a dedicated group and user:

sudo groupadd --system signaling
sudo useradd --system \
    --gid signaling \
    --shell /usr/sbin/nologin \
    --comment "Standalone signaling server for Nextcloud Talk." \
    signaling

Copy server.conf.in to /etc/signaling/server.conf and fix permissions:

sudo chmod 600 /etc/signaling/server.conf
sudo chown signaling: /etc/signaling/server.conf

Copy dist/init/systemd/signaling.service to /etc/systemd/system/signaling.service (adjust abs. path in ExecStart to match your binary location!)

Enable and start service:

systemctl enable signaling.service
systemctl start signaling.service

Running with Docker

Official docker containers for the signaling server and -proxy are available on Docker Hub at https://hub.docker.com/r/strukturag/nextcloud-spreed-signaling

See the README.md in the docker subfolder for details.

Docker Compose

You will likely have to adjust the Janus command line options depending on the exact network configuration on your server. Refer to Setup of Janus and the Janus documentation for how to configure your Janus server.

Copy server.conf.in to server.conf and adjust it to your liking.

If you're using the docker-compose.yml configuration as is, the MCU Url must be set to ws://localhost:8188, the NATS Url must be set to nats://localhost:4222, and TURN Servers must be set to turn:localhost:3478?transport=udp,turn:localhost:3478?transport=tcp.

docker-compose build
docker-compose up -d

Please note that docker-compose v2 is required for building while most distributions will ship older versions. You can download a recent version from https://docs.docker.com/compose/install/

Setup of NATS server

There is a detailed description on how to install and run the NATS server available at http://nats.io/documentation/tutorials/gnatsd-install/

You can use the gnatsd.conf file as base for the configuration of the NATS server.

Setup of Janus

A Janus server (from https://github.com/meetecho/janus-gateway) can be used to act as a WebRTC gateway. See the documentation of Janus on how to configure and run the server. At least the VideoRoom plugin and the websocket transport of Janus must be enabled.

The signaling server uses the VideoRoom plugin of Janus to manage sessions. All gateway details are hidden from the clients, all messages are sent through the signaling server. Only WebRTC media is exchanged directly between the gateway and the clients.

Edit the server.conf and enter the URL to the websocket endpoint of Janus in the section [mcu] and key url. During startup, the signaling server will connect to Janus and log information of the gateway.

The maximum bandwidth per publishing stream can also be configured in the section [mcu], see properties maxstreambitrate and maxscreenbitrate.

Use multiple Janus servers

To scale the setup and add high availability, a signaling server can connect to one or multiple proxy servers that each provide access to a single Janus server.

For that, set the type key in section [mcu] to proxy and set url to a space-separated list of URLs where a proxy server is running.

Each signaling server that connects to a proxy needs a unique token id and a public / private RSA keypair. The token id must be configured as token_id in section [mcu], the path to the private key file as token_key.

Setup of proxy server

The proxy server is built with the standard make command make build as bin/proxy binary. Copy the proxy.conf.in as proxy.conf and edit section [tokens] to the list of allowed token ids and filenames of the public keys for each token id. See the comments in proxy.conf.in for other configuration options.

When the proxy process receives a SIGHUP signal, the list of allowed token ids / public keys is reloaded. A SIGUSR1 signal can be used to shutdown a proxy process gracefully after all clients have been disconnected. No new publishers will be accepted in this case.

Clustering

The signaling server supports a clustering mode where multiple running servers can be interconnected to form a single "virtual" server. This can be used to increase the capacity of the signaling server or provide a failover setup.

For that a central NATS server / cluster must be used by all instances. Each instance must run a GRPC server (enable listening in section grpc and optionally setup certificate, private key and CA). The list of other GRPC targets must be configured as targets in section grpc or can be retrieved from an etcd cluster. See server.conf.in in section grpc for configuration details.

Setup of frontend webserver

Usually the standalone signaling server is running behind a webserver that does the SSL protocol or acts as a load balancer for multiple signaling servers.

The configuration examples below assume a pre-configured webserver (nginx or Apache) with a working HTTPS setup, that is listening on the external interface of the server hosting the standalone signaling server.

After everything has been set up, the configuration can be tested using curl:

$ curl -i https://myserver.domain.invalid/standalone-signaling/api/v1/welcome
HTTP/1.1 200 OK
Date: Thu, 05 Jul 2018 09:28:08 GMT
Server: nextcloud-spreed-signaling/1.0.0
Content-Type: application/json; charset=utf-8
Content-Length: 59

{"nextcloud-spreed-signaling":"Welcome","version":"1.0.0"}

nginx

Nginx can be used as frontend for the standalone signaling server without any additional requirements.

The backend should be configured separately so it can be changed in a single location and also to allow using multiple backends from a single frontend server.

Assuming the standalone signaling server is running on the local interface on port 8080 below, add the following block to the nginx server definition in /etc/nginx/sites-enabled (just before the server definition):

upstream signaling {
    server 127.0.0.1:8080;
}

To proxy all requests for the standalone signaling to the correct backend, the following location block must be added inside the server definition of the same file:

location /standalone-signaling/ {
    proxy_pass http://signaling/;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

location /standalone-signaling/spreed {
    proxy_pass http://signaling/spreed;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

Example (e.g. /etc/nginx/sites-enabled/default):

upstream signaling {
    server 127.0.0.1:8080;
}

server {
    listen 443 ssl http2;
    server_name myserver.domain.invalid;

    # ... other existing configuration ...

    location /standalone-signaling/ {
        proxy_pass http://signaling/;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location /standalone-signaling/spreed {
        proxy_pass http://signaling/spreed;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Apache

To configure the Apache webservice as frontend for the standalone signaling server, the modules mod_proxy_http and mod_proxy_wstunnel must be enabled so WebSocket and API backend requests can be proxied:

$ sudo a2enmod proxy
$ sudo a2enmod proxy_http
$ sudo a2enmod proxy_wstunnel

Now the Apache VirtualHost configuration can be extended to forward requests to the standalone signaling server (assuming the server is running on the local interface on port 8080 below):

<VirtualHost *:443>

    # ... existing configuration ...

    # Enable proxying Websocket requests to the standalone signaling server.
    ProxyPass "/standalone-signaling/"  "ws://127.0.0.1:8080/"

    RewriteEngine On
    # Websocket connections from the clients.
    RewriteRule ^/standalone-signaling/spreed/$ - [L]
    # Backend connections from Nextcloud.
    RewriteRule ^/standalone-signaling/api/(.*) http://127.0.0.1:8080/api/$1 [L,P]

    # ... existing configuration ...

</VirtualHost>

Caddy

v1

Caddy (v1) configuration:

myserver.domain.invalid {
  proxy /standalone-signaling/ http://127.0.0.1:8080 {
    without /standalone-signaling
    transparent
    websocket
  }
}

v2

Caddy (v2) configuration:

myserver.domain.invalid {
  route /standalone-signaling/* {
    uri strip_prefix /standalone-signaling
    reverse_proxy http://127.0.0.1:8080
  }
}

Setup of Nextcloud Talk

Login to your Nextcloud as admin and open the additional settings page. Scroll down to the "Talk" section and enter the base URL of your standalone signaling server in the field "External signaling server". Please note that you have to use https if your Nextcloud is also running on https. Usually you should enter https://myhostname/standalone-signaling as URL.

The value "Shared secret for external signaling server" must be the same as the property secret in section backend of your server.conf.

If you are using a self-signed certificate for development, you need to uncheck the box Validate SSL certificate so backend requests from Nextcloud to the signaling server can be performed.

Benchmarking the server

A simple client exists to benchmark the server. Please note that the features that are benchmarked might not cover the whole functionality, check the implementation in src/client for details on the client.

To authenticate new client connections to the signaling server, the client starts a dummy authentication handler on a local interface and passes the URL in the hello request. Therefore the signaling server should be configured to allow all backend hosts (option allowall in section backend).

The client is not compiled by default, but can be using the client target:

$ make client

Usage:

$ ./bin/client
Usage of ./bin/client:
  -addr string
        http service address (default "localhost:28080")
  -config string
        config file to use (default "server.conf")
  -maxClients int
        number of client connections (default 100)

Running multiple signaling servers

IMPORTANT: This is considered experimental and might not work with all functionality of the signaling server, especially when using the Janus integration.

The signaling server uses the NATS server to send messages to peers that are not connected locally. Therefore multiple signaling servers running on different hosts can use the same NATS server to build a simple cluster, allowing more simultaneous connections and distribute the load.

To set this up, make sure all signaling servers are using the same settings for their session keys and the secret in the backend section. Also the URL to the NATS server (option url in section nats) must point to the same NATS server.

If all this is setup correctly, clients can connect to either of the signaling servers and exchange messages between them.