processone / eturnal

STUN / TURN standalone server
https://eturnal.net
Apache License 2.0
237 stars 22 forks source link

update docker image to alpine 3.18 #42

Closed szaimen closed 1 year ago

szaimen commented 1 year ago

Hi,

I just discovered your project today and it looks great!

However for security reasons I need an eturnal image based on alpine 3.18. Would you mind updating that?

Thanks a lot! :)

Zoey2936 commented 1 year ago

Maybe you could use tools like renovate/dependabot to keep the alpine version up-to-date

sando38 commented 1 year ago

Hi @szaimen

Thanks for your interest and suggestion.

It is in progress. We currently refactor the Docker image. The source code is in this fork and currently reviewed. https://github.com/sando38/eturnal/pkgs/container/eturnal

You could use the image ghcr.io/sando38/eturnal:edge for now until we have released the new eturnal vsn.

~# docker run --rm ghcr.io/sando38/eturnal:edge cat /etc/alpine-release
Unable to find image 'ghcr.io/sando38/eturnal:edge' locally
edge: Pulling from sando38/eturnal
35c4a8d5816f: Pull complete 
0b0d4f1fcb24: Pull complete 
4f4fb700ef54: Pull complete 
Digest: sha256:b9af9761cea8f53b8551c446926b575027408f5dcba30469954a22e5f60bf14e
Status: Downloaded newer image for ghcr.io/sando38/eturnal:edge
3.18.2

BTW: the vulnerabilities detected for ghcr.io/processone/eturnal:1.10.1 by e.g. trivy do not affect eturnal, as eturnal does not use the functions marked vulnerable. :)

Zoey2936 commented 1 year ago

You could use the image ghcr.io/sando38/eturnal:edge for now until we have released the new eturnal vsn.

I think we need tagged releases, when it is done we try to switch from coturn to eturnal because the image seems to be much smaller and szaimen found that eturnal is easier to configure (I hope eturnal will work)

BTW: the vulnerabilities detected for ghcr.io/processone/eturnal:1.10.1 by e.g. trivy do not affect eturnal, as eturnal does not use the functions marked vulnerable. :)

Even if this sounds very good, we want to use the eturnal image as base and integrate other software into it (janus-gateway/nats and more) and some of them don't exist in alpine v3.16 or still have CVEs or are outdated

It is in progress. We currently refactor the Docker image. The source code is in this fork and currently reviewed. https://github.com/sando38/eturnal/pkgs/container/eturnal

Is there a way to help?

And one question from me, is eturnal a static binary file/multiple static binarys or does this it consists of librarys and many small files to run it?

sando38 commented 1 year ago

I think we need tagged releases, when it is done we try to switch from coturn to eturnal because the image seems to be much smaller and szaimen found that eturnal is easier to configure (I hope eturnal will work)

I rebuild the eturnal image in the fork. So you can pull ghcr.io/sando38/eturnal:1.10.1. It is, however, alpine 3.17.4:

~# docker run --rm ghcr.io/sando38/eturnal:1.10.1 cat /etc/alpine-release
Unable to find image 'ghcr.io/sando38/eturnal:1.10.1' locally
1.10.1: Pulling from sando38/eturnal
8f1d01595b84: Pull complete 
da83b7d41ada: Pull complete 
4f4fb700ef54: Pull complete 
Digest: sha256:e0452d3f331d015c3cde1c0c7175c3c50fa9baa123c146ea008736960226542a
Status: Downloaded newer image for ghcr.io/sando38/eturnal:1.10.1
3.17.4

Even if this sounds very good, we want to use the eturnal image as base and integrate other software into it (janus-gateway/nats and more) and some of them don't exist in alpine v3.16 or still have CVEs or are outdated

gotcha ;)

One remark here: Our eturnal image is be completely stripped, meaning it does not contain any package manager anymore, so you can't run apk add <package-name>. Will provide you a possible solution below though.

Is there a way to help?

thanks for the offer, basically, it is all done. Just some scripts need a review. The image itself will not have any significant changes.

And one question from me, is eturnal a static binary file/multiple static binarys or does this it consists of librarys and many small files to run it?

It is basically the second: "it consists of librarys and many small files to run it". That is "erlang style". In the container image, but also in general, we package all relevant parts in /opt/eturnal. We have even two variants:

You want to use the static for your custom/ build-on-top approach when using alpine 3.18 as your base, as our prod image is still based on alpine 3.17.4. The following example Dockerfile would provide a running eturnal container image which you can extend to your needs:

FROM ghcr.io/sando38/eturnal:1.10.1-otp-25 AS eturnal

FROM docker.io/library/alpine:3.18 AS build
RUN apk add tini --no-cache

COPY --from=eturnal --chown=9000:9000 /opt/eturnal /opt/eturnal
COPY --from=eturnal /usr/local/bin/* /usr/local/bin/

RUN addgroup eturnal -g 9000 \
    && adduser -s /sbin/nologin -D -u 9000 -h /opt/eturnal -G eturnal eturnal

ENV ERL_DIST_PORT='3470' \
    PIPE_DIR="/$HOME/run/pipe/" \
    STUN_SERVICE='stun.conversations.im 3478'

USER eturnal

ENTRYPOINT ["/sbin/tini","--"]
CMD ["eturnalctl", "foreground"]
sando38 commented 1 year ago

And an example Dockerfile with alpine 3.17 and the prod variant:

FROM ghcr.io/sando38/eturnal:1.10.1 AS eturnal

FROM docker.io/library/alpine:3.17 AS build
RUN apk add --no-cache \
      libcap \
      libstdc++ \
      ncurses-libs \
      tini \
      yaml \
      zlib 

COPY --from=eturnal --chown=9000:9000 /opt/eturnal /opt/eturnal
COPY --from=eturnal /usr/local/bin/* /usr/local/bin/

RUN addgroup eturnal -g 9000 \
    && adduser -s /sbin/nologin -D -u 9000 -h /opt/eturnal -G eturnal eturnal

ENV ERL_DIST_PORT='3470' \
    PIPE_DIR="/$HOME/run/pipe/" \
    STUN_SERVICE='stun.conversations.im 3478'

USER eturnal

ENTRYPOINT ["/sbin/tini","--"]
CMD ["eturnalctl", "foreground"]
sando38 commented 1 year ago

In case of any further questions, let me know.

P.S. tini is not an actual dependency, however, it improves signal handling for eturnal and we recommend to not run eturnal as pid 1.

Zoey2936 commented 1 year ago

eturnel would be launched by supervisor, is tini still recommended?

Zoey2936 commented 1 year ago

@szaimen can I create a PR containing etrunal in talk, so that sando can maybe check if that would work?

sando38 commented 1 year ago

eturnel would be launched by supervisor, is tini still recommended?

No, supervisor is fine! No tini needed in that case.

Zoey2936 commented 1 year ago

to your example:

FROM ghcr.io/sando38/eturnal:1.10.1-otp-25 AS eturnal # what does -otp-25 mean? and does a similar tag already exist in the official ghcr repo?

FROM docker.io/library/alpine:3.18 AS build
RUN apk add tini --no-cache

COPY --from=eturnal --chown=9000:9000 /opt/eturnal /opt/eturnal # I think the uid/gid can be changed, right?
COPY --from=eturnal /usr/local/bin/* /usr/local/bin/ # does this folder only contain eturnal files? or could there be also system bin files?

RUN addgroup eturnal -g 9000 \
    && adduser -s /sbin/nologin -D -u 9000 -h /opt/eturnal -G eturnal eturnal # can be any user, right?

ENV ERL_DIST_PORT='3470' \ # what does this do?
    PIPE_DIR="/$HOME/run/pipe/" \ # what does this do?
    STUN_SERVICE='stun.conversations.im 3478' # what does this do?

USER eturnal # can be any user, right?

ENTRYPOINT ["/sbin/tini","--"]
CMD ["eturnalctl", "foreground"] # how to specify the path of the config file/what is the default location?
sando38 commented 1 year ago

what does -otp-25 mean? and does a similar tag already exist in the official ghcr repo?

this suffix means, that the image contains our binary (static) release. That tag is new and will be official with the next release. If the suffix changes due to our review, I will let you know. OTP-25 specifically means, that eturnal is compiled using erlang/otp vsn 25. That is somehow related to this feature #29, which is in work currently.

I think the uid/gid can be changed, right?

yes, that can be changed, it must match however the UID/GID of the eturnal user

does this folder only contain eturnal files? or could there be also system bin files?

in our image only eturnal related files, namely:

to be sure, you can do:

COPY --from=eturnal /usr/local/bin/eturnalctl /usr/local/bin/eturnalctl
COPY --from=eturnal /usr/local/bin/stun /usr/local/bin/stun

can be any user, right?

eturnal looks for user named eturnal, so a user named eturnal is needed in /etc/passwd. The actual name can be configured, but that is only possible during build.

ERL_DIST_PORT='3470' \ # what does this do?

This tells eturnal to not start epmd, which is the "erlang port mapper daemon". The eturnalctl cmd uses the defined port 3470 to talk to the eturnal process. It can be any port, e.g. 12345 or whatever. More here.

PIPE_DIR="/$HOME/run/pipe/" \ # what does this do?

It tells eturnal to use that directory for pid files, if you start eturnal as a background process (daemon). You will not want that with supervisor, so you can drop that variable.

STUN_SERVICE='stun.conversations.im 3478' # what does this do?

see here: https://github.com/processone/eturnal/tree/master/docker-k8s#general-hints

USER eturnal # can be any user, right?

yes.

how to specify the path of the config file/what is the default location?

eturnal looks first for a config file at /etc/eturnal.yml, after that in /opt/eturnal/etc/eturnal.yml. If you want a different location, you must specify ETURNAL_ETC_PREFIX.

Zoey2936 commented 1 year ago

eturnal looks for user named eturnal, so a user named eturnal is needed in /etc/passwd. The actual name can be configured, but that is only possible during build.

the user of our image currently is called "talk" and should have the uid/gid 1000, so that will not work?

Zoey2936 commented 1 year ago

see here: https://github.com/processone/eturnal/tree/master/docker-k8s#general-hints

so relay_ipv4_address is the external ip of the server running eturnal? and will eturnal start without this env?

This tells eturnal to not start epmd, which is the "erlang port mapper daemon". The eturnalctl cmd uses the defined port 3470 to talk to the eturnal process. It can be any port, e.g. 12345 or whatever. More here.

so it can be left empty?

sando38 commented 1 year ago

eturnal looks for user named eturnal, so a user named eturnal is needed in /etc/passwd. The actual name can be configured, but that is only possible during build.

the user of our image currently is called "talk" and should have the uid/gid 1000, so that will not work?

This works:

FROM ghcr.io/sando38/eturnal:1.10.1-otp-25 AS eturnal

FROM docker.io/library/alpine:3.18 AS build
RUN apk add tini --no-cache

COPY --from=eturnal --chown=9000:9000 /opt/eturnal /opt/eturnal
COPY --from=eturnal /usr/local/bin/eturnalctl /usr/local/bin/eturnalctl
COPY --from=eturnal /usr/local/bin/stun /usr/local/bin/stun

RUN addgroup eturnal -g 9000 \
    && adduser -s /sbin/nologin -D -u 9000 -h /opt/eturnal -G eturnal eturnal

RUN addgroup talk -g 1000 \
    && adduser -s /sbin/nologin -D -u 1000 -G talk talk

ENV ERL_DIST_PORT='3470' \
    STUN_SERVICE='stun.conversations.im 3478'

USER talk

ENTRYPOINT ["/sbin/tini","--"]
CMD ["eturnalctl", "foreground"]
Zoey2936 commented 1 year ago

so the user needs to exist even if it is not used?

sando38 commented 1 year ago

see here: https://github.com/processone/eturnal/tree/master/docker-k8s#general-hints

so relay_ipv4_address is the external ip of the server running eturnal? and will eturnal start without this env?

eturnal will start without it, but TURN will only be enabled, if there is an IPv4 address defined, see here. We use the STUN_SERVICE for convenience, but if it is preferred to configure it in the eturnal.yml configuration file, that would work as well of course.

This tells eturnal to not start epmd, which is the "erlang port mapper daemon". The eturnalctl cmd uses the defined port 3470 to talk to the eturnal process. It can be any port, e.g. 12345 or whatever. More here.

so it can be left empty?

Yes, it can be left empty. In that case I suggest to leave the variable entirely away from the Dockerfile.

sando38 commented 1 year ago

so the user needs to exist even if it is not used?

yes :) , although it is not entirely true, that is isn't used. The eturnalctl script sus eturnal (or the user name, defined during eturnal build)

Zoey2936 commented 1 year ago

do you think this could work? https://github.com/nextcloud/all-in-one/pull/2855/files (also the config) but thank for your help!

sando38 commented 1 year ago

do you think this could work? https://github.com/nextcloud/all-in-one/pull/2855/files (also the config) but thank for your help!

I would change, as you use the configuration file for the relay IP address:

COPY --from=eturnal /usr/local/bin/eturnalctl /usr/local/bin/eturnalctl
COPY --from=eturnal /usr/local/bin/stun /usr/local/bin/stun

to

RUN ln -s $(find /opt/eturnal -name eturnalctl) /usr/local/bin/eturnalctl ; \
         ln -s $(find /opt/eturnal -name stun) /usr/local/bin/stun

Of course you can embody it in your main RUN cmd

sando38 commented 1 year ago

Regarding the configuration:

Zoey2936 commented 1 year ago

I removed it

sando38 commented 1 year ago

I would give it a try as it is configured now.

sando38 commented 1 year ago

The Dockerfile now uses erlang/otp vsn 26.0.2 as base image, which is based upon alpine 3.18.