Container image for eturnal STUN/TURN Server
View Sourceeturnal container images are available for multiple
architectures as ghcr.io/processone/eturnal from GitHub Packages
or DockerHub.
Starting from releases newer than 1.12.1 container images are built using
the glibc based binaries and Wolfi OS. The
Alpine Linux based images are still available, but
have a tag suffix -alpine, i.e. ghcr.io/processone/eturnal:latest-alpine.
Tags and variants
XX.YY.ZZ represents the official eturnal release, a -AA suffix the image
version of a particular release in case of any bug fix etc. of the image.
| Tags | Description | Additional notes |
|---|---|---|
edge | Built from master branch, see changelog | For testing purposes. |
1.12.2, latest | Release changelog | |
1.12.2-acme, acme | As the standalone image, but including the acme.sh | Variant specific documentation |
Images are scanned daily by Trivy and,
if necessary, the latest release will be rebuilt and updated.
Getting started
Note: the below commands can be run with podman as well, just use podman as an equivalent: alias docker=podman
To pull the image:
docker pull ghcr.io/processone/eturnal:latest
This will run a container named eturnal with the default, unprivileged user
eturnal (uid=9000) in foreground mode with default ports published, if
started this way:
docker run -d --rm \
--name eturnal \
-p 3478:3478 \
-p 3478:3478/udp \
-p 49152-65535:49152-65535/udp \
ghcr.io/processone/eturnal:latest
Recommended: The container can also run in a less privileged mode:
docker run -d --rm \
--name eturnal \
--read-only \
--cap-drop=ALL \
--security-opt no-new-privileges \
-p 3478:3478 \
-p 3478:3478/udp \
-p 49152-65535:49152-65535/udp \
ghcr.io/processone/eturnal:latest
Note: Stating
--cap-add=NET_BIND_SERVICEmay be needed here depending on the container runtime, see e.g. Docker
Only relevant for Docker, not Podman: Since Docker does not perform well with large port ranges, consider decreasing the TURN default port range, e.g. through environment variables:
docker run -d --rm \
--name eturnal \
--read-only \
--cap-drop=ALL \
--security-opt no-new-privileges \
-p 3478:3478 \
-p 3478:3478/udp \
-p 50000-50500:50000-50500/udp \
-e ETURNAL_RELAY_MIN_PORT=50000 \
-e ETURNAL_RELAY_MAX_PORT=50500 \
ghcr.io/processone/eturnal:latest
Or use the host network by adding
--network=host to the command line:
docker run -d --rm \
--name eturnal \
--read-only \
--cap-drop=ALL \
--security-opt no-new-privileges \
--network=host \
ghcr.io/processone/eturnal:latest
Note: The container is no longer isolated from the host network when using this option.
Inspect the running container with:
docker logs eturnal
To use the eturnalctl command, e.g. just
run:
docker exec eturnal eturnalctl info
Stop the running container with:
docker stop eturnal
Configuration
Configuration is mainly done by a mounted eturnal.yml file (recommended), see
the example configuration file.
The file must be readable by the eturnal user (e.g. chown 9000:9000 and
chmod 640). Mountpath, e.g. with docker run add:
-v /path/to/eturnal.yml:/etc/eturnal.yml:ro
eturnal may also be configured by specifying certain environment variables, see the documentation. Here are some more hints how to configure eturnal.
General hints:
For logs to be printed with the
docker logscommand,log_dir:should be set tostdoutineturnal.yml.The container attempts to autodetect the
relay_ipv4_addressandrelay_ipv6_addressusing an external STUN service.- This STUN service may be exchanged by defining a different external STUN
service with the
STUN_SERVICEenvironment variable, which defaults to:STUN_SERVICE="stun.conversations.im 3478". Note: the stun client only supports UDP queries. - If that fails, consider defining the
relay_ipv4_address(andrelay_ipv6_address) either within a mountedeturnal.ymlfile or with theETURNAL_RELAY_IPV4_ADDR(andETURNAL_RELAY_IPV6_ADDR) environment variable to enable the TURN service. Note: the IPv6 address is optional. - If the external STUN lookup is not desired, define the environment variable
STUN_SERVICE=falsein thedocker runcommand.
- This STUN service may be exchanged by defining a different external STUN
service with the
If eturnal shall bind to privileged ports (<1024) directly, there are two ways to accomplish that:
The eturnal container has the capability
NET_BIND_SERVICEincluded and the option--security-opt no-new-privilegesis not set, since the unprivileged container usereturnalneeds to escalateNET_BIND_SERVICE.You enable binding to privileged ports system-wide through defining the lowest port:
sysctl net.ipv4.ip_unprivileged_port_start=80This also works in kubernetes.
Hint: Newer Docker versions set this option during install already.
Note: All variables can be defined as secrets with a __FILE suffix:
printf "secret" | podman secret create eturnal_secret -
podman run \
... \
--secret eturnal_secret \
-e ETURNAL_SECRET__FILE='/run/secrets/eturnal_secret' \
ghcr.io/processone/eturnal:latest
Custom TLS certificates and dh-parameter file
To use eturnal's TLS listener with cutsom TLS certificates/dh-parameter files
they must be mounted into the container and referenced
in the eturnal.yml file. TLS certificates and the dh-parameter file shall be
.pem files. They must be readable by the eturnal user/group and should not
have world-readable access rights (e.g. chown 9000:9000 and chmod 440).
Mountpath, e.g. with docker run add:
-v /path/to/tls-files:/opt/eturnal/tls:ro
Rootless environments:
- If eturnal runs in rootless environments, e.g.
podman rootless, then file permissions and editing files must be performed within the same user namespace as the container runs in. More information here. - The "magic" command in e.g.
podman rootlessis called podman unshare. - To change e.g. the file permissions for
eturnal.ymluse:
podman unshare chown 9000:9000 /path/to/eturnal.yml
podman unshare chmod 640 /path/to/eturnal.yml
Deployment examples
This repository also contains configuration examples for:
Building yourself
Instructions can be found here.