Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 41 additions & 10 deletions .drone.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ local browser = "firefox";
local nextcloud = "32.0.5";
local redis = "7.0.15";
local nginx = "1.24.0";
local nats = "2.10";
local postgresql = "16-bullseye";
local platform = '25.09';
local python = '3.12-slim-bookworm';
local debian = 'bookworm-slim';
Expand All @@ -29,10 +31,10 @@ local build(arch, test_ui) = [{
]
},
{
name: "download",
image: "debian:" + debian,
name: "nextcloud",
image: "nextcloud:" + nextcloud + "-fpm",
commands: [
"./download.sh " + nextcloud
"./nextcloud/build.sh"
]
},
{
Expand Down Expand Up @@ -62,18 +64,47 @@ local build(arch, test_ui) = [{
commands: [
"./redis/test.sh"
]
},
{
name: "nats",
image: "debian:" + debian,
commands: [
"./nats/build.sh"
]
},
{
name: "nats test",
image: "syncloud/platform-" + distro_default + "-" + arch + ":" + platform,
commands: [
"./nats/test.sh"
]
},
{
name: "signaling",
image: "debian:" + debian,
commands: [
"./signaling/build.sh"
]
},
{
name: "signaling test",
image: "syncloud/platform-" + distro_default + "-" + arch + ":" + platform,
commands: [
"./signaling/test.sh"
]
},
{
name: "postgresql",
image: "docker:" + dind,
image: "postgres:" + postgresql,
commands: [
"./postgresql/build.sh"
],
volumes: [
{
name: "dockersock",
path: "/var/run"
}
]
},
{
name: "postgresql test",
image: "syncloud/platform-" + distro_default + "-" + arch + ":" + platform,
commands: [
"./postgresql/test.sh"
]
},
{
Expand Down
3 changes: 3 additions & 0 deletions bin/service.nats.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )
exec $DIR/nats/bin/nats.sh -c ${SNAP_DATA}/config/nats.conf
24 changes: 4 additions & 20 deletions bin/service.php-fpm.sh
Original file line number Diff line number Diff line change
@@ -1,21 +1,5 @@
#!/bin/bash

#!/bin/bash -e
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )

if [[ -z "$1" ]]; then
echo "usage $0 [start]"
exit 1
fi

case $1 in
start)
exec $DIR/php/bin/php-fpm.sh -y ${SNAP_DATA}/config/php-fpm.conf -c ${SNAP_DATA}/config/php.ini
;;
post-start)
timeout 5 /bin/bash -c 'until [ -S '${SNAP_COMMON}'/log/php5-fpm.sock ]; do echo "waiting for ${SNAP_COMMON}/log/php5-fpm.sock"; sleep 1; done'
;;
*)
echo "not valid command"
exit 1
;;
esac
exec $DIR/php/bin/php-fpm.sh \
-y ${SNAP_DATA}/config/php-fpm.conf \
-c ${SNAP_DATA}/config/php.ini
22 changes: 1 addition & 21 deletions bin/service.postgresql.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,5 @@

DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )

if [[ -z "$1" ]]; then
echo "usage $0 [start]"
exit 1
fi
# shellcheck source=config/env
. "${SNAP_DATA}/config/env"

case $1 in
start)
exec ${DIR}/postgresql/bin/pg_ctl.sh -w -s -D ${PSQL_DATABASE} start
;;
reload)
exec ${DIR}/postgresql/bin/pg_ctl.sh -s -D ${PSQL_DATABASE} reload
;;
stop)
exec ${DIR}/postgresql/bin/pg_ctl.sh -s -D ${PSQL_DATABASE} stop -m fast
;;
*)
echo "not valid command"
exit 1
;;
esac
exec ${DIR}/postgresql/bin/pg_ctl.sh -w -s -D ${PSQL_DATABASE} start
3 changes: 3 additions & 0 deletions bin/service.signaling.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )
exec $DIR/signaling/bin/signaling.sh -config ${SNAP_DATA}/config/signaling.conf
29 changes: 29 additions & 0 deletions config/nats.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# NATS Server Configuration for Nextcloud Signaling
# Unix socket for client connections
host: /var/snap/nextcloud/current/nats.sock
http_port: 8222

# Logging
debug: false
trace: false
logtime: true

# Authorization (optional, can be enabled for production)
# authorization {
# user: nats
# password: changeme
# }

# Cluster (optional, for high availability)
# cluster {
# port: 6222
# }

# Max connections
max_connections: 1000

# Max payload size (1MB)
max_payload: 1048576

# Write deadline for connections
write_deadline: "2s"
31 changes: 31 additions & 0 deletions config/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ http {
server unix:/var/snap/nextcloud/common/log/php5-fpm.sock;
}

upstream signaling {
server unix:/var/snap/nextcloud/current/signaling.sock;
}

map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}

# Set the `immutable` cache control options only for assets with a cache busting `v` argument
map $arg_v $asset_immutable {
"" "";
Expand Down Expand Up @@ -108,6 +117,28 @@ http {
# always provides the desired behaviour.
index index.php index.html /index.php$request_uri;

# Nextcloud Talk Signaling Server
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;
proxy_set_header X-Forwarded-Proto $scheme;
}

location /standalone-signaling/spreed {
proxy_pass http://signaling/spreed;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $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;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400;
}

# Rule borrowed from `.htaccess` to handle Microsoft DAV clients
location = / {
if ( $http_user_agent ~ ^DavClnt ) {
Expand Down
82 changes: 82 additions & 0 deletions config/signaling.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
[http]
# Path to Unix socket to listen on for HTTP requests
# Comment the "listen" line to disable the listener
listen = /var/snap/nextcloud/current/signaling.sock

[app]
# Set to "true" to enable debug logging
debug = false

# The NATS server URL (Unix socket)
natsurl = unix:///var/snap/nextcloud/current/nats.sock

[sessions]
# The hash key to use for session ids (32 bytes hex encoded)
# Can be generated with: openssl rand -hex 16
hashkey = {{ signaling_session_hashkey }}

# The block key to use for session data encryption (32 bytes hex encoded)
# Can be generated with: openssl rand -hex 16
blockkey = {{ signaling_session_blockkey }}

[clients]
# Shared secret for connections from internal clients
# Can be generated with: openssl rand -hex 16
internalsecret = {{ signaling_internal_secret }}

[backend]
# Comma-separated list of backend endpoints (e.g., Nextcloud instances)
# Leave empty to accept connections from all backends with valid secret
backends = backend1

# Shared secret for authenticating backend requests (same as in Nextcloud Talk settings)
# This secret needs to be configured in Nextcloud Talk admin settings
secret = {{ signaling_backend_secret }}

# Allow all backends (for testing only, not recommended for production)
allowall = false

# Maximum number of concurrent backend connections per host
connectionsperhost = 8

# Timeout for backend requests
timeout = 10s

[backend1]
url = https://localhost
secret = {{ signaling_backend_secret }}

[nats]
# URL of the NATS server (Unix socket)
url = unix:///var/snap/nextcloud/current/nats.sock

[mcu]
# Type of MCU to use (leave empty for none, set to "janus" for Janus gateway)
# type = janus

# URL of the Janus gateway WebSocket
# url = ws://localhost:8188

# Maximum bitrate for streams (in bits per second)
# maxstreambitrate = 1048576

# Maximum bitrate for screen sharing (in bits per second)
# maxscreenbitrate = 2097152

[turn]
# API key for TURN REST API (if using coturn with REST API)
# apikey =

# Shared secret for TURN REST API (if using coturn with REST API)
# secret =

# TURN server URLs (comma-separated)
# servers = turn:turn.example.com:3478?transport=udp,turn:turn.example.com:3478?transport=tcp

[geoip]
# Path to GeoIP2 database file (optional, for location-based server selection)
# license =

[stats]
# Set to "true" to enable statistics collection
enabled = false
39 changes: 39 additions & 0 deletions hooks/installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
from os.path import realpath

import logging
import os
import re
import secrets
import shutil
import uuid
from crontab import CronTab
Expand All @@ -30,6 +32,14 @@
SYSTEMD_PHP_FPM = '{0}.php-fpm'.format(APP_NAME)
SYSTEMD_POSTGRESQL = '{0}.postgresql'.format(APP_NAME)

SIGNALING_SECRETS_FILE = 'signaling.secrets'


def generate_hex_secret():
"""Generate a 16-byte hex-encoded secret (32 characters)."""
return secrets.token_hex(16)


class Installer:
def __init__(self):
if not logger.factory_instance:
Expand All @@ -47,6 +57,33 @@ def __init__(self):
self.cron = Cron(CRON_USER)
self.db = Database(self.app_dir, self.data_dir, self.config_dir, PSQL_PORT)
self.oc_config = OCConfig(join(self.app_dir, 'bin/nextcloud-config'))
self.signaling_secrets_path = join(self.data_dir, SIGNALING_SECRETS_FILE)

def get_signaling_secrets(self):
"""Get or create signaling server secrets."""
if isfile(self.signaling_secrets_path):
# Load existing secrets
secrets_dict = {}
with open(self.signaling_secrets_path, 'r') as f:
for line in f:
if '=' in line:
key, value = line.strip().split('=', 1)
secrets_dict[key] = value
return secrets_dict
else:
# Generate new secrets
secrets_dict = {
'signaling_session_hashkey': generate_hex_secret(),
'signaling_session_blockkey': generate_hex_secret(),
'signaling_internal_secret': generate_hex_secret(),
'signaling_backend_secret': generate_hex_secret()
}
# Save secrets to file
with open(self.signaling_secrets_path, 'w') as f:
for key, value in secrets_dict.items():
f.write('{0}={1}\n'.format(key, value))
os.chmod(self.signaling_secrets_path, 0o600)
return secrets_dict

def install_config(self):

Expand All @@ -55,6 +92,7 @@ def install_config(self):
storage.init_storage(APP_NAME, USER_NAME)
templates_path = join(self.app_dir, 'config')

signaling_secrets = self.get_signaling_secrets()
variables = {
'app_dir': self.app_dir,
'common_dir': self.common_dir,
Expand All @@ -64,6 +102,7 @@ def install_config(self):
'config_dir': self.config_dir,
'domain': urls.get_app_domain_name(APP_NAME)
}
variables.update(signaling_secrets)
gen.generate_files(templates_path, self.config_dir, variables)

fs.makepath(self.nextcloud_config_path)
Expand Down
Loading