From 62bebb6cbbebcc86f19a472fb716fa076b680d29 Mon Sep 17 00:00:00 2001 From: jnfrati Date: Fri, 9 Oct 2026 12:14:20 +0200 Subject: [PATCH] [relay] Align the UBI image with the shared UBI pattern Main now ships UBI variants of the client, combined server and proxy that share one license collector and one image layout, and the Red Hat certification workflow expects every certified image to carry both amd64 and arm64. The relay variant predated that, kept its own copy of the license script, built amd64 only, and ran as UID 65532 on the privileged default port :443, so it would not start under OpenShift or rootless Podman. Use release_files/collect-licenses.sh and build amd64 and arm64 like the other UBI images. Run as 1000:0 with a group-0 writable /var/lib/netbird for Let's Encrypt data, and default the listener to :8443 so an arbitrary non-root UID can bind it; the relay's Let's Encrypt flow uses TLS-ALPN on that same listener, so no separate challenge port is needed. --- .goreleaser.yaml | 4 +-- relay/Dockerfile.ubi | 26 +++++++++----- relay/collect-licenses.sh | 76 --------------------------------------- 3 files changed, 20 insertions(+), 86 deletions(-) delete mode 100644 relay/collect-licenses.sh diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 15ae9abc5..54f58cfc9 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -462,15 +462,15 @@ dockers_v2: dockerfile: relay/Dockerfile.ubi platforms: - linux/amd64 + - linux/arm64 build_args: VERSION: "{{ .Version }}" RELEASE: "{{ .Timestamp }}" hooks: pre: - - cmd: 'sh relay/collect-licenses.sh "{{ .ContextDir }}/licenses"' + - cmd: 'sh release_files/collect-licenses.sh -l relay/LICENSE "{{ .ContextDir }}/licenses" ./relay amd64 arm64' env: - GOOS=linux - - GOARCH=amd64 - CGO_ENABLED=0 labels: "org.opencontainers.image.created": "{{.Date}}" diff --git a/relay/Dockerfile.ubi b/relay/Dockerfile.ubi index 459fc5aac..86b0cbc01 100644 --- a/relay/Dockerfile.ubi +++ b/relay/Dockerfile.ubi @@ -9,15 +9,25 @@ LABEL name="netbird-relay" \ vendor="NetBird GmbH" \ version="${VERSION}" \ release="${RELEASE}" \ - summary="NetBird Relay server" \ - description="NetBird Relay carries traffic when a direct peer connection is unavailable." + summary="NetBird Relay" \ + description="NetBird Relay carries traffic between peers when a direct connection is unavailable." COPY --chmod=0555 ${TARGETPLATFORM}/netbird-relay /go/bin/netbird-relay -COPY licenses/AGPL-3.0.txt licenses/BSD-3-Clause.txt licenses/Go-LICENSE licenses/Go-PATENTS /licenses/ -COPY licenses/third_party/ /licenses/third_party/ -RUN chmod -R a+rX /licenses +COPY licenses/ /licenses/ +# Only the data directory shares the root group for arbitrary non-root UIDs. +# Runtime-created Let's Encrypt keys retain the application's restrictive modes. +RUN mkdir -p /var/lib/netbird && \ + chown 1000:0 /var/lib/netbird && \ + chmod 0770 /var/lib/netbird && \ + chmod -R a+rX /licenses -USER 65532 -STOPSIGNAL SIGTERM -ENTRYPOINT [ "/go/bin/netbird-relay" ] +USER 1000:0 +ENV HOME=/var/lib/netbird ENV NB_LOG_FILE=console +# Unprivileged port: runtimes such as OpenShift and Podman keep the kernel +# default that reserves ports below 1024 for root. 8443/udp carries QUIC and +# 9000 is the health probe. +ENV NB_LISTEN_ADDRESS=":8443" +EXPOSE 8443 8443/udp +STOPSIGNAL SIGTERM +ENTRYPOINT ["/go/bin/netbird-relay"] diff --git a/relay/collect-licenses.sh b/relay/collect-licenses.sh deleted file mode 100644 index d169c96c2..000000000 --- a/relay/collect-licenses.sh +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/sh -set -eu - -if [ "$#" -ne 1 ]; then - printf '%s\n' "usage: $0 OUTPUT_DIRECTORY" >&2 - exit 2 -fi - -repo_root=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd) -output_name=$(basename "$1") -case "$output_name" in - "" | . | .. | /) - printf '%s\n' "OUTPUT_DIRECTORY must name a directory" >&2 - exit 2 - ;; -esac -output_parent=$(CDPATH= cd -- "$(dirname "$1")" && pwd) -output="$output_parent/$output_name" -modules=$(mktemp "${TMPDIR:-/tmp}/netbird-relay-licenses.modules.XXXXXX") -sorted_modules=$(mktemp "${TMPDIR:-/tmp}/netbird-relay-licenses.sorted.XXXXXX") -trap 'rm -f "$modules" "$sorted_modules"' EXIT HUP INT TERM - -if [ -e "$output" ] || [ -L "$output" ]; then - printf 'output directory already exists: %s\n' "$output" >&2 - exit 1 -fi -mkdir "$output" -mkdir "$output/third_party" - -cp "$repo_root/relay/LICENSE" "$output/AGPL-3.0.txt" -cp "$repo_root/LICENSE" "$output/BSD-3-Clause.txt" - -cd "$repo_root" -GOOS=${GOOS:-linux} GOARCH=${GOARCH:-amd64} CGO_ENABLED=${CGO_ENABLED:-0} \ - go list -deps -f '{{with .Module}}{{if .Replace}}{{.Replace.Path}}{{"\t"}}{{.Replace.Version}}{{"\t"}}{{.Replace.Dir}}{{else}}{{.Path}}{{"\t"}}{{.Version}}{{"\t"}}{{.Dir}}{{end}}{{end}}' ./relay >"$modules" -LC_ALL=C sort -u "$modules" >"$sorted_modules" - -goroot=$(go env GOROOT) -for term in LICENSE PATENTS; do - if [ ! -f "$goroot/$term" ]; then - printf 'missing Go standard-library term: %s\n' "$goroot/$term" >&2 - exit 1 - fi - cp "$goroot/$term" "$output/Go-$term" -done - -while IFS=' ' read -r module version module_dir; do - [ -n "$module" ] || continue - [ "$module" = "github.com/netbirdio/netbird" ] && continue - - if [ -z "$version" ] || [ ! -d "$module_dir" ]; then - printf 'cannot collect terms for module %s at version %s\n' "$module" "$version" >&2 - exit 1 - fi - - destination="$output/third_party/$module/$version" - mkdir -p "$destination" - printf 'module: %s\nversion: %s\n' "$module" "$version" >"$destination/MODULE" - - found=false - for term in \ - "$module_dir"/LICENSE* "$module_dir"/License* "$module_dir"/license* \ - "$module_dir"/LICENCE* "$module_dir"/Licence* "$module_dir"/licence* \ - "$module_dir"/COPYING* "$module_dir"/Copying* "$module_dir"/copying* \ - "$module_dir"/NOTICE* "$module_dir"/Notice* "$module_dir"/notice* \ - "$module_dir"/PATENTS* "$module_dir"/Patents* "$module_dir"/patents*; do - [ -f "$term" ] || continue - cp "$term" "$destination/" - found=true - done - - if [ "$found" = false ]; then - printf 'no root license terms found for module %s at %s\n' "$module" "$module_dir" >&2 - exit 1 - fi -done <"$sorted_modules"