2020-05-29 17:49:23 +02:00
|
|
|
|
# Installation
|
|
|
|
|
|
2020-09-24 19:08:25 +02:00
|
|
|
|
## Build the server binary
|
2020-04-29 18:31:54 +02:00
|
|
|
|
|
|
|
|
|
CGO_ENABLED=0 go build -ldflags='-s -w'
|
|
|
|
|
|
2020-09-24 19:08:25 +02:00
|
|
|
|
## Create a server certificate
|
2020-04-29 18:31:54 +02:00
|
|
|
|
|
2020-05-03 15:09:02 +02:00
|
|
|
|
mkdir data
|
2020-04-29 18:31:54 +02:00
|
|
|
|
openssl req -newkey rsa:2048 -nodes -keyout data/key.pem -x509 -days 365 -out data/cert.pem
|
|
|
|
|
|
2020-09-24 19:08:25 +02:00
|
|
|
|
## Set the server administrator credentials
|
|
|
|
|
|
|
|
|
|
This step is optional.
|
2020-04-29 18:31:54 +02:00
|
|
|
|
|
|
|
|
|
echo 'god:topsecret' > data/passwd
|
|
|
|
|
|
2020-09-24 19:08:25 +02:00
|
|
|
|
## Set up a TURN server
|
|
|
|
|
|
2020-11-09 00:23:44 +01:00
|
|
|
|
This step depends on your network setup and your user population. If your
|
|
|
|
|
server is accessible from the Internet (no firewall or NAT) and none of
|
|
|
|
|
your users are behind restrictive firewalls, then no ICE servers are
|
|
|
|
|
necessary. If your server is behind a NAT, a STUN server is required. If
|
|
|
|
|
any of your users are behind restrictive firewalls (which is usually the
|
|
|
|
|
case of Academic and Enterprise networks), then you will need a TURN
|
|
|
|
|
server running on an innocent-looking TCP port. This is the recommended
|
|
|
|
|
setup.
|
|
|
|
|
|
|
|
|
|
You should probably be running your own TURN server — I use *coturn*. The
|
|
|
|
|
address of the TURN server is configured in the file `data/ice-servers.json`.
|
|
|
|
|
It should look like this:
|
|
|
|
|
|
|
|
|
|
[
|
|
|
|
|
{
|
|
|
|
|
"urls":["turn:turn.example.com:443"],
|
|
|
|
|
"username":"username",
|
|
|
|
|
"credential":"password"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"urls":["turn:turn.example.com:443?transport=tcp"],
|
|
|
|
|
"username":"username",
|
|
|
|
|
"credential":"password"
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
The port number, username and password should be the same as the ones in
|
|
|
|
|
your TURN server's configuration.
|
2020-04-29 18:31:54 +02:00
|
|
|
|
|
2020-09-24 19:08:25 +02:00
|
|
|
|
## Set up a group
|
|
|
|
|
|
|
|
|
|
A group is set up by creating a file `groups/name.json`. The available
|
|
|
|
|
options are described below.
|
2020-04-29 18:31:54 +02:00
|
|
|
|
|
|
|
|
|
mkdir groups
|
|
|
|
|
vi groups/public.json
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
"public":true,
|
|
|
|
|
"op":[{"username":"jch","password":"1234"}],
|
|
|
|
|
"presenter":[{}],
|
|
|
|
|
"max-users":100
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-24 19:08:25 +02:00
|
|
|
|
## Copy the necessary files to your server:
|
|
|
|
|
|
|
|
|
|
Assuming you have set up a user *sfu*:
|
2020-04-29 18:31:54 +02:00
|
|
|
|
|
2020-09-24 23:21:05 +02:00
|
|
|
|
rsync -a sfu static data groups sfu@server.example.org:
|
2020-04-29 18:31:54 +02:00
|
|
|
|
|
2020-09-24 19:08:25 +02:00
|
|
|
|
## Run the server binary:
|
2020-04-29 18:31:54 +02:00
|
|
|
|
|
2020-09-24 19:08:25 +02:00
|
|
|
|
ssh sfu@server.example.org
|
2020-04-29 18:31:54 +02:00
|
|
|
|
nohup ./sfu &
|
|
|
|
|
|
2020-09-24 19:08:25 +02:00
|
|
|
|
If you are using *runit*, use a script like the following:
|
|
|
|
|
|
|
|
|
|
#!/bin/sh
|
|
|
|
|
exec 2>&1
|
|
|
|
|
cd ~sfu
|
|
|
|
|
exec setuidgid sfu ./sfu
|
|
|
|
|
|
|
|
|
|
If you are using *systemd*, use `Type=simple` in your service file.
|
2020-05-29 17:49:23 +02:00
|
|
|
|
|
2020-05-31 23:16:08 +02:00
|
|
|
|
# Locations
|
|
|
|
|
|
|
|
|
|
There is a landing page at the root of the server. It contains a form
|
|
|
|
|
for typing the name of a group, and a clickable list of public groups.
|
|
|
|
|
|
|
|
|
|
Groups are available under `/group/groupname`. You may share this URL
|
|
|
|
|
with others, there is no need to go through the landing page.
|
|
|
|
|
|
|
|
|
|
Recordings can be accessed under `/recordings/groupname`. This is only
|
|
|
|
|
available to the administrator of the group.
|
|
|
|
|
|
|
|
|
|
Some statistics are available under `/stats`. This is only available to
|
|
|
|
|
the server administrator.
|
|
|
|
|
|
|
|
|
|
|
2020-05-29 17:49:23 +02:00
|
|
|
|
# Group definitions
|
|
|
|
|
|
|
|
|
|
Groups are defined by files in the directory defined by the `-groups`
|
|
|
|
|
command-line option, one per group. The group definition file does not
|
|
|
|
|
contain the name of the group -- that makes it possible to set up a new
|
|
|
|
|
group just by copying a template file.
|
|
|
|
|
|
|
|
|
|
The group definition file contains a JSON directory with the following
|
|
|
|
|
fields, all of which are optional.
|
|
|
|
|
|
|
|
|
|
- `op`, `presenter`, `other`: each of these is an array of user
|
|
|
|
|
definitions (see below) and specifies the users allowed to connect
|
|
|
|
|
respectively with operator privileges, with presenter privileges, and
|
|
|
|
|
as passive listeners;
|
2020-05-30 01:18:00 +02:00
|
|
|
|
- `public`: if true, then the group is visible on the landing page;
|
2020-09-24 22:03:41 +02:00
|
|
|
|
- `description`: a human-readable description of the group; this is
|
|
|
|
|
displayed on the landing page for public groups;
|
2020-05-29 17:49:23 +02:00
|
|
|
|
- `max-clients`: the maximum number of clients that may join the group at
|
|
|
|
|
a time;
|
2020-10-08 14:38:33 +02:00
|
|
|
|
- `max-history-age`: the time, in seconds, during which chat history is
|
|
|
|
|
kept (default 14400, i.e. 4 hours);
|
2020-05-30 01:18:00 +02:00
|
|
|
|
- `allow-recording`: if true, then recording is allowed in this group;
|
2020-10-08 15:18:22 +02:00
|
|
|
|
- `allow-anonymous`: if true, then users may connect with an empty username.
|
2020-11-22 19:54:54 +01:00
|
|
|
|
- `allow-subgroups`: if true, then subgroups of the form `group/subgroup`
|
|
|
|
|
are automatically created when accessed.
|
2020-09-10 13:55:57 +02:00
|
|
|
|
- `redirect`: if set, then attempts to join the group will be redirected
|
|
|
|
|
to the given URL; most other fields are ignored in this case.
|
2020-05-29 17:49:23 +02:00
|
|
|
|
|
|
|
|
|
A user definition is a dictionary with the following fields:
|
|
|
|
|
|
|
|
|
|
- `username`: the username of the user; if omitted, any username is
|
|
|
|
|
allowed;
|
|
|
|
|
- `password`: the password of the user; if omitted, then any password
|
|
|
|
|
(including the empty paassword) is allowed.
|
|
|
|
|
|
|
|
|
|
For example
|
|
|
|
|
|
2020-05-31 23:16:08 +02:00
|
|
|
|
{"username":"jch", "password":"topsecret"}
|
2020-05-29 17:49:23 +02:00
|
|
|
|
|
|
|
|
|
specifies user *jch* with password *topsecret*, while
|
|
|
|
|
|
|
|
|
|
{"password":"topsecret"}
|
|
|
|
|
|
|
|
|
|
specifies that any username will do. The empty dictionary
|
|
|
|
|
|
|
|
|
|
{}
|
|
|
|
|
|
2020-09-24 19:08:25 +02:00
|
|
|
|
specifies that any username will do and that passwords are not verified.
|
2020-05-29 17:49:23 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Commands
|
|
|
|
|
|
|
|
|
|
Typing a line starting with a slash `/` in the chat dialogue causes
|
2020-11-24 15:04:23 +01:00
|
|
|
|
a command to be sent to the server. Type `/help` to get the list of
|
|
|
|
|
available commands; the output depends on whether you are an operator or
|
|
|
|
|
not.
|
2020-05-29 17:49:23 +02:00
|
|
|
|
|
|
|
|
|
--- Juliusz Chroboczek <https://www.irif.fr/~jch/>
|