Skip to content

Commit

Permalink
Update Dockerfile and include cronjob
Browse files Browse the repository at this point in the history
including s6 overlay to docker image plus implementing the cronjob to
update certs in eturnal turn server. eturnal reloads certificates
without interrupting/closing existing sessions.
  • Loading branch information
Sando committed Sep 11, 2022
1 parent 751016c commit a2a1458
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 68 deletions.
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,8 @@ services:
restart: ${RESTART_POLICY:-unless-stopped}
ports:
- '${TURN_RELAY_MIN_PORT:-50000}-${TURN_RELAY_MAX_PORT:-50500}:${TURN_RELAY_MIN_PORT:-50000}-${TURN_RELAY_MAX_PORT:-50500}/udp'
security_opt:
- no-new-privileges:true
volumes:
- ${CONFIG}/eturnal:/opt/eturnal/etc:Z
- ${CONFIG}/web/acme-certs:/etc/eturnal/tls:Z
Expand Down
30 changes: 15 additions & 15 deletions eturnal/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ FROM debian:bullseye-slim as prepare
# BUILD: define image build arguments
ARG ETURNAL_VERSION=1.10.1
ARG TINI_VERSION=0.19.0
ARG S6_VERSION=v3.1.2.1

RUN set -x \
&& apt-get update && apt-get install curl -y \
&& apt-get update && apt-get install apt-transport-https apt-utils ca-certificates curl wget xz-utils -y \
# RUNTIME: install eturnal binary with installer
&& ARCH=$(uname -m | sed -e 's/x86_64/x64/;s/aarch64/arm64/;s/armv7l/arm/;s/s390x/s390x/;s/ppc64le/ppc64le/') \
&& curl -O https://eturnal.net/download/linux/installer/eturnal-$ETURNAL_VERSION-linux-$ARCH.run \
Expand All @@ -15,15 +16,16 @@ RUN set -x \
&& mkdir -p /rootfs/opt/eturnal/log /rootfs/opt/eturnal/run /rootfs/opt/eturnal/tls \
&& cp -r /opt/eturnal /rootfs/opt \
# RUNTIME: install runtime init
&& ARCH=$(uname -m | sed -e 's/x86_64/amd64/;s/aarch64/arm64/;s/armv7l/arm/;s/s390x/s390x/;s/ppc64le/ppc64le/') \
&& curl -fL -o /rootfs/tini https://github.com/krallin/tini/releases/download/v$TINI_VERSION/tini-$ARCH \
&& chmod +x /rootfs/tini
# RUNTIME: copy entrypoint script
&& ARCH=$(uname -m) \
&& wget -qO - https://github.com/just-containers/s6-overlay/releases/download/$S6_VERSION/s6-overlay-noarch.tar.xz | tar xfJ - -C /rootfs \
&& wget -qO - https://github.com/just-containers/s6-overlay/releases/download/$S6_VERSION/s6-overlay-$ARCH.tar.xz | tar xfJ - -C /rootfs
# RUNTIME: copy s6 scripts
COPY rootfs /rootfs

FROM busybox:stable-glibc AS eturnal
FROM gcr.io/distroless/base-debian11 AS eturnal
# BUILD: copy eturnal
COPY --from=prepare --chown=9000:9000 /rootfs /
COPY --from=busybox:stable-glibc /bin /bin
ARG HOME=/opt/eturnal

RUN set -x \
Expand All @@ -33,11 +35,8 @@ RUN set -x \
# RUNTIME: create symbolic links, entrypoint script and minimal configuration file
&& ln -s $HOME/bin/eturnalctl /usr/sbin/eturnalctl \
&& ln -s $HOME/bin/stun /usr/sbin/stun \
&& chmod +x /usr/sbin/*
&& chmod +x /etc/cont-init.d/* /etc/services.d/*/run

FROM gcr.io/distroless/base-debian11 AS cleanup
# BUILD: copy eturnal
COPY --from=eturnal --chown=9000:9000 / /
# remove libssl and openssl from distroless image
# as they are statically built within eturnal binary
RUN find -type f -name 'libcrypt*' -exec rm -rv {} + \
Expand All @@ -49,10 +48,11 @@ RUN find -type f -name 'libcrypt*' -exec rm -rv {} + \

FROM scratch AS runtime
# BUILD: copy eturnal
COPY --from=cleanup --chown=9000:9000 / /
COPY --from=eturnal / /
ARG HOME=/opt/eturnal
# RUNTIME: define container runtime environment variables
ENV ERL_DIST_PORT=3470 \
# RUNTIME: define environment variables
ENV S6_BEHAVIOUR_IF_STAGE2_FAILS=2 \
ERL_DIST_PORT=3470 \
PIPE_DIR=$HOME/run/pipe/ \
STUN_SERVICE="stun.conversations.im 3478"

Expand All @@ -61,5 +61,5 @@ WORKDIR $HOME
#USER eturnal
VOLUME ["$HOME"]
EXPOSE 3478 3478/udp
ENTRYPOINT ["/tini","--","run.sh"]
CMD ["eturnalctl", "foreground"]
ENTRYPOINT ["/init"]
#CMD ["eturnalctl", "foreground"]
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/sh
#!/command/with-contenv /bin/sh
# eturnal config
#DOCKER_INTERNAL_IP=$(cat /etc/hosts | grep $(hostname) | awk '{ print $1 }')
cat > /opt/eturnal/etc/eturnal.yml <<EOF
Expand All @@ -10,6 +10,10 @@ eturnal:
transport: auto
proxy_protocol: true

## TLS certificate/key files (must be readable by 'eturnal' user!):
#tls_crt_file: /opt/eturnal/tls/fullchain.pem
#tls_key_file: /opt/eturnal/tls/key.pem

## Reject TURN relaying from/to the following addresses/networks:
blacklist: # This is the default blacklist.
- "127.0.0.0/8" # IPv4 loopback.
Expand All @@ -32,71 +36,23 @@ eturnal:
# port: 8081 # This is the default.
# tls: false # This is the default.
# vm_metrics: true # This is the default.
EOF

# tls certificates
TLS_CERT_FILE=$(find /etc/ -name fullchain.pem)
TLS_KEY_FILE=$(find /etc/ -name key.pem)
if [ ! -z $TLS_CERT_FILE ] || [ ! -z $TLS_KEY_FILE ]; then
echo " ## TLS certificate/key files (must be readable by 'eturnal' user!):" >> /opt/eturnal/etc/eturnal.yml
if [ ! -z $TLS_CERT_FILE ]; then
cp -p $TLS_CERT_FILE /opt/eturnal/tls
echo " tls_crt_file: /opt/eturnal/tls/fullchain.pem" >> /opt/eturnal/etc/eturnal.yml
sed -i -e "s|#tls_crt_file:|tls_crt_file:|g" /opt/eturnal/etc/eturnal.yml
fi
if [ ! -z $TLS_KEY_FILE ]; then
cp -p $TLS_KEY_FILE /opt/eturnal/tls
echo " tls_key_file: /opt/eturnal/tls/key.pem" >> /opt/eturnal/etc/eturnal.yml
sed -i -e "s|#tls_key_file:|tls_key_file:|g" /opt/eturnal/etc/eturnal.yml
fi
chown 9000:9000 /opt/eturnal/tls/*
fi

# change file permissions
chown 9000:9000 /opt/eturnal/etc/eturnal.yml
chown -R 9000:9000 /opt/eturnal/etc
chmod 640 /opt/eturnal/etc/eturnal.yml
chown 9000:9000 /opt/eturnal/tls/*

# start certificate renewal cronjob
#if [ ! -z $TURNS_HOST ]
#then
# crond -b -d
#fi

# TURN credentials
if [ ! -z $TURN_CREDENTIALS ]
then
export ETURNAL_SECRET=$TURN_CREDENTIALS
fi

# TURN relay port range
if [ ! -z $TURN_RELAY_MIN_PORT ] || [ ! -z $TURN_RELAY_MAX_PORT ]
then
if [ ${TURN_RELAY_MIN_PORT-50000} \< ${TURN_RELAY_MAX_PORT-50500} ]
then
export ETURNAL_RELAY_MIN_PORT=${TURN_RELAY_MIN_PORT-50000}
export ETURNAL_RELAY_MAX_PORT=${TURN_RELAY_MAX_PORT-50500}
else
echo ""
echo " Configuration check:"
echo ""
echo " [WARNING] Defined TURN range minimum port -> ${TURN_RELAY_MIN_PORT-50000} is greater or equal than maximum port -> ${TURN_RELAY_MAX_PORT-50500}"
echo " [INFO] Starting eturnal with relay port range 50000 - 50500"
echo ""
export ETURNAL_RELAY_MIN_PORT=50000
export ETURNAL_RELAY_MAX_PORT=50500
fi
else
export ETURNAL_RELAY_MIN_PORT=50000
export ETURNAL_RELAY_MAX_PORT=50500
fi

# discover public IP addresses
if [ ! -z $DOCKER_HOST_ADDRESS ]
then
export ETURNAL_RELAY_IPV4_ADDR=$DOCKER_HOST_ADDRESS
else
if [ -z "$JVB_DISABLE_STUN" ]
then
export ETURNAL_RELAY_IPV4_ADDR=${ETURNAL_RELAY_IPV4_ADDR-$(stun -4 $STUN_SERVICE)}
fi
fi
exec "$@"
47 changes: 47 additions & 0 deletions eturnal/rootfs/etc/services.d/cron/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/command/with-contenv /bin/sh

# only run the script if TURNS is enabled (and if acme.sh is used in web container)
if [ ! -z $TURNS_HOST ] || ([ ! -z $TURNS_HOST ] && [ $ENABLE_LETSENCRYPT -eq 1 ]); then

while true; do
# sleep a sufficient time to give the web container's acme.sh script a chance to obtain certificates
sleep 60s

# mounted certs from web container
TLS_CERT_FILE=$(find /etc/ -name fullchain.pem)
TLS_KEY_FILE=$(find /etc/ -name key.pem)

# check if files have changed
if [ ! -z $TLS_CERT_FILE ] || [ ! -z $TLS_KEY_FILE ]; then
current=$(md5sum /opt/eturnal/tls/fullchain.pem | awk '{ print $1 }')
last_modified=$(md5sum $TLS_CERT_FILE | awk '{ print $1 }')

# copy certs to eturnal, adjust configuration file
if [ "$current" != "$last_modified" ]; then
echo " $(date) [Info] TLS certificates have been renewed, copy certs to eturnal and reload"

if [ ! -z $TLS_CERT_FILE ]; then
cp -p $TLS_CERT_FILE /opt/eturnal/tls
sed -i -e "s|#tls_crt_file:|tls_crt_file:|g" /opt/eturnal/etc/eturnal.yml
fi

if [ ! -z $TLS_KEY_FILE ]; then
cp -p $TLS_KEY_FILE /opt/eturnal/tls
sed -i -e "s|#tls_key_file:|tls_key_file:|g" /opt/eturnal/etc/eturnal.yml
fi

# fix ownership and reload the service (reloading eturnal does not stop/break any active sessions)
chown 9000:9000 /opt/eturnal/tls/*
eturnalctl reload

else
echo " $(date) [Info] CronJob: TLS certificates have not been renewed, check again in 5 minutes"
fi
sleep 240s
fi
done

# don't repeatedly run the cron job, if eturnal does not serve TURNS
else
s6-svc -O /var/run/s6/legacy-services/cron
fi
43 changes: 43 additions & 0 deletions eturnal/rootfs/etc/services.d/eturnal/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/command/with-contenv /bin/sh

# TURN credentials
if [ ! -z $TURN_CREDENTIALS ]
then
export ETURNAL_SECRET=$TURN_CREDENTIALS
fi

# TURN relay port range
if [ ! -z $TURN_RELAY_MIN_PORT ] || [ ! -z $TURN_RELAY_MAX_PORT ]
then
if [ ${TURN_RELAY_MIN_PORT-50000} \< ${TURN_RELAY_MAX_PORT-50500} ]
then
export ETURNAL_RELAY_MIN_PORT=${TURN_RELAY_MIN_PORT-50000}
export ETURNAL_RELAY_MAX_PORT=${TURN_RELAY_MAX_PORT-50500}
else
echo ""
echo " $(date) [INFO] Configuration check:"
echo ""
echo " $(date) [WARNING] Defined TURN range minimum port -> ${TURN_RELAY_MIN_PORT-50000} is greater or equal than maximum port -> ${TURN_RELAY_MAX_PORT-50500}"
echo " $(date) [INFO] Starting eturnal with relay port range 50000 - 50500"
echo ""
export ETURNAL_RELAY_MIN_PORT=50000
export ETURNAL_RELAY_MAX_PORT=50500
fi
else
export ETURNAL_RELAY_MIN_PORT=50000
export ETURNAL_RELAY_MAX_PORT=50500
fi

# discover public IP addresses
if [ ! -z $DOCKER_HOST_ADDRESS ]
then
export ETURNAL_RELAY_IPV4_ADDR=$DOCKER_HOST_ADDRESS
else
if [ -z "$JVB_DISABLE_STUN" ]
then
export ETURNAL_RELAY_IPV4_ADDR=${ETURNAL_RELAY_IPV4_ADDR-$(stun -4 $STUN_SERVICE)}
export ETURNAL_RELAY_IPV6_ADDR=${ETURNAL_RELAY_IPV6_ADDR-$(stun -6 $STUN_SERVICE)}
fi
fi

exec eturnalctl foreground

0 comments on commit a2a1458

Please sign in to comment.