369 lines
10 KiB
Markdown
369 lines
10 KiB
Markdown
# Skald installation instructions
|
||
|
||
## Basic installation
|
||
|
||
### Build the Skald binary
|
||
|
||
Say:
|
||
|
||
```sh
|
||
CGO_ENABLED=0 go build -ldflags='-s -w'
|
||
```
|
||
|
||
On Windows, say:
|
||
|
||
```dosbat
|
||
set CGO_ENABLED=0
|
||
go build -ldflags="-s -w"
|
||
```
|
||
|
||
If your server has a different architecture than the machine on which you
|
||
are building, set the `GOOS` and `GOARCH` environment variables. For
|
||
example, in order to compile for a 64-bit ARM system (a Raspberry Pi or an
|
||
Olimex board, for example), you would say:
|
||
|
||
```sh
|
||
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags='-s -w'
|
||
```
|
||
|
||
### Deploy to your server
|
||
|
||
The following instructions assume that your server is called
|
||
`skald.example.org` and that you have already created a dedicated user
|
||
called `skald`.
|
||
|
||
First, make sure that the `halls` and `data` directories exist:
|
||
|
||
```sh
|
||
mkdir halls data
|
||
```
|
||
|
||
Now copy the `skald` binary, and the directories `static`, `data` and
|
||
`halls` to the server:
|
||
|
||
```sh
|
||
rsync -a skald static data halls skald@skald.example.org:
|
||
```
|
||
|
||
If you don't have a TLS certificate, Skald will generate a self-signed
|
||
certificate (and print a warning to the logs). If you have a certificate,
|
||
install it in the files `data/cert.pem` and `data/key.pem`:
|
||
|
||
```sh
|
||
ssh skald@skald.example.org
|
||
sudo cp /etc/letsencrypt/live/skald.example.org/fullchain.pem data/cert.pem
|
||
sudo cp /etc/letsencrypt/live/skald.example.org/privkey.pem data/key.pem
|
||
sudo chown skald:skald data/*.pem
|
||
chmod go-rw data/key.pem
|
||
```
|
||
|
||
Since certificates are regularly rotated, this should be done in a monthly
|
||
cron job or a systemd timer unit.
|
||
|
||
### Run Skald on the server
|
||
|
||
Arrange to run the binary on the server. If you never reboot your server,
|
||
just do:
|
||
|
||
```sh
|
||
ssh skald@skald.example.org
|
||
ulimit -n 65536
|
||
nohup ./skald &
|
||
```
|
||
|
||
If you are using *runit*, use a script like the following:
|
||
|
||
```sh
|
||
#!/bin/sh
|
||
exec 2>&1
|
||
cd ~skald
|
||
ulimit -n 65536
|
||
exec setuidgid skald ./skald
|
||
```
|
||
|
||
If you are using *SystemD*, put the following in
|
||
`/etc/systemd/system/skald.service` (and then run `systemctl daemon-reload`):
|
||
|
||
```ini
|
||
[Unit]
|
||
Description=Skald
|
||
After=network.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
WorkingDirectory=/home/skald
|
||
User=skald
|
||
Group=skald
|
||
ExecStart=/home/skald/skald
|
||
LimitNOFILE=65536
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
```
|
||
|
||
### Set up skaldctl
|
||
|
||
The `skaldctl` utility administers a Skald instance by editing its JSON files
|
||
locally. Run it on the server as a user that may write the Skald `data/` and
|
||
`halls/` directories. It does not connect to Skald over HTTPS.
|
||
|
||
Build the `skaldctl` utility, and copy it somewhere on your path:
|
||
|
||
```sh
|
||
cd skaldctl
|
||
go build -ldflags='-s -w'
|
||
sudo cp skaldctl /usr/local/bin/
|
||
```
|
||
|
||
Create the initial server configuration file:
|
||
|
||
```sh
|
||
skaldctl initial-setup
|
||
```
|
||
|
||
If Skald uses directories other than `./data` and `./halls`, pass them before
|
||
the command name. For example, packages that use `/var/lib/skald` can be
|
||
administered with:
|
||
|
||
```sh
|
||
sudo -u skald skaldctl -data /var/lib/skald/data -halls /var/lib/skald/halls initial-setup
|
||
```
|
||
|
||
### Hall setup
|
||
|
||
For a guided setup, create a hall interactively:
|
||
|
||
```sh
|
||
skaldctl create-hall -interactive
|
||
```
|
||
|
||
This asks for the hall name, common hall settings, operator accounts, and an
|
||
optional shared participant password. To create a minimal hall without
|
||
prompts, use:
|
||
|
||
```sh
|
||
skaldctl create-hall -hall city-watch
|
||
```
|
||
|
||
Create an "op", a user with hall moderation privileges:
|
||
|
||
```sh
|
||
skaldctl create-user -hall city-watch -user Username -permissions op
|
||
```
|
||
|
||
Set the new user's password:
|
||
|
||
```sh
|
||
skaldctl set-password -hall city-watch -user Username
|
||
```
|
||
|
||
You should now be able to test your Skald installation by pointing a web
|
||
browser at <https://skald.example.org:8443/hall/city-watch/>.
|
||
|
||
Create an ordinary user:
|
||
|
||
```sh
|
||
skaldctl create-user -hall city-watch -user Participant
|
||
skaldctl set-password -hall city-watch -user Participant
|
||
```
|
||
|
||
Check the results:
|
||
|
||
```sh
|
||
skaldctl list-halls
|
||
skaldctl list-users -l -hall city-watch
|
||
```
|
||
|
||
Type `skaldctl -help`, `skaldctl create-hall -help`, etc. for more
|
||
information.
|
||
|
||
### Recording dependency
|
||
|
||
Skald recordings are single mixed Ogg Opus audio files. Recording requires
|
||
`ffmpeg` on the server:
|
||
|
||
```sh
|
||
ffmpeg -version
|
||
```
|
||
|
||
If `ffmpeg` is missing or cannot be started, Skald reports a recording error
|
||
to the operator instead of creating a partial recording.
|
||
|
||
## Advanced configuration
|
||
|
||
Skald is designed to be exposed directly to the Internet. If your server
|
||
is behind a firewall or NAT router, some extra configuration is necessary.
|
||
|
||
### Running behind a firewall
|
||
|
||
If your server is behind a firewall but has a global IPv4 address (it is
|
||
not behind NAT), then, at the very minimum, the firewall must allow
|
||
incoming connections to:
|
||
|
||
* TCP port 8443 (or whatever is configured with the `-http` option); and
|
||
|
||
* TCP and UDP port 1194 (or whatever is configured with the `-turn` option).
|
||
|
||
For good performance, your firewall should allow incoming and outgoing
|
||
traffic from the UDP ports used for media transfer. By default, these are
|
||
all high-numbered (ephemeral) ports, but they can be restricted using one
|
||
of the following options:
|
||
|
||
* the `-udp-range port1-port2` option restricts the UDP ports to be in
|
||
the range from port1 to port2 inclusive; this should be a large range,
|
||
on the order of a few tens of thousands of ports;
|
||
|
||
* the `-udp-range port` option makes the server use just a single port,
|
||
and demultiplex the traffic in userspace.
|
||
|
||
At the time of writing, this mechanism is not quite complete, and you will
|
||
see Skald attempting to use other ports. Unless you see connection
|
||
failures, this is nothing to worry about.
|
||
|
||
### Running behind NAT
|
||
|
||
If your server is behind NAT, then currently the only option is to use
|
||
a STUN, or, preferably, TURN server on a separate host, one that is not
|
||
behind NAT. See Section *Connectivity issues and ICE servers* below.
|
||
|
||
Skald has some support for running behind NAT without a helpful server,
|
||
but this has not been exhaustively tested. Please see the section
|
||
"Connectivity issues and ICE servers" below.
|
||
|
||
### Running behind a reverse proxy
|
||
|
||
Skald is designed to be directly exposed to the Internet. In order to
|
||
run Skald behind a reverse proxy, you might need to make a number of
|
||
tweaks to your configuration.
|
||
|
||
First, you might need to inform Skald of the URL at which users connect
|
||
(the reverse proxy's URL) by adding an entry `proxyURL` to your
|
||
`data/config.json` file:
|
||
|
||
```json
|
||
{
|
||
"proxyURL": "https://skald.example.org/"
|
||
}
|
||
```
|
||
|
||
Second, and depending on your proxy implementation, you might need to
|
||
proxy normal Skald paths such as `/hall/` and `/skald-api/`, and pass
|
||
WebSocket handshakes to the URL at `ws`; for example, with Nginx, you will
|
||
need to say something like the following:
|
||
|
||
```
|
||
location /hall/ {
|
||
proxy_pass https://localhost:8443/hall/;
|
||
proxy_set_header Host $http_host;
|
||
}
|
||
|
||
location /skald-api/ {
|
||
proxy_pass https://localhost:8443/skald-api/;
|
||
proxy_set_header Host $http_host;
|
||
}
|
||
|
||
location /ws {
|
||
proxy_pass https://localhost:8443/ws;
|
||
proxy_set_header Upgrade $http_upgrade;
|
||
proxy_set_header Connection "Upgrade";
|
||
proxy_set_header Host $http_host;
|
||
}
|
||
```
|
||
|
||
Finally, in order to avoid TLS termination issues, you may want to run
|
||
Skald over plain HTTP instead of HTTPS by using the command-line flag
|
||
`-insecure`.
|
||
|
||
Note that even if you're using a reverse proxy, clients will attempt to
|
||
establish direct UDP flows with Skald and direct TCP connections to
|
||
Skald's TURN server; see the section *Configuring your firewall*
|
||
above.
|
||
|
||
## Connectivity issues and ICE servers
|
||
|
||
Most connectivity issues are due to an incorrect ICE configuration.
|
||
|
||
ICE is the NAT and firewall traversal protocol used by WebRTC. ICE can
|
||
make use of two kinds of servers to help with NAT traversal: STUN servers,
|
||
that help punching holes in well-behaved NATs, and TURN servers, that
|
||
serve as relays for traffic. TURN is a superset of STUN: no STUN server
|
||
is necessary if one or more TURN servers are available.
|
||
|
||
Skald includes an IPv4-only TURN server, which is controlled by the
|
||
`-turn` command-line option. It has the following behaviour:
|
||
|
||
* if its value is set to the empty string `""`, then the built-in server
|
||
is disabled; in this case, the file `data/ice-servers.json` configures
|
||
an external TURN server;
|
||
|
||
* if its value is a colon followed with a port number, for example
|
||
`:1194`, then the TURN server will listen on all public IPv4 addresses
|
||
of the local host, over UDP and TCP; this is the recommended value if
|
||
the server is not behind NAT, and the firewall allows incoming
|
||
connections to the TURN port.
|
||
|
||
* if the value of this option is a socket address, such as
|
||
`203.0.113.1:1194`, then the TURN server will listen on all addresses
|
||
of the local host but assume that the address seen by the clients is
|
||
the one given in the option; this may be useful when running behind NAT
|
||
with port forwarding set up.
|
||
|
||
* the default value is `auto`, which behaves like `:1194` if there is no
|
||
`data/ice-servers.json` file, and like `""` otherwise.
|
||
|
||
If the server is not accessible from the Internet, e.g. because of NAT or
|
||
because it is behind a restrictive firewall, then you should configure
|
||
a TURN server that runs on a host that is accessible by both Skald and
|
||
the clients. Disable the built-in TURN server (`-turn ""` or the default
|
||
`-turn auto`), and provide a working ICE configuration in the file
|
||
`data/ice-servers.json`. In the case of a single STUN server, it should
|
||
look like this:
|
||
|
||
```json
|
||
[
|
||
{
|
||
"urls": [
|
||
"stun:stun.example.org"
|
||
]
|
||
}
|
||
]
|
||
```
|
||
|
||
In the case of a single TURN server, the `ice-servers.json` file should
|
||
look like this:
|
||
|
||
```json
|
||
[
|
||
{
|
||
"urls": [
|
||
"turn:turn.example.org:443",
|
||
"turn:turn.example.org:443?transport=tcp"
|
||
],
|
||
"username": "skald",
|
||
"credential": "secret"
|
||
}
|
||
]
|
||
```
|
||
|
||
It is more secure to use coturn's `use-auth-secret` option. If you do
|
||
that, then the `ice-servers.json` file should look like this:
|
||
|
||
```json
|
||
[
|
||
{
|
||
"urls": [
|
||
"turn:turn.example.org:443",
|
||
"turn:turn.example.org:443?transport=tcp"
|
||
],
|
||
"username": "skald",
|
||
"credential": "secret",
|
||
"credentialType": "hmac-sha1"
|
||
}
|
||
]
|
||
```
|
||
|
||
For redundancy, you may set up multiple TURN servers, and ICE will use the
|
||
first one that works. If an `ice-servers.json` file is present and
|
||
Skald's built-in TURN server is enabled, then the external server will be
|
||
used in preference to the built-in server.
|