View Source Container image for eturnal STUN/TURN Server

eturnal container images are available for multiple architectures as ghcr.io/processone/eturnal from GitHub Packages or DockerHub. The images are based on Alpine Linux.

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.

TagsDescriptionAdditional notes
edgeBuilt from master branch, see changelogFor testing purposes.
1.12.1, latestRelease changelog
1.12.1-acme, acmeAs the standalone image, but including the acme.shVariant 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_SERVICE may 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 logs command, log_dir: should be set to stdout in eturnal.yml.

  • The container attempts to autodetect the relay_ipv4_address and relay_ipv6_address using an external STUN service.

    • This STUN service may be exchanged by defining a different external STUN service with the STUN_SERVICE environment 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 (and relay_ipv6_address) either within a mounted eturnal.yml file or with the ETURNAL_RELAY_IPV4_ADDR (and ETURNAL_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=false in the docker run command.
  • If eturnal shall bind to privileged ports (<1024) directly, there are two ways to accomplish that:

    • The eturnal container has the capability NET_BIND_SERVICE included and the option --security-opt no-new-privileges is not set, since the unprivileged container user eturnal needs to escalate NET_BIND_SERVICE.

    • You enable binding to privileged ports system-wide through defining the lowest port:

      sysctl net.ipv4.ip_unprivileged_port_start=80

      This 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 rootless is called podman unshare.
  • To change e.g. the file permissions for eturnal.yml use:
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.